Java Black Book
Java Black Book
Table of Contents
Chapter 11 - Security
Chapter 12 - Internationalization
Appendix A - Development Tools
Appendix B - References
Appendix C - The Java Virtual Machine
Appendix D - Active RFCs
Index
List of Figures
List of Tables
List of Listings
-1 -
Team-Fly®
Java 2 Core Language Little Black Book Press Information
Alain Trottier
Al Williams
CORIOLIS
President and CEO
Roland Elgey
Publisher
Al Valvano
Associate Publisher
Katherine R. Hartlove
Acquisitions Editor
Jawahara Saidullah
Development Editor
Jessica Choi
Product Marketing Manager
Jeff Johnson
Project Editor
Sally M. Scott
Technical Reviewer
Sumit Pal
Production Coordinator
Peggy Cantrell
Cover Designer
Laura Wellander
This book may not be duplicated in any way without the express written consent of the publisher,
except in the form of brief excerpts or quotations for the purposes of review. The information
contained herein is for the personal use of the reader and may not be incorporated in any
commercial programs, other books, databases, or any kind of software without written consent of
the publisher. Making copies of this book or any portion for any purpose other than your own is a
violation of United States copyright laws.
The author and publisher of this book have used their best efforts in preparing the book and the
programs contained in it. These efforts include the development, research, and testing of the
theories and programs to determine their effectiveness. The author and publisher make no
-2 -
Java 2 Core Language Little Black Book Press Information
warranty of any kind, expressed or implied, with regard to these programs or the documentation
contained in this book.
The author and publisher shall not be liable in the event of incidental or consequential damages
in connection with, or arising out of, the furnishing, performance, or use of the programs,
associated instructions, and/or claims of productivity gains.
Trademarks
Trademarked names appear throughout this book. Rather than list the names and entities that
own the trademarks or insert a trademark symbol with each mention of the trademarked name,
the publisher states that it is using the names for editorial purposes only and to the benefit of the
trademark owner, with no intention of infringing upon that trademark.
Trottier, Alain
Java 2 core language little black book/by Alain Trottier and Al Williams.
p. cm.
Includes index.
1-932111-66-2
10 9 8 7 6 5 4 3 2 1
This book is dedicated to my wife, Patricia, the love of my life, and to my son, Devyn, who has
brought us tremendous joy.
— Alain Trottier
— Al Williams
About the Authors
-3 -
Java 2 Core Language Little Black Book Press Information
Alain Trottier observes the dot-com warfare of Southern California from his vantage point as an
independent consultant (Trottier Technologies) and Adjunct Professor at Vanguard University of
Southern California. He has been in the tech sector for two decades, wearing many hats such as
technologist, customer -support provider, programmer, architect, manager, and director. He has
worked in a wide range of environments such as the U.S. Navy, Chevron's research center, and
Adforce. His experience includes methodical, exacting research as well as code -til -ya-drop
Internet, pre-IPO, ventures.
He is as fascinated by people as he is by the IT trenches they inhabit. His Microsoft and Sun
certifications are balanced by his Bachelor's and Master's degrees in religion. Alain would be
delighted to hear from readers who have requests or comments; he can be reached at
http://www.inforobo.com/javacorelanguage .
Al Williams is a long-time consultant and author. His articles have appeared regularly in
magazines such as Web Techniques , Dr. Dobb's , Visual Developer, and many others. He's the
author of more than a dozen books on programming and computers, including MFC Black Book
and Java 2 Network Protocol Black Book (both from The Coriolis Group). Al's programming
career has seen him programming in Fortran, C, C++, and— more recently— Java. Al's consulting
projects have included aerospace projects, chemical production software, a nd many embedded
systems. He also teaches programming courses across the United States.
When Al's not working (which isn't often), he enjoys tinkering with amateur radio projects,
watching or reading science fiction, and maintaining a few personal Web sites. He lives near
Houston, Texas, with his wife, Pat, and a varying number of kids, dogs, and cats.
Acknowledgments
I would like to thank Jawahara Saidullah, Acquisitions Editor, and Chris Van Buren, agent at
Waterside, who made this book possible. Thank you also to Jessica Choi, Development Editor,
for your valuable guidance. Thank you, Sally Scott, Project Editor, and your team, for all the
detailed work you do. Every book purchase is a nod to your effectiveness.
— Alain Trottier
Producing a book is a lot of work. Sure, writing is hard, but that's just the tip of the iceberg.
Behind the scenes, a lot of people do most of the real work— the proofreading, the typesetting,
the layout, the indexing, and all the other details that it takes to transform some ran dom typing in
Microsoft Word into the book you're holding in your hands.
To that end, I'd like to thank Sally Scott, Project Editor; Peggy Cantrell, Production Coordinator;
Catherine Oliver, Copyeditor; Sumit Pal, Technical Reviewer; Christine Sherk, Proofreader;
William Hartman, Compositor; Christina Palaia, Indexer; and Laura Wellander, Cover Designer.
I'd also like to thank Jawahara Saidullah, Acquisitions Editor, for bringing me in to join the team
that produced this book.
-4 -
Java 2 Core Language Little Black Book Press Information
My thanks also go to Alain Trottier for all of his example code and other material. There's an old
saying that two workers make twice the work, but fortunately, in this case, it cut the work in half,
as it should.
Some of the material in this book appeared in a different format in my Java@Work column in
Web Techniques magazine and appears with permission. Thanks to Amit Asaravala at Web
Techniques for his continuing support and friendship.
I couldn't even start to tackle projects of this size and scope without the support of my family. My
wife, Pat, and kids Jerid, Amy, and Patrick all have to put up with me seeming to live in my office,
but they never complain (well— almost, never). Thanks guys! Oh, and if you've read this
far— thanks to you, for taking the time to read about all of these people who are important to me.
— Al Williams
-5 -
Java 2 Core Language Little Black Book Introduction
Introduction
Suppose you wanted to take up painting. You can learn about painting, basically, in one of two ways.
First, you can make a study of painting and spend a lot of time reading and thinking about c olors,
lighting, and perspective. Eventually, you could make some simple sketches— maybe just some
geometrical shapes— and tentatively try to paint them. After a great deal of study and effort, you might
even be able to produce something you might be able to sell.
The second way is to buy a paint-by-number set. You've seen these, of course. You get a canvas with
all the areas of the painting already marked and numbered. All you have to do is fill in the areas with
paint from the little numbered tins, and you have a masterpiece.
Programming is a lot like painting. You can spend years training and planning and writing small
tentative programs. Or you can use wizards and example code; essentially, this is a
program -by-number. In this book, you'll find a hybrid a pproach that bridges these two philosophies.
Modern tools and the Internet have made it very easy for people to create programs without having a
real understanding of the details. This is especially true with graphical user interface builders that
automatically write all but the small details of your application. On the other hand, most of us need
professional results now . We don't want to spend years honing skills; instead, we need to produce
results today.
We wrote this book to provide you with plenty of cut-and-paste examples, and also to explain the
reasoning behind them. This lets you find a balance between your need to get things done and your
need to understand why and how things work.
You'll find that this book focuses on the Java language and its core libraries. While many books jump
into graphical programming, this book focuses on non-graphical, text -based programs. Why?
Because graphics programming techniques can obscure the fundamental Java tasks you need to
understand. And also, setting up user interface screens is one place where the "paint-by-number"
tools are something you probably will use. It is better that you have a firm grasp of the underlying Java
language and calls. Even the most sophisticated graphics program uses the same core language
techniques that this book illustrates.
Some of the book's sample code also comes from a working online service, the engine behind Words
Count, a Writing Analysis Tool at http://wordscount.ezpublishing.com. This is because there is no
tougher test for code than placing it in production— if you miss something, customers will howl. Using
the unforgiving production test, as a result, keeps the material practical, and we wanted to give you
something more than academic code to study.
-6 -
Java 2 Core Language Little Black Book Introduction
In short, if you want to learn about the core Java language and libraries— in settings as diverse as
Internet access, security, and XML — then this book is for you. If you've been using a
"paint- by-numbers" tool and you want to increase your understanding of what's going on behind the
scenes, you'll find that this book will help you fill in the gaps. If you are an experienced developer
looking for quick code examples for database code, network servers, and other topics covered in this
book, you'll find the Little Black Book format fast and useful.
§ Examples of major language features, including arrays, exceptions, casting, and more.
§ Object and package examples that show you how to get the most from the class system.
§ Examples of using vectors, arrays, and other data structures to store and manipulate data
efficiently.
§ File and stream handling examples. These programs show you a variety of ways to deal
with files and also illustrate how to apply the techniques to any data source, not just files.
§ E xamples that use JDBC (Java DataBase Connectivity) for database access. You can use
JDBC to access a variety of SQL databases.
§ Programs that act as Internet clients and servers, including programs that extract data from
Web pages. These examples also show techniques used with network sockets and
streams.
§ Programs that use multiple threads to execute several tasks at once, which can provide
better performance for programs that can benefit from multitasking.
§ Examples that serialize objects to persistent storage and later restore them. You can use
these techniques to save and restore data or transmit data across a network.
§ Encryption, key generation, and digital signature examples. Encryption is necessary for
many e-commerce and communications programs.
-7 -
Java 2 Core Language Little Black Book Introduction
If you haven't already installed Sun's free Software Development Kit (SDK) for Java, start with
Chapter 1. Although you can use other products (like VisualAge or JBuilder), you'll get more of a
low-level view with the SDK. The experience you gain will directly apply to writing programs using
these more sophisticated tools. If you insist on using some other tool, be sure to avoid or disable as
much of the automatic code generation as you can because, like painting by number, this hides much
of what is really happening at the code level. Also, be sure your tool is using the 1.4 version of the
Java 2 SDK.
This book uses version 1.4 of the Java 2 SDK, Standard Edition— the latest version of the language.
Although many of the topics will still be useful if you use a different version, some of the exam ples
might require modification if you aren't using the same version that we use in this book.
After Chapter 1 , you can decide which approach you want to take. If you are already familiar with
Java's syntax and semantics, you might just randomly thumb through the chapters starting with
Chapter 5 until you find topics that interest you. Although some of the examples in these chapters
assume familiarity with earlier chapters, if you are comfortable with Java you shouldn't have much
trouble picking out what you need. If you are just starting with Java, or if you've been using tools that
hide a lot of detail from you, or even if you just want a refresher course, pay special attention to
Chapters 2, 3, and 4 . These core concepts are not glamorous, but they are the foundation that all
programs require. You can't build a castle on a shaky foundation, and you can't write a great Java
program without understanding why and how things work in Java (including the class system). Once
you are comfortable with these chapters, you can pursue the more advanced chapters that appear
later in the book.
Written by experienced professionals, Coriolis Little Black Books are terse, easily "thumb-able"
question-answerers and problem solvers. The Little Black Book's uniq ue two-part chapter
format— brief technical overviews followed by practical immediate solutions — is structured to help you
use your knowledge, solve problems, and quickly master complex technical issues to become an
expert. By breaking down complex topics into easily manageable components, this format helps you
quickly find what you need with the code you need to make it happen.
We welcome your feedback on this book. You can email us at The Coriolis Group at
[email protected].
-8 -
Java 2 Core Language Little Black Book Chapter 1: Getting Started with Java
In Brief
This book focuses on the core Java language, an easy-to-learn, yet powerful, programming language.
The book will teach you what you need to know in order to produce full-featured software products
based on Java. It concentrates on the core language, the use of which involves much more than
understanding a list of simple keywords and syntax. Knowing how to use a language well requires
more than the ability to spell correctly; the nuances come, instead, from word combinations. Java and
English are similar in that they both have syntax, grammars, rules, and conventions — the core of any
language.
You can divide Java into two main parts. The first part (the Java Virtual Machine) executes Java
programs. The second part (the Software Development Kit) is the set of tools used to develop Java
programs.
For execution, you need a compiled program and a Java Virtual Machine (JVM), which serves as the
intermediary between your program and the host computer. The JVM provides cross-platform
portability because your program will work on any JVM regardless of the operating system or
hardware involved. Of course, there are different versions (or editions) of the JVM, so in practice
some programs will require specific JVM versions. However, the idea is that one Java program can
run on many JVMs regardless of the operating system or computer hardware involved.
Note Sun (and Sun-approved vendors) give away a JVM with every major operating
system. Of course, your users' machines need a JVM, but many new PCs,
servers, and even handheld devices already have one installed. If not, Sun
allows you to redistribute the user portion of Java with your product.
For development, you need only a text editor and the basic Java tools that Sun provides for free.
There are fancier tools available— some for free.
This chapter will introduce the Java architecture, providing you with the background information you'll
need in order to better understand what you're doing in later chapters. This chapter will also teach you
how to enter code, compile it, and then run it on a JVM.
Java Editions
Sun uses a peculiar naming scheme to differentiate different versions of Java. First, Sun generates an
abstract specification that defines what Java is. This is known as the platform. Major specification
changes would require a change in platform. Then, a particular version of Java might target a different
type of application (for example, a desktop computer or a handheld computer). These different types
are known as editions. Finally, each specific implementation of an edition on the platform has a
version number and is known as a Java SDK (Software Development Kit; formerly known as the Java
Development Kit or JDK).
-9 -
Java 2 Core Language Little Black Book Chapter 1: Getting Started with Java
Tip For a good glossary, see "Unraveling Java Terminology," by Dana Nourie, at
http://www.developer.java.sun.com/developer/onlineTraining/new2java/programming/learn/unravelingjava.html .
Sun has three editions of Java for a given platform or version (the current platform is Java 2). The
editions for the current platform are:
§ J2ME (Micro Edition)— Used to create programs that run on small handheld devices, such
as phones, PDAs (personal digital assistants), and appliances.
§ J2SE (Standard Edition)— Used primarily to create programs for desktop computers or for
any computer too large for J2ME and too small for J2EE.
§ J2EE (Enterprise Edition)— Used to create very large programs that run on servers
managing heavy traffic and complicated transactions. These programs are the backbone of
many online services, such as banking, e-commerce, and B2B (business-to-business)
trading systems.
Each edition has different capabilities. It's important for you to know the differences among the
editions because they affect your projects. Many programmers start with J2SE and intend to jump to
J2EE later. The advantage of this approach is that the development team can get up to speed on Java
technology with J2SE, which is not as complex as J2EE. The disadvantage is that the team will face a
major conversion to move to J2EE. In addition, equipping a team for J2EE can be significantly more
expensive than equipping a team for J2SE. The SDK is free, but you'll probably want a server
machine in addition to workstations— not to mention database software and multiple clients for testing.
There is a world of difference between writing and testing code snippets on a standalone machine and
stress-testing the whole product on a true enterprise system that involves multiple servers, clients,
and middleware.Therefore, if you have J2SE v1.3, you know that it is the Java SDK version 1.3,
targeting desktop computers (Standard Edition) and that it is based on the Java 2 platform
(specification). Presumably in the future there will be a Java 3 and even additional editions (unless
Sun changes the naming scheme again).
For each Java edition, Sun gives away a Software Development Kit (SDK), which has everything you
need to compile and test programs. Most of the code in this book was developed with the J2SE SDK.
Be warned that the programs you compile for one edition will often not work for the other two editions.
J2SE compiled programs will work on J2EE because J2EE is a true superset of J2SE. J2EE
programs that use special J2EE features won't work with J2SE, however. Nor will J2SE or J2EE
programs run on J2ME, since the JVMs are quite different between the two editions.
The SDK is a development environment for building programs using the Java programming language;
the SDK includes everything you need to develop and test programs. The tools include command-line
programs (which were used, incidentally, to develop the samples for this book). Although these tools
do not provide a graphical user interface (GUI), using them is a good way to learn the Java language.
-1 0 -
Java 2 Core Language Little Black Book Chapter 1: Getting Started with Java
Besides, if you understand how the core tools work, you'll have no problems using one of the many
integrated development environments (IDEs) available.
Tip You can download the current release of the Java 2 SDK, Standard Edition from
http://www.java.sun.com.
The SDK provides many tools, the three most important of which are:
§ The compiler— The compiler converts the human-readable source file into
platform-independent code that a JVM interprets. This code is called bytecode .
§ The runtime system— The SDK includes a JVM that allows you to run Java programs
and test your programs. The runtime system also includes a command-line debugger
that you can use to monitor your program's execution.
§ The source code— Sun provides quite a bit of source code for the Java libraries that
form part of the JVM. You shouldn't change this code directly. Thanks to object
orientation, however, you can modify these classes by making new classes that
extend the existing ones. Examining the source code is often helpful in understanding
how a class works. Y
FL
If you are familiar with other programming languages, you might wonder about linking. A C program,
AM
for example, is not only compiled but also linked with other library modules to form an executable
program. This linking is not necessary (or even possible) in Java. The JVM dynamically searches for
and loads library modules as the prog ram needs them. This dynamic loading is a crucial capability.
TE
For example, a Java program embedded in a Web browser can load modules over the Internet. The
browser does not need to know anything about the modules at compile time. The linkage is handled
completely at run time.
Java is the first truly useful portable language. The JVM architecture offers you several advantages:
cross-platform portability, size, and security.
Cross-Platform Portability
The JVM provides cross-platform portability. You write code for the JVM, not for the operating system
(OS). Because all JVMs look the same to Java programs, you have to write only one version of your
program, and it will work on all JVMs. The JVM interprets the byte-code and carries out the program's
operations in a way that is compatible with the current hardware architecture and operating system.
-1 1-
Team-Fly®
Java 2 Core Language Little Black Book Chapter 1: Getting Started with Java
Size
The second interesting side effect of using JVM architecture is the small size of its compiled code.
Most of the functionality is buried in the JVM, so the compiled code that runs on top of it doesn't need
to be loaded with large libraries. Of course, the JVM is, among other things, a large library, but it is
shared among all Java programs. That means that a Java program can be quite small— at least, the
part of the program that is uniquely yours. All Java programs share the large JVM, but presumably it is
already on the target machine. This is especially important when users are downloading programs
over the Internet, for example. Of course, if users' computers don't have a JVM, they'll have a large
download for installing the JVM on their machines first. After the JVM installs, the users won't have to
worry about installing again.
Security
Java has been designed to protect users from malicious programs. Programs from an untrusted
source (for example, the Internet) execute in a restricted environment (known as a sandbox). The
JVM can then prevent those programs from causing mischief. For example, a Java applet (a small
program that runs on a Web page) usually can't access local files or open network connections to
arbitrary computers. These restrictions prevent a Web page from erasing your critical files or sending
threatening email from your computer.
Software has to manage many types of data, including numbers, dates, currencies, and letters. There
are several numeric data types and two character data types, among others. Whereas the decimal
number system is universal, alphabets vary considerably. What do you do if you want to name a
variable using Cyrillic letters, for example? To accommodate these variations, Java uses the Unicode
character set.
At the basic level, computers only crunch numbers. When it comes to character data, the computer
assigns a number for each letter. Because computers need to communicate with each other, there
should be a standard way to map characters to numbers. For years, the two predominant standards
were ASCII (the American Standard Code for Information Interchange) and EBCDIC (Extended
Binary Coded Decimal Interchange Code). Both of these used 8 -bit numbers to represent common
characters used in the United States.
With only 8 bits, these character sets can handle only 256 unique characters (including spaces and
control characters). However, this capability is not adequate for truly international programs that might
encounter languages using a variety of alphabets, such as Farsi or Cyrillic.
To deal with these problems, a new standard emerged: Unicode (see http://www.unicode.org).
Unicode uses 16-bit (or even 32 -bit) characters that allow it to represent a large number of symbols.
The 32 -bit Unicode system (with 4.3 billion characters) can handle all known languages, including the
huge Asian character sets, and still leave room for growth. There are even Unicode characters for
-12 -
Java 2 Core Language Little Black Book Chapter 1: Getting Started with Java
dead languages such as Sanskrit. Unicode is used by Java, as well as by XML, ECMAScript
(JavaScript), and many others. It is also used by most modern operating systems and We b browsers.
That means you can write programs that deal with international character sets. This Unicode support
is provided throughout Java. Not only can your programs handle user input and output in Unicode, but
the programs themselves are written using Unicode. You can name variables and functions using any
character set you can represent.
If you are an American used to dealing with ASCII, don't worry. It just so happens that the first 256
characters of the Unicode set correspond to those in the ASCII character set. Programs like the Java
compiler can recognize ASCII files, so you can write programs with any text editor. A special encoding
(known as Unicode Transformational Format, or UTF) allows you to specify extended characters in an
ASCII file so you can take advantage of Unicode even if you don't have a Unicode-aware text editor.
Java Tools
Many tool vendors provide additional tools for Java (some free and some for a price). Because the
SDK is command -line oriented, it's no surprise that tool vendors sell IDEs (integrated development
environments) that enable you to edit and compile code from a GUI, improving productivity. Even Sun
has a GUI IDE: Forte. You can download a free version of Forte or buy a version with additional
features.
Note You can read more about tools in Appendix A. For now, just understand that,
although these tools can improve productivity, they are not generally discussed
in this book. Once you are comfortable with the basic Java system, you'll be
able to use any IDE with ease.
Several good editors are on the market. IBM provides a world-class IDE called VisualAge for Java.
The entry-level version is free and targets the IBM WebSph ere software platform (a combination Web
server and application server)— not bad, considering that IBM is giving away WebSphere with a
one-user license. You can download these two tools and use them to develop powerful applications.
Inprise (formerly Borland) offers JBuilder, and Sun provides Forte.
Note Be careful if you install these IDEs because they might take a huge amount of
disk space. Also, many are written in Java. This is a good idea, but, because
the JVM interprets the programs, the IDEs may require a fast computer and lots
of memory to be truly useful.
Other tools are also available, but all you need for now is a text editor. We will be starting with simple
programs, so you don't need anything fancy. I use Notepad, the simple editor included with the
Windows OS. You can use plenty of other editors, ranging from simple Notepad replacements and vi
(a common Unix text editor), to large text-editor systems such as Emacs. The key is to use something
you are already comfortable with so you can focus on the Java code instead of on the text editor.
-13 -
Java 2 Core Language Little Black Book Chapter 1: Getting Started with Java
SDK Contents
The SDK provides you with several tools that you'd expect to receive from a language vendor, along
with a few additional tools that help with the overall development effort. The basic components include
the compiler (javac.exe under Windows), the runtime engine (java.exe), and the debugger (jdb.exe).
The SDK provides a few other tools that you probably won't use as often:
§ appletviewer— Runs and debugs applets (small programs that run in other programs).
§ jar— Manages Java archives (collections of files similar to a Zip file or a compressed tar
archive).
§ native2ascii— Used to convert files that contain native-encoded characters into UTF format.
The SDK also has tools that handle network programming, but you won't need these for a while yet.
The examples in this book were written using the Java 2 SDK version 1.4. Usually, newer versions of
the SDK will work with older versions, but to be safe you should work through the examples using
version 1.4, if possible. Installing multiple SDK versions is possible; if you are not careful, however,
installing two or more versions can cause problems. For example, if you compile with one version and
inadvertently execute with a different runtime version, your program will probably not work properly.
You can have two versions of the SDK installed, however, if you are very careful to keep them
separate. If you have 1.3 of the Java 2 SDK, and you install Java 2 SDK 1.4, you will have to decide
which version's binaries (i.e., java.exe, javac.exe) you want the PATH variable to point to. Also,
Windows systems have DLLs that are difficult to keep separate between versions.
Java in general has many powerful features, and Java 2 SDK 1.4 provides a few new twists. Many of
the improvements are performance related, so they don't change your programming.
One major change that is apparent is Java's handling of XML. Prior to SDK 1.4, you had to add
someone else's XML parser to your program to handle XML. Now, Java has its own XML parser. The
next release will include a major expansion of this a rea, but at least now there is a native XML API.
Before SDK 1.4, real database work required you to buy or download and install third-party packages.
It is such a relief that SDK 1.4 now includes APIs for JDBC (Java Database Connectivity) 3 as part of
the core Java platform. Relying on additional, third-party packages for this important functionality was
-14 -
Java 2 Core Language Little Black Book Chapter 1: Getting Started with Java
irksome. SDK 1.4 also adds full support for Unicode 3. Java now supports all major locales on the
planet, making internationalization easier. For example, this support affects the handling of
currency— Java now makes the euro the default currency used by the java.text.NumberFormat ,
DecimalFormat, and DecimalFormatSymbol classes for the member countries of the European
Monetary Union.
Finally, there is a major improvement to security. Java now includes JSSE (Java Secure Socket
Extensions), JAAS (Java Authentication and Authorization Service), JCE (Java Cryptography
Extensions), and Kerberos security capabilities. In fact, Java Kerberos supports single sign-on using
OS credentials.
You may redistribute the Java 2 runtime environment with your applications, subject to Sun's license.
The Java 2 runtime environment can be downloaded separately, offering you a way to distribute your
program and the Java virtual machine it needs to run. The JVM comes in the Java 2 SDK, or you can
download the JVM alone and then give it out so your end users will have a JVM with which to run your
software.
A source file contains the Java program as text. You can place this file anywhere, but keep in mind
that Java development is easier if you organize files properly.
The source file must have a .java extension, like this: myFirstProgram.java. If you don't use this
extension, the compiler will ignore the file.
The compiler creates a file by the class name, not by the file name. So when you compile a file, the
compiler will create a new file with the class name and will add the extension .class, like this:
-15-
Java 2 Core Language Little Black Book Chapter 1: Getting Started with Java
myFirstProgram.class. This file is the one containing the bytecode. Once you have all this, you can
run the program, and it is at that point that the JVM will interpret your bytecode file and execute code.
Because the compiler needs the class name, the compiler will insist that the file name matches any
public class name (names are case-sensitive). So if you try to put a public class named MyFirstClass
in a file named My1stclass.java (or myfirstclass.java), the compiler will generate an error.
Immediate Solutions
A current release of the Java 2 Platform SDK (Standard Edition version 1.4 for Windows, Linux, and
Solaris) is available at Sun's Web site. To download the SDK, follow these steps:
1. Go to http://www.java.sun.com.
2. Scroll down until you see a drop-down list box labeled "The Java Platform" on the left side
of the screen.
3. From the drop-down list, select Java 2 Platform–Standard Edition. Click the Go button to go
to the home page for the Java 2 Platform, Standard Edition (shown in Figure 1.1 ).
4. Click the hyperlink for the Java 2 SDK, Standard Edition v 1.4.
5. Choose your operating system, as shown in Figure 1.2.
-16 -
Java 2 Core Language Little Black Book Chapter 1: Getting Started with Java
6. You will be presented with Sun's "Terms and conditions of the license" agreement. Click
the button that signifies you agree.
7. You'll next get the page where you can finally download the SDK; see Figure 1.3 . Click o ne
of the Download buttons to download the software.
Tip We always select one of the alternate download sites; the main site is sometimes
slow because most people click the top Download button.
8. You will get a file like this: j2sdk-1_4_0-win.exe (for Windows). It is the installer that
decompresses the files and then copies them to your destination folder. The installer file is
large, around 50MB.
Tip If you don't have a fast or reliable Internet connection, you might want to use a
download-management program (for example, FlashGet at
http://www.amazesoft.com) that allows you to download faster and, what's more
important, download this large file in multiple attempts.
-17 -
Java 2 Core Language Little Black Book Chapter 1: Getting Started with Java
The SDK for the Standard Edition doesn't include advanced features that are found in the Enterprise
Edition, such as RMI (Remote Method Invocation) and email functionality. This S DK does, however,
include everything you need in order to build non-Enterprise applications, including typical network
programs.
The file j2sdk-1_4_0-win.exe is the Java 2 SDK installer. Double-click it when you have it on your hard
drive. Then follow the instructions the installer provides. When you're done with the installation, you
can delete the download file to recover disk space.
When you're ready to run the SDK installer, you will be prompted for the installation directory. The
default for the Java 2 SDK 1.4 is c:\jdk1.4. You can install the SDK wherever you want to, but keep in
mind that you will be typing this path in many places.
Tip We don't like installing software in the root directory— this, to us, is sacred real
estate. Instead, we always create a dev directory for all development files, such
as sample Java code. Under the dev directory, we have a java directory for all
things related to Java development. So the directory looks like this:
c:\dev\ja va\jdk1.4.
If you accept the default installation, then create this directory: C:\jdk1.4\myPrograms\test1. The
Windows Java 2 SDK has the directory structure shown in Figure 1.4.
Figure 1.4: The recommended directory structure for the local hard drive.
-1 8-
Java 2 Core Language Little Black Book Chapter 1: Getting Started with Java
You can run the Java 2 SDK without setting the Windows PATH variable, but it is best to set it. The
installation instructions describe how to do this. For example, to set the PATH variable permanently in
Windows 2000, you open the Control Panel, choose the System icon, select the Advanced tab of the
System Properties dialog box, and choose the Environment Variables button. Take a look at Figure
1.5, which shows the Edit System Variable dialog box.
Setting the PATH variable permanently allows you to run your Java programs from any directory.
Otherwise, it can be cumbersome to specify the path to the executable files every time you compile or
run your program. A few little things can go wrong when you try to compile and run a Java program.
You can run out of disk space, or you can get the following error message: "This program cannot be
run in DOS mode." You can fix this problem easily by changing the properties of the command
window, as explained in the Java Installation Notes that were installed with the SDK.
In addition to PATH, Java uses another environment variable CLASSPATH to locate nonstandard
class files and packages. Recent versions of Java automatically include standard classes, and
classes in the current directory. Therefore, you won't have to deal with CLASSPATH until the
examples become a bit more complicated.
Obtaining Documentation
The SDK doesn't include much documentation. We recommend that you download the
documentation by going back to the http://www.java.sun.com page and selecting Documentation
under the heading "The Java Platform." The documentation installer is just as big and expands to
about 9,000 files, eating 200MB of your hard drive. This documentation includes general information,
API and language details, a guide to features, documentation for the tools (compiler, documentation
creator, runtime engine, and others), and tutorial and demonstration information. If you have a fast,
-19 -
Java 2 Core Language Little Black Book Chapter 1: Getting Started with Java
always -on Internet connection, you might prefer to just browse the documentation online at the
http://www.java.sun.com documentation site (http://www.java.sun.com/j2se/1.4/docs/index.html).
Writing Code
After installing Java, start your text editor. Enter the following code into your text editor (for this
example, the file name must be countShoppersApplication.java):
/*******************************************
*******************************************/
class countShoppersApplication
int numberOfNewShoppers = 72 ;
int numberOfReturningShoppers = 81 ;
int numberOfShoppers = 0 ;
numberOfShoppers = numberOfNewShoppers +
numberOfReturningShoppers ;
System.out.println( numberOfShoppers ) ;
-2 0-
Java 2 Core Language Little Black Book Chapter 1: Getting Started with Java
Note Depending on your Windows setup, Notepad might try to append a .txt extension to your
file. Notepad doesn't check to see if you have typed your own extension, so be sure to
change Save As Type to All Files, or you will end up with the incorrect name
countShoppersApplication.java.txt. One way to ensure that this doesn't happen is to put
double quotes around the file name in the Save As dialog box.
Now, you are ready to compile your first Java program. To do so, follow these steps:
1. Execute the javac.exe program (the compiler) to compile the source file you just created. In
older versions of Windows, use the DOS prompt; in newer versions (Windows 2000),
choose Start|Programs|Accessories|Command Prompt.
Do not use the Start|Run command; if you do, the window will close upon completion of
Y
your program without giving you a chance to see what happened.
FL
At the prompt, change the directory by typing the following:
CD \myPrograms\test1
AM
2. You should have set the path as mentioned earlier. If you didn't, you can issue the following
TE
5. javac countShoppersApplication.java
6. Look in the directory by entering "dir " or using a Windows Explorer window.
The compiler does not display a message in the Command Prompt window unless you have
encountered an error. If you do get an error message, then you probably have a path problem or have
mistyped something. Check your path carefully. Examine the lines the compiler doesn't like and the
nearby lines for mistakes.
Notice that the file name is the same as the class name. You can use a different name for the file, and
Java will compile and run it correctly. That's because the class is not a public class. We strongly
recommend naming source files the same as the primary class names, however. Not only does this
make things easier, but it is a requirement when you write public classes, as you will in later chapters.
-2 1-
Team-Fly®
Java 2 Core Language Little Black Book Chapter 1: Getting Started with Java
The file named countShoppersApplication.class should appear in the directory. You will be working
with twin files: the source file, which ends with .java; and the compiled file, which ends with .class.
The last thing we will do in this chapter is to run the program. To do this, issue the following command
in the same command window that you used for compiling:
java countShoppersApplication
You'll need the same path setup that you used for compiling.
The program you wrote defined a class (countShoppersApplication). In that class, you defined a
method (main). Within that method, you declared variables (numberOfNewShoppers,
numberOfReturning Shoppers, number Of Shoppers), assigned values to them, computed a sum,
and then printed the sum to the screen (System.out.println). Congratulations! It gets easier from
here.
-2 2-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
In Brief
In this chapter, you'll learn what the compiler recognizes as legal characters and statements.
Although syntax details aren't the glamorous part of programming, a solid understanding of Java's
syntax is necessary before you plumb Java's depths.
Syntax
Computers can't understand humans very well. Even a young child has a better grasp of language
than do today's most sophisticated computers. To help the computer, we use special languages to
describe the tasks we want it to do. The compiler— a special computer program itself— translates our
special language into commands the computer can execute. Because the compiler itself is a
computer program, it isn't very at good understanding humans, either.
To simplify the computer's task, languages such as Java define strict rules you must follow. If you
deviate from these rules, the compiler will generate an error. You want to learn the correct rules— the
language syntax— so that they become second nature. That way, you can focus on the actual
programming problem at hand and not on the language details.
Compilation starts by breaking your code into lines that are defined by line terminators. Then the
compiler breaks lines into chunks of text called tokens . Tokens are defined or delimited by white
space. The compiler then identifies the meaning of each token and converts the program into
bytecodes.
Objects Everywhere
Java programs are built around classes. A class defines data and programming that go together to
represent something. For example, if I worked for a grocery store, I might write one class to represent
the store, another class to represent aisles in the store, and yet another class to represent cash
registers.
The CashRegister class is a prototype for all cash registers. In my program, I'll use a class to create
one or more instances of these classes; these instances are often called objects ( these two terms are
more or less interchangeable). Each class contains a number of fields (places to store data) and
methods (program steps that operate on the object's data).
For example, the CashRegister class might have a field (some people call these fields variables) that
contains the amount of money in the drawer. The methods of this hypothetical class might be sale,
refund, printReceipt, and similar cash-register -related operations.
Don't forget, the CashRegister class doesn't represent the cash register. Instead, you use the
CashRegister class to create objects that represent cash registers. Think of classes as cookie cutters.
Cookie cutters aren't cookies; you use the cutters to make cookies. You can make one cookie or
dozens of cookies. They will all be the same, but they will all be separate entities.
-2 3-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
You'll read more about classes, fields, and methods in this chapter and throughout the rest of this
book. Understanding the basic structure of a Java program will help you digest the material in the rest
of this chapter.
Basic Structure
Every Java program has at least one class. Some classes are public; that is, they are visible from any
other part of the program. Other classes may not be visible from everywhere; either they are private ,
or they have package scope (discussed in Chapter 4). Java is very strict about public classes. Each
file you create can contain only one public class. If your program needs more than one public class,
you'll need to create more than one file. Furthermore, the file's base name must exactly match the
name of the public class. If you create a public class named CashRegister , therefore, it must reside
in the file CashRegister.java. Java even recognizes the case of the file name, so it must match
exactly.
Before stating the class definition, your source file may contain import statements. Superficially,
import statements resemble include statements that you might find in other languages, such as C or
C++. This analogy isn't perfect, however. The import statement is actually much smarter than a C
include statement (for example, you don't have to worry about importing the same file twice). Also, C
include statements can contain any sort of code or macros you want. The Java import merely
provides simplified access to another object's public methods and fields.
To understand import completely, you have to realize that Java organizes classes into packages . By
default, if you use a class name in your program, the compiler looks for this class in two places: in the
package you are currently creating (which may be the default package that has no name), and in the
special package java.lang. For example, suppose you write:
This defines a string variable named s. In Java, strings are objects, and the String object is part of the
special system package java.lang. Therefore, you could write:
These two statements are equivalent. Suppose you want to use classes from a different package,
however. For example, you might want to use the Socket class from the java.net package. You could
write:
java.net.Socket sock;
It gets tiresome to keep specifying this lengthy prefix in front of the class name, however. That's
where import helps you. By specifying an import, you can tell the compiler that you will be using
classes from another package. You can import a specific class like this:
import java.net.Socket;
-2 4-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
You can also import an entire package, and gain access to all the classes in that package. Simply
place a star at the end of the package name, like this:
import java.net.*;
You read earlier that a class is a cookie cutter that creates objects. You've also read that all Java
programs are objects. This leads to a chicken -and-egg problem: What creates the first object in your
program? The answer is that you do. In a conventional Java program, one class will have a static
function named main. When a function is static, it is really part of the class and not part of the
individual objects in the class. That means that static functions exist even before you create any
objects.
Java calls the main function in your object. This is your chance to create a new object or to do any
other processing that is required. Very simple programs can do all their work in the main function.
Consider the simple program in Listing 2.1 . This program prints a friendly Texas-style greeting.
Listing 2.1: This simple program does all of its work in the main function.
System.out.println("Howdy!");
This program has only three significant lines. The first line begins the definition of the class (Howdy).
The second line begins the definition of the main function. The third line prints a message on the
system console.
Tip A common mistake is to try to simplify the above program by using import with
System.out.println or System.out.* so that you can use println instead of
System.out.println. That sounds like a good idea, but it won't work. In future chapters,
you'll learn that although System.out looks like a package, it isn't. System is really an
object itself and not a package.
Although some of the details in Listing 2.1 might not be apparent, you can probably make several
observations about the program. First, the Howdy class is public, so the file name must be named
Howdy.java. You can see that curly braces group statements together. You'll read more about this
-2 5-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
throughout this chapter. For now, notice that the final curly brace ends the definition of the class. The
penultimate brace ends the definition of the main function. (Functions are also known as methods.)
Tip Parameters are the variables that are declared in a method's opening parentheses and
that contain values sent to the method. In this case, the main method accepts a String
array named args. Java supplies any command-line arguments in this array. You'll learn
more about arrays later in this chapter.
This simple program doesn't create any objects. You could rewrite it to be more object oriented, if you
like (see Listing 2.2). This example uses several features you'll read about later.
Listing 2.2: This simple program creates an object.
void execute() {
System.out.println("Howdy");
// call execute
Comments
Notice that Listing 2.2 contains two pairs of slash characters (//). This notation is one form of comment.
These notes are meant for humans, and the compiler ignores them. Comments are very helpful to
other people who are trying to read your code. Comments can also help you when you have to revisit
code you wrote in the past.
You can use two different types of markers for comments. One type of marker, as you've seen, is the
pair of forward slashes (//). The compiler ignores anything after the double forward slash on the same
line (between the slashes and the end of the line). This type of comment is often used to make a short
note about a particular line.
For multiple-line comments, you can use /* and */ to delimit as much text as you want. The compiler
ignores anything between /* and */, even if the comment spans many lines. The following examples
would all be ignored by the compiler:
-2 6-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
/********************************
* are ignored by *
* the compiler, *
* int a = 29; *
********************************/
You can place the /* and */ comments anywhere you can put a space. The examples at the top of the
next page are legal (although not necessarily good form because they make the code harder to read):
Comments do not nest. That means you shouldn't mix single-line and multiple-line comments. Once
you begin a single-line comment, the multiple-line comment tag has no meaning, so /* and */ are
ignored on the same line if they occur after //. Also, // is ignored if it occurs anywhere between the
multiple-line comment tags.
There is one more rule you must follow. You can place multiple-line comments between any tokens
(sometimes very good practice), but don't place comments within quotes (character literals or string
literals) or in the middle of a number or name (such as a variable, keyword, or reference). After the
comments are stripped away, the compiler starts looking for line terminators.
Sometimes you'll see comments that start with a slash and two asterisks. To the compiler, this is jus t
an ordinary comment that happens to start with an asterisk. However, special tools can read your
program and automatically generate documentation (in the form of Web pages) by reading and
interpreting these special comments. Therefore, you shouldn't use the /** syntax unless you mean to
create these special comments. In Appendix A, you'll learn about the javadoc tool, which interprets
these comments.
Line Te rminators
The compiler collects all characters it encounters, left to right, until it finds a terminator. Everything the
compiler finds between terminators is considered a single line (which is different from a statement).
The compiler recognizes three line terminators. They are:
-27 -
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
When the compiler finds one of these terminators, it parses the text of that line into tokens by looking
for white space.
Java recognizes tokens — words that potentially have meaning— by using white-space characters to
mark the end of tokens. White-space characters include the blank, tab, form -feed, and end-of-line
characters. When the compiler runs across a white -space character, the compiler ignores subsequent
white space until it reaches another token (indicated by a non-white -space character). The exception,
of course, is within quoted string constants (like the output string in Listings 2.1 and 2.2), where every
space counts. The compiler finds that the following two statements are equivalent:
int numberOfNewShoppers = 72 ;
int numberOfNewShoppers = 72 ;
The characters the compiler finds between white -space characters are tokens (int,
numberOfNewShoppers, =, 72 , and ; in this example). The compiler further breaks the tokens it
finds on this initial pass into more tokens based on specific rules. For example, consider this
statement:
int x=10;
Initially, this appears to be two tokens, int and x=10;, but there are actually five tokens: int, x, =, 10 ,
and the semicolon.
Although the compiler doesn't care much about white space, you can use spaces to your advantage
to make your code more readable.
Now that the compiler has broken a given line into tokens, it goes through each one, character by
character, to refine the token list. One of the tasks is to figure out which tokens are names of things
(identifiers).
Separators
Some separators are used to group code fragments, and others are used to distinguish between
fragments. The following nine characters are the separators:
{}()[];,.
-2 8 -
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
if (result == -1)
if (nextVal == -1)
return result;
The braces, { and }, are the separators that group the largest sections of code. Braces are used to
define blocks (see Chapter 3). The braces define the start and end of code for classes and methods.
Braces can be nested. Parentheses, ( and ), are used for method parameters such as the method
parseInt in the previous example.
Brackets, [ and ], are used for arrays, which are discussed later in this chapter. As seen earlier, the
semicolon (;) is a statement terminator. The comma (,) is used to separate arguments in a method call,
parameters in a method declaration, and declarations.
Identifiers
An identifier is the name of an item (such as a package, class, object, interface, method, variable, or
constant) used in a program written in the Java language. Identifiers can use letters, numbers, dollar
signs, and the underscore character (_). The letters can be anything defined by Unicode. That means
you can declare your variables as half English and half Greek or all in Cyrillic.
§ The remaining characters can be letters, numbers, dollar signs, and the underscore
character.
§ Identifiers can be any length (in practice, you'll rarely use more than a few dozen
characters).
-2 9-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
§ You can mix letters and numbers as long as the first character is a letter.
§ Identifiers cannot be the same as reserved keywords (such as int, long, class , true, false,
null, etc.).
numberOfNewShoppers
start12345zcounting
alphaBetaGamma___
We recommend two principles: be consistent, and use descriptive names. Make sure your names are
self-documenting, and spell them out. If you wrote Fortran in the 1960s, the length of variable names
was limited by the compiler or memory limitations. These days, there is no excuse for using cryptic
identifiers. It is hard to read code in which the variable names don't follow an easily recognized pattern.
Table 2.1 shows examples of common naming conventions used for various entities.
BigDecimal
Classes Each word begins with an uppercase letter; the first
letter of the class name is capitalized.
Checksum
Interfaces Same rules as classes.
compareTo
Methods Method names are verbs with the first letter
lowercase; then capitalize each subsequent word.
keyBytes
Variables Variables are nouns with the first letter lowercase;
then capitalize each subsequent word.
-3 0-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
underscores.
You can't name your objects by the same name Java uses already. The following are keywords
reserved by Java:
While you can't use the exact keywords in a name, you can create a name that incorporates a
keyword, as long as it doesn't duplicate the reserved word. For example, you might write returnTrue
or return_ break, both of which are legal identifiers.
Reusing Names
Problems can arise when you reuse the name of an existing object such as a class or variable
declared previously. You need to be very careful about this. It is legal, but it can cause errors. For
example, if you declare the variable shopperCount at the class level and then declare it again in a
method within the same class, Java considers these to be two different variables and assigns them
-3 1-
Team-Fly®
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
two different memory locations even though they have the same spelling. We will cover scope (where
objects can be accessed) in Chapter 4. For now, just be careful to avoid repeating an object name
unless you have a good reason to do so (such as for method overloading).
A string literal is composed of characters enclosed in double quotes. You can make an empty string
(one with zero characters) by writing two double quotes together. The following are examples of string
literals:
"r"
Two strings that have the same set of characters are not necessarily the same string object. However,
the compiler will form one object for multiple string literals that contain the same characters. This
makes it tricky to compare strings for equality. If two variables point to the same object in memory,
then they are equal. If two string variables refer to different objects— even if both contain the same
sequence of characters — they are not equal. Look at the following:
System.out.print(firstString == secondString ) ;
The two string variables — firstString and secondString— appear identical to a human, but to the
computer they are quite different. The program will print false when run. That's because the compiler
generates two separate string objects and the == operator tests to see if two object references refer to
the same objec t— not if the objects appear to be the same to a human observer. Think of firstString
and secondString as identical twins: No matter how much alike they look, they are still two separate
entities. The compiler will try to identify the identical literal. Try changing the second line to this:
-3 2-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
Now the compiler will recognize that the two strings are the same literal and generate a single object
(causing the program to print true).
A few characters require special treatment if they are intended to be literal characters or part of a
string. For example, you might want to include a quotation mark. Java allows you to use escape
sequences (these begin with a backslash; see Table 2.2 ) to write special characters. The \u escape
sequence allows you to enter any arbitrary Unicode character.
\b
Backspace Positions the cursor one position back.
\f
Form feed Positions the cursor at the start of the next page.
\r Carriage return Positions the cursor at the beginning of the current line without
advancing to the next line. (On some platforms, this is the
same as a newline character.)
\”
Double quote Prints a double-quote character.
Variables
In Java, a variable is an item of data named by an identifier. Your program stores data in variables so
it can manipulate the variables. Each variable has a name, a type, and a scope. The three rules for
variable names are:
§ A variable name cannot be a keyword, a Boolean literal (true or false), or the reserved word
null.
-3 3-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
§ A variable name must be unique within its scope (covered in detail in Chapter 4).
int x;
float salary;
These statements declare two variables: x , which contains an integer, and salary, a floating -point
number. These variables can hold values for use in computations. For example, you might write:
x = x * 128;
You'll see shortly that this statement will multiply x by 128 and put the result back in the x variable.
Declarations
When memory is first allocated for an object, the data it contains is unpredictable. This can cause
bizarre behavior. Java prevents this type of trouble by initializing variables to safe default values. The
main steps to using a variable in Java are:
Declarations tell the compiler that you will be using a certain name to refer to a variable whose type is
explicitly given. For basic data types (like int, for example), the compiler will reserve enough memory
to hold the data. However, a declaration of an object reference type does not create an object; the
declaration just adds the name to an internal list of names that Java knows will be holding objects,
and it reserves enough space to hold a reference to an object. Instantiating an object allocates
memory for it. For basic types, this happens automatically; for object types, your program must
explicitly instantiate the object. Initializing places the first value in that object reference.
Java has a shortcut for initializing variables that use primitive data types. You can do all three steps
simultaneously, like so:
The int count portion declared the variable and instantiated it as well. The = 243 portion initializes the
new variable. We would say that this variable is initialized with an assignment statement upon
declaration. Table 2.3 shows the instance and static variables' default values upon declaration.
-3 4-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
byte
0
short 0
int
0
long 0L
float 0.0F
double
0.0D
char ‘
\u0000’(note: not a space (‘\u0020’
) !)
boolean false
When you create a variable, Java always initializes the variable to a default value as a safety measure.
After you declare a variable, you can depend on this initial value without having to set it yourself
manually.
You might think that you would have to initialize maxAge because it can't be changed. That was true
in old versions of Java, but since the release of the 1.1 version of Java the rules have changed. You
can leave a final variable uninitialized. If you do, you must assign a value to it before you use the
variable, and you can only assign to it once. Multiple assignments will result in an compile-time error.
-35 -
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
The new operator is used to declare objects (not primitive data types, but instantiated classes and
arrays). Look at the following examples:
// object
The word after the new operator specifies the type of object you want to create. The arguments in
parentheses allow you to modify the object creation process (through something known as a
constructor, which you'll read about in Chapter 4 ).
Strings are so common that Java allows you to use a shortcut to declare and initialize them like a
basic type. For example:
The discussion about the new operator in the previous section implies that variables can be objects.
While this appears to be true, it isn't. In Java, a variable can be a simple type (like an int ) or it can be
an object reference. In fact, objects (including strings and arrays) are never actually directly and
uniquely named by an identifier. Instead, reference variables refer to the objects. This is a subtle
distinction but an important one.
A good analogy is a phone number. You probably have a phone number (perhaps several). That
phone number isn't really you, though; it just refers to you. If you move, someone else will get your
phone number (and you might get another one). You might even have a regular phone number and a
cell phone number. They both still refer to you. Consider the following code:
codeName=myCodeName;
This code creates one String object (it contains the string "Destroy"). However, there are two
reference variables (myCodeName and codeName). These variables now refer to the same object.
-3 6-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
Operators
When you think of a computer program, you often think of computations. Operators are the
mechanism that allows programs to perform computations on various values. There are three types of
operators. A unary operator acts on one operand; a binary operator acts on two operands; and a
ternary operator acts on three operands.
Operators tell Java to perform a task using one, two, or three values. For example, consider this bit of
code:
a = b + c;
This statement uses two operators. The + operator tells Java to add variabl es b and c. The = operator
puts the result into the a variable. Table 2.4 shows the 37 symbols that are Java operators.
>, <, <=, >= Binary Less than, greater than, less than or equal to, and
greater than or equal to
+, - , *, /
Binary Basic math operations (addition, subtraction,
multiplication, division)
&&, ||
Binary Logical AND, logical OR
!
Unary Logical NOT
-37 -
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
<<, >>
Binary Left shift, right shift
>>>
Binary Unsigned right shift
++, - -
Unary Increment or decrement
Math Operators
Most of the math operators in Java are familiar to everyone (+, -, *, and / represent addition,
subtraction, multiplication, and division). Keep in mind that dividing integers results in an integer. So
10/3 — if both numbers are integers — results in 3. The % operator provides the remainder from a
division, so 10%3 results in 1 because 10/3 leaves a remainder of 1.
The – operator is usually the binary subtraction operator, but it can also be a unary operator. For
example, 10+-3 uses the unary – operator to negate the number 3.
It is very common to perform an operation on a variable and put the result back in the same variable.
This is so common that Java provides a shortcut to simplify this operation. Consider this expression:
x=x+10;
x+=10;
Another common operation is to add (or subtract) 1 from a variable. Java provides a shortcut for this
as well in the ++ and -- operators. These operators have a special property because they are unary.
-3 8 -
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
x = 100;
y = 5 + x++;
The ++ operator adds 1 to x. Because the ++ operator appears after the x (postfix), however, Java
uses the original value of x in the expression. Therefore, after these statements are executed, y will
contain 105, and x will contain 101. You can rewrite the code so that the ++ operator appears before
the x(prefix) like this:
x = 100;
y = 5 + ++x;
After this code executes, x will still contain 101, but now y is 106.
Relational Operators
Relational operators are those that compare two values (for e xample, == and < are relational
operators). These operators produce a true or false result. You could store these Boolean values in a
variable of type boolean. However, usually you'll use these in if and similar statements (see the next
chapter). For example:
You can change the sense of any Boolean value (including a relational operator) by using the unary !
operator. This operator turns true into false and vice versa. So writing a<b is the same as
writing !(a>=b).
You can also join relational operators (or any Boolean expressions) by using the && or || operators
(&& is a logical AND; || is a logical OR). One point about these operators bears mentioning: These
operators evaluate values from left to right and stop processing as soon as the result is clear.
Tip A common error is mixing up the equality operator (==) with an assignment
operator (=). The equality expression is a test returning true or false . The
assignment expression copies what is on the right to the left.
int a = 1;
int b = 2;
int c = 1;
-3 9-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
The char da ta type is treated as an integer internally, so it also uses the == operator. Strings and
objects are more complicated. For example, if two different string variables contain the same
sequence of characters, we say they are lexicographically equal. They hold equivalent strings, but
these two string objects are held in two separate memory locations. Look at the string comparisons
shown in Listing 2.3
String b;
System.out.println("(a==b)=" + (a==b));
System.out.println("(a==(b+\"\"))=" + (a==(b+"")) );
System.out.println("(a.equals(b))=" + a.equals(b));
System.out.println("(a.equals(b+\"\"))=" + a.equals(b+""));
System.out.println("((a+\"\")==(b))=" + ((a+"")==b));
(a==b)=false
(a==(b+""))=false
-4 0-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
(a.equals(b))=true
(a.equals(b+""))=true
((a+"")==(b))=false
You need to be careful with objects, especially strings. The equality operator is not intuitive here. The
== operator simply tests to see if the object references on either side refer to the exact same object. If
there are two objects involved (as there are in this case) the == operator returns false even if the
strings contain the same characters. The equals method retrieves the contents and compares the
letters; this is probably what you usually want to do when comparing strings or objects.
Tip Use the equals or compareTo methods when comparing strings unless you
really want to test for object equality.
Operator Precedence
Java follows strict rules regarding which operators it processes first when there are multiple operators.
These rules will be familiar to you if you remember your high-school math classes. You learned in
math class that, by convention, you perform multiplication and division before addition and subtraction.
Y
Java uses this rule as well as others. Consider this series of statements:
FL
x = 10;
AM
y = 3;
TE
z = x + y * 5;
Because multiplication occurs first, z will contain 25 (not 65). Table 2.5 shows Java's operator
precedence listed in order; each row has priority over all rows beneath it. Operators on the same row
have equal pre cedence and are performed in the order in which they appear in code (reading left to
right).
Name Symbol
-4 1 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
Name Symbol
*/%
multiplicative
+-
additive
equality == !=
bitwise exclusive OR ?
bitwise inclusive OR |
&&
logical AND
||
logical OR
conditional ?:
-4 2-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
You can find an example of using & (and) on the numbers 2 and 3 in Figure 2.1. For clarity, I've shown
only the least significant bits of the numbers.
A B A&B A? B A | B (OR)
(AND) (XOR)
0 0 0 0 0
0 1 0 1 1
1 0 0 1 1
1 1 1 0 1
The first bit in the integer 2 is 1, as is the first bit in the integer 3. The expression 1 & 1 returns true or
a 1. The second column, 0 & 1, returns 0. The result is the integer 2. The following code demonstrates
this:
//Returns:
//2 & 3 = 2
Shift Operators
A shift operator moves bits in a binary number: All bits slide over a certain number of positions,
determined by the second operand. The first operand bits are shifted right or left by the number of
positions specified in the second operand. Shifting a number left has the effect of multiplying the
-4 3-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
1
number by a power of two. So shifting a number left by one position will multiply the number by 2 (2 ).
Shifting three places is the same as multiplying by 8 (23). Shifting right divides by a power of 2. Table
2.7 summarizes the shift operators.
<<
A << B Shifts bits of A left by B positions.
>>>
A >>> B Shifts bits of A right by B positions (unsigned).
The right shift operator (>>) knows that the leftmost bit of an integer corresponds to its sign. Negative
numbers always have a one in the leftmost bit, and positive numbers always have a zero in that
position. The normal right shift operator (>>) preserves this bit so that dividing a negative number
yields a negative result. If you want a true shift, you can use the unsigned shift operator (>>>).
The ShiftOperators.java program (see Listing 2.4) demonstrates how to use the shift operators.
int shift;
for (shift=0;shift<8;shift++)
-4 4 -
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
r=v1<<shift;
r=v2>>shift;
We say, "a shift right 1" or "a is shifted right by 1." Notice that shifting by zero doesn't affect the
number at all.
Assignment Operators
An assignment operator (=) places the result of what is on its right- hand side into the left-hand
expression. It is very common to perform an operation on a variable and then reassign the result to
the same result. For example, you might write:
x=x+10;
Because this practice is so common, Java allows you to combine this sort of operation into a
shorthand statement (see Table 2.8). The previous statement can be written as:
x+=10;
+=
A += B A=A+B
-= A- =B A=A - B
*= A *= B A=A*B
/=
A /= B A=A/B
%=
A %= B A=A%B
-4 5-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
|=
A |= B A=A|B
?= A ?=B A=A ?B
<<=
A <<= B A = A << B
>>>=
A >>>= B A = A >>> B
if (a > b) {
maxValue = 100;
else {
maxValue = 200;
Java provides a nice shorthand way of doing the same thing, like this:
This is the only operator that accepts three arguments, and it is sometimes called the ternary operator
for this reason.
Arrays
An array is a structure that holds multiple values of the same type. In Java, arrays are really a form of
object. You use the square brackets to indicate an array variable. The square brackets also appear
-4 6 -
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
after the new keyword to specify the size of the array. In the following example, the array has 10
elements ranging from anArrayofIntegers[0] to anArrayofIntegers[9]. For example:
// integers
Just as strings have a shortcut initializer, arrays also have a special syntax you can use. Here's an
example:
Arrays are actually objects, and therefore they can have fields. The main field you will use for arrays is
length. This field returns the number of elements in the array.
Arrays can even contain other arrays; this capability allows you to create arrays of many dimensions.
For example, here's a three-dimensional string array:
};
You can copy elements from one array to another, like so:
char[] copyFrom = { 'b', 'l', 'a', 'c', 'k', 'b', 'o', 'o', 'k', };
In this example, the blackWord string contains the string "black." An element within an array can be
accessed by its index. The snippet copyTo[3] will return the character "c" (an array index is zero
based, so this is the fourth element). The primary rules for arrays are:
§ The first array element is index 0. The last element is the array length –1 .
-47 -
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
§ Once you create an array, you can't directly change its size.
§ For arrays of primitive data types, each element gets the default value when the array is
created. Object arrays are initialized with null (a special value that marks a reference
variable that doesn't refer to anything).
§ You can precede the array name with [] in the declaration. Alternatively, you can use the []
as a suffix.
§ [][] declares a two-dimensional array. The number of brackets determines how many
dimensions are used. Technically, this forms an array of arrays.
§ Arrays are objects (this is true even if the array's contents are simple data types, such as
integers).
Casting
When you have a variable of one type, it is often useful to convert it t emporarily into a different (yet
compatible) type. For example, suppose you are computing the average of several integers. You add
the integers together in the total variable and you count the integers in the count variable. Then you
might write:
float avg;
avg=total/count;
System.out.println(avg);
The problem is that the right-hand side of the assignment contains only integers. Therefore, Java
performs integer division. If total is 125 and count is 99, avg will contain 1.0; this is technically correct,
but probably not what you expected.
Of course, you could assign total or count to a temporary floating- point variable, but it is more
efficient to use a cast. To cast a value to a different type, put the type's name in parenthesis preceding
the expression. You could therefore rewrite the previous example to read:
float avg;
avg=total/(float)count;
System.out.println(avg);
Converting either variable to float will cause the division to use floating point and will yield a more
correct result. You can't cast to any type; it has to be a compatible type. For example, trying to cast
count to a String will cause a compile-time error.
-4 8 -
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
Immediate Solutions
In Java, every variable and every expression have a data type known as compile time. Java is a
strongly typed language. Data typing defines what kind of values a variable can contain. The data
type restricts both the variable's values and the operations that can be performed on it.
Data types fall into two broad categories: primitive (such as int) or reference (these refer to classes
such as String). The primitive data types appear in Table 2.9 .
char
Unicode characters Single character
byte
–128 to +127 8-bit integer
float
± 3.4028235E38 Real number
double
± 1.7976931348623157E308 Double-precision
floating-point number
You can easily declare a variable by naming a type and then listing one or more variable names:
int myCount;
-4 9 -
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
Declaring arrays requires that you use square brackets. You can place them after the type name or
after the variable name; it doesn't matter which you choose. Here's an example of an integer array:
int [] numList;
int numList[];
In Java, arrays are technically objects, so to create the array you must use the new operator and
provide the size of the array. Here's how you'd make an array of three integers and set the first and
last elements:
primes[0]=1;
primes[2]=5;
Using Literals
A literal is what you "literally" type to represent a value of a primitive data type or a string. For example,
if you type the number 49.2 in your code somewhere, then this number is a literal. The form of the
literal determines its data type (see Table 2.10).
byte
3 8 –128 to +127
decimal
243 32 –2147483648 to +2147483647
hexadecimal
0x59fff000 32 0x7fffffff
-5 0-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
decimal
544297L 64 –9223372036854775808L to
+9223372036854775807L
octal
087897L 64 0777777777777777777777L
float
3.14f or 32 ± 3.4028235E38
5.827e+23f
double
3.14 or
Y64 ± 1.7976931348623157E308
FL
5.827e+23
AM
char
TE
‘
b’ 16 One character
Listing 2.5 shows a program that demonstrates how to get the maximum and minimum values for
Java's numerical data types.
Listing 2.5: Getting the maximum and minimum values for Java's numerical data types.
-5 1-
Team-Fly®
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
The conditional AND (&&) and conditional OR operators have "conditional" in their names because
the compiler evaluates the first operand but may or may not evaluate the second operand. The
second operation is conditional because it depends on the result of the first evaluation. With the &&
operator, the second operand is not evaluated if the first result is false. This makes sense because
-5 2-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
the result could not possibly be true. The second value is immaterial. Similarly, the second operand is
not evaluated if the OR (||) operator finds a true result in the first operand. In this case, a false result
is not possible.
import java.util.Random;
a = randomGenerator.nextBoolean();
b = randomGenerator.nextBoolean();
count = 1;
++actualEvals;
-53 -
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
skippedEvals = totalEvals-actualEvals;
//returns:
You'll read about the random generator later in the book. For now, focus on the highlighted lines.
These lines make up a single statement that conditionally tests a and b for true values. They must
both be true for the expression to return true . Therefore, if a is false, there is no need to evaluate b.
With the ordinary OR operator (||), the situation is reversed. If a is true , there is no reason to continue.
The exclusive OR operator (?) always evaluates both operands (there is no ?? operator).
If you try to apply a Boolean operator directly to a data type other than boolean, you will get a
compile-time error.
-5 4-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
The Boolean NOT operator reverses a Boolean value. If the operand is true , then false is returned. If
the operand is false, then true is returned. The NOT operator is often combined with other operators
(such as !=, which is "not equal to") and used to reverse the outcome of expressions, like so:
This statement defines customer satisfaction by two conditions. If the price is too high or he was
overcharged, then the customer will not be happy. If either of these conditions is true, the expression
between the parentheses will return true . If one of the two conditions is true , we want to show that the
customer is unhappy, so we use the NOT operator to set the isCustomerHappy flag to false.
Tip The NOT (!) operator has a high precedence, so parentheses are often needed
to make a statement correct.
The NOT operator (!) reverses a single Boolean value. It is easy to confuse NOT with the complement
operator (~). The difference between these two operators is that the NOT operator works with
Boolean values. The complement operator works on binary numbers, inverting each bit in the value.
The following program demonstrates both the NOT and complement operators:
import java.util.Random;
int randomInteger = 0;
randomBoolean = randomGenerator.nextBoolean();
randomInteger = randomGenerator.nextInt();
System.out.println("randomBoolean=" + randomBoolean +
-55 -
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
System.out.println("randomInteger=" + randomInteger +
//returns:
//randomBoolean=false; !randomBoolean=true
//randomBoolean=true; !randomBoolean=false
//randomBoolean=true; !randomBoolean=false
In this program, the Boolean value simply gets inverted. Look at the integers, however. The
complement operator inverts every bit in the integer; this has the effect of changing the sign and
incrementing the result by one. If the operand was positive, then the result is equivalent to "add one
and negate." If the operand was negative, the result is "take away one and remove the negative sign."
The complement operator works on all integer types.
The need to mix data types is common in programming. Java performs data type conversions when
you mix the data types in the same statement. Java tries to avoid losing information, so it converts all
variables and expressions to the type that is the largest (most bits) and most precise type in the
statement. For example, if you have five variables, of which four are integers and one is long, the
result will be a long type:
int firstInteger = 1;
int secondInteger = 1;
int thirdInteger = 1;
int fourthInteger = 1;
System.out.print(firstInteger+secondInteger+thirdInteger+
fourthInteger+firstLong);
-5 6-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
The previous example prints "14" to the console. However, if you try to do the following:
fourthInteger = firstInteger+secondInteger+thirdInteger+firstLong;
the compiler will complain because you tried to place a long into an int. The following does work,
however:
firstLong = firstInteger+secondInteger+thirdInteger+firstLong;
You can read more about casting (explicitly changing a data type) in the next section. For now,
observe that the data type precedence for arithmetic operations (and most others, if possible) should
be read left to right where the resulting data type is the leftmost type in the following list: double, float,
long, int, short, byte.
Tip The expression+count promotes count to int if it's a byte, short , or char;
however, -count arithmetically negates count regardless of its data type.
When you convert one data type to a nother, there is always a risk that information will be lost. You
can't hope to change a long to an int correctly because you would be trying to stuff 64 bits of data into
a 32-bit container. Going from a bigger data type to a smaller one is known as a nar rowing conversion.
Going from a smaller data type to a larger one is known as a widening conversion. Generally,
widening works fine, but narrowing loses information.
If widening is required (multiplying an int by a float, for example), Java handles the conversion
automatically. Java does what is called an implicit conversion. When you go the other way, Java does
not automatically narrow the data for you to avoid losing information. You have to use a cast to
perform a narrowing conversion. There are two types of casts:
Casting is used to force an explicit conversion of data from one type to another. It requires you to use
the type name in parentheses, like this:
(type)variableName
Java then takes the value of the variable (or expression) and converts it to the data type you specified
in the cast. So, the expression 100*5 returns an integer, but the following returns a long: (long)(100 *
5). This is an example of a widening conversion. It is convenient to let Java do this automatically, but it
is usually better to explicitly cast an expression if you know the resulting data type requirement.
Explicit casting prevents future problems when you change the expression to include data types that,
if left to Java's implicit conversion, would result in an undesirable data type.
The following is a widening conversion scale for numbers. Converting left to right will happen
automatically (implicitly), but converting right to left requires explicit casting:
-5 7 -
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
All the previous conversions can be done by Java implicitly. What about narrowing conversions? The
following is an example of a narrowing cast:
float a =3.583453f;
int b=0;
b = (int)a;
float a =0f;
int b=2390;
Whenever you perform math on dissimilar data types, Java will always perform a widening conversion.
You have to explicitly cast to override this like so:
Without the explicit byte cast, Java would return an integer because the 100 is an integer and Java
promotes the byte to an integer. You will get a compile-time error if you try to perform a narrowing
conversion, say of a long to an int, without the cast operator. For example, if you try to put the literal
12L into an integer variable (for example, i), Java will complain:
found : long
required: int
int i = 12L;
1 error
-5 8-
Java 2 Core Language Little Black Book Chapter 2: Essential Java Syntax
Of course, removing the L from the literal will solve this problem. You could also cast to an int. Be
careful when mixing numbers and strings. You should not rely on Java's implicit casting unless it is a
trivial situation. We recommend avoiding any math directly in a string construction. Do the math first;
then cast, as in the following:
Sun's documentation states, "Despite the fact that overflow, underflow, or other loss of information
may occur, narrowing conversions among primitive types never result in a run -time exception." The
phrase "loss of information," though, means that you can't predict what is going to happen. For
example, if you assign a float value that is too large to fit into an integer variabl e, Java returns the
maximum int value. However, a double value that is too big for a float variable returns infinity.
Tip Generally, you can't cast primitive types to or from reference or boolean data
types.
-5 9-
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
In Brief
In the previous chapter, we looked at the foundation of the Java language. You learned how to create
variables and write expressions. Real programs typically don't perform a fixed set of calculations,
however; rather, programs repeat steps or make decisions that control what steps to perform. Real
programs join multiple statements together into blocks. Blocks allow you to define pieces of your
program that you can then treat as a unit. For example, you might execute a certain piece of your
program only if some condition is true. You might want to execute the same set of steps for each
record in a database. Blocks make this sort of manipulation possible.
By using literals, variables, and operators, you create expressions. An expression is the smallest
piece of code that is executed and returns a value. The statement is the equivalent of a sentence in
Java. Not all statements return a value. A variable declaration is an example of a statement that
doesn't return a value.
Som e statements aren't expressions. Instead, they control how Java executes other statements.
You've already seen the if statement in other examples. It evaluates a Boolean expression. If the
expression is true, the if statement executes the code it controls; otherwise, that code does not
execute.
By default, the if statement (and most other control statements) affects only one statement. With that
in mind, consider the following three lines of code:
x=x+1;
if (x==100) x=0;
System.out.println(x);
The lines before and after the if statement will execute, no matter what. However, the x=0 statement
executes only when x is equal to 100.
Of course, you often want to do a series of statements when some condition is true. You can group
statements together with curly braces, { and }. All blocks begin with an open brace and end with a
matching closing brace. You can nest blocks — that is, put one block inside another. Here's an
example of nesting:
if (x==100)
int someValue;
someValue=y/100;
-6 0-
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
x=someValue+35;
y=y+1;
if (y==100)
int tmpval;
tmpval=9*z/5+32-someValue;
y=tmpval/2+y;
System.out.println(x);
The braces do two things. First, they define scope (the accessibility of variables). Variables declared
within braces are accessible only within that block (and any nested blocks). In the previous example,
all the code within the outer if statement can refer to the someValue variable. However, only the code
within the inner if statement can refer to the tmpva l variable. Outside the inner curly braces, tmpval
is not defined. The second function of the braces, of course, is to group multiple statements together
Y
so that each if statement controls multiple statements.
FL
In many contexts, you must use braces. For example, the definition of a class or method requires
braces. However, some statements use braces to define a block of code that the compiler treats as a
AM
if (x==10)
f(x);
The braces, in this c ase, are optional because there is just one line in the body of the if statement.
You could write this as:
if (x==10) f(x);
Because white space is irrelevant, you can also indent the one-line block to make it clearer that it is a
block:
if (x==10)
f(x);
-6 1 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
Note This notation is succinct. However, many programmers shy away from this
style, and you might, too, because you might later add more statements before
or after the f(x) statement. If you indent these new statements to line up with
the original one, you might think you've created a multi -statement block.
However, the compiler doesn't care how you lined it up; without the braces, the
if statement applies only to the next statement.
Sequencing
In addition to if, there are many other statements th at control execution. What's more, you can create
a block using curly braces anywhere (although it is typically bad form to do so). Normally, a block
begins execution at the beginning and— as you'd expect — terminates execution at the end of the
braces.
Two events, however, can cause execution of a block to stop before reaching the end of the block:
§ With certain types of loops, you can use the break or continue statements to force an
early end to the loop (see the Immediate Solutions for more information about these
statements).
§ An exception can cause a block to stop processing; when this happens, Java
searches for an appropriate exception handler. Exceptions occur when something
happens that requires exceptional processing. For example, if your program attempts
to divide by zero (an illegal operation), Java will raise an exception.
Java might signal an exception for many reasons. For example, when you divide by zero, Java
causes an exception to occur. Consider the simple program in Listing 3.1 .
System.out.println(100/denom);
-6 2-
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
new ZException().go(0);
java.lang.ArithmeticException: / by zero
at ZException.go(ZException.java:6)
at ZException.main(ZException.java:11)
This exception terminates your program. What if you want to print 0 if the input to the go method is
zero? You can, of course, simply test for this particular condition with an if statement. However,
exception handling provides a different technique, which has advantages you'll see soon.
Consider the program in Listing 3.2 . It also generates an exception, bu t now the program uses the try
keyword to detect exceptions in the block of code in the go method. When an exception occurs,
execution resumes at the catch keyword. Actually, each try statement can have multiple catch
keywords. Execution will continue at the catch keyword that matches the type of thrown exception
(more on that later).
try
System.out.println(100/denom);
-6 3-
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
catch (Exception e)
System.out.println(0);
new ZException().go(0);
As it stands, using the code in Listing 3.2 isn't much different from using an if statement to detect a
zero argument. However, the exception handling protects any amount of code and— if written
correctly— detects any error condition, not just the ones you've planned for. If you wanted to handle
only math errors (like the divide -by-zero error), you could replace the Exception class name in the
catch statement with ArithmeticException.
In fact, you can use multiple catch statements to handle different types of exceptions. The Exception
type is the most general and should appear last because Java processes catch blocks in order. If you
put a more general exception (like Exception) before a specific exception (like ArithmeticException),
the compiler will complain. Consider the example in Listing 3.3.
try
-6 4 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
System.out.println(100/denom);
catch (ArithmeticException e)
System.out.println(0);
new ZException().go(0);
What's really interesting about exceptions is that they can be handled in any calling routine. Java
searches the current block to find an exception handler. If one isn't found, Java begins searching
other active blocks. In other words, because main calls go, main could provide some or all exception
handlers for the code. This is useful when go knows that an error occurred but doesn't know what to
do about it. With e xceptions, each caller can specify its own error-handling code. Listing 3.4 shows an
example. The go method could continue to maintai n some exception handlers if you wanted to handle
some errors without sending them to the caller. Exceptions handled in the go routine would not
propagate to the main method.
Listing 3.4: Calling routines can handle exceptions.
-6 5-
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
System.out.println(100/denom);
try
new ZException().go(0);
catch (ArithmeticException e)
System.out.println(0);
It is possible to create your own exceptions for custom conditions. To do this, however, you need to
create your own objects (derived from Exception)— something we haven't covered yet. Then you can
use throw to generate the exception.
Types of Exceptions
The divide-by-zero exception is an example of an unchecked exception. You are not required to
handle these exceptions (although, as you've seen, you can). If an unchecked exception occurs and
you don't handle it, your program terminates.
-6 6 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
Many exceptions are checked exceptions, however. A method that performs operations that might
generate a checked exception must handle it in one of two ways. First, the method can provide the
appropriate try and catch blocks that will handle the exception. Second, the method can specify the
exception in the throws statement for the method. This tells the compiler that the method's callers
must handle the exception (or delegate it to their callers).
For example, suppose you are writing a method named go. It will call another method called work.
The work method might throw a checked exception called CustomException. If the go method
doesn't specify a matching exception handler, it must specify the exception name in its throws
clause:
. . .
work();
. . .
Block Cleanup
if (using_a_file == true)
open_a_file();
process_data();
close_the_file();
This block does fine when everything works normally. If process_data throws an exception, however,
close_the_file never executes. Presumably, this leaves the file open, and that isn't a good idea.
The answer to this problem is to use a finally block (which you must use with a try statement). The
code in a finally block executes when the main block ends for any reason (including when no
exceptions occur). Listing 3.5 shows an example.
Listing 3.5: The finally block executes at the end of its main block in all cases.
-67 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
try
System.out.println(100/denom);
catch (ArithmeticException e)
System.out.println(0);
finally
System.out.println("Go complete");
obj.go(0);
obj.go(50);
-6 8 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
Style Guidelines
Because Java is white-space-independent, you have a lot of leeway in formatting your source code.
Four major elements affect the readability of your code, although they are not pertinent to the
program's execution. First, spacing between lines can help distinguish code blocks. Second, the
position and alignment of braces can help readers follow the structure of your program. Third, since
white space isn't important to the compiler, you can indent your code to show what parts of the
program go together. Finally, you can use spaces (including new lines) to separate portions of
statements and make them more readable.
Each line of code should fit on a printed page; this guideline gives you about 80 characters per line.
Most people prefer to read code with lots of spaces instead of code that is jammed together with
minimal white space. Consider the difference that proper line spacing and self- descriptive names
make in the example that follows at the top of the next page. The first two lines are valid Java but are
hard to read. The same code is rewritten below those first two lines to illustrate the preferred way to
write code.
for(i =0;i<j;i++){j--;i++;n+=i+j;++n;}
colorFlag--;
count++;
++customerNumber;
-6 9 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
Some programmers place the starting brace at the end of the conditional statement or on the next line
directly under the first letter of the keyword. It is easier to find the start and end of a block by finding
braces that line up vertically. The eyes just work better that way. On the other hand, most braces in
most of the world's source code (for example, the Sun documentation) start at the end of the first line
rather than underneath on the second line. This book generally uses our personal preference— brace
underneath.
Whatever brace style you use, please be consistent. Use one of these:
statement;
or:
statement;
Some people like to line up the braces with the code they surround. For example:
statement;
Indenting code makes it easier to read. The idea is to indent the same amount for all statements that
are in the same block. How many spaces you indent isn't important, but all the code in a block should
line up. Many text editors will automatically indent with spaces or tabs for you.
Spaces
The spaces affect the readability quite a bit. Which of the two following code snippets do you prefer?
int count=5,colorFlag=97,customerNumber=40;
customerNumber= customerNumber*colorFlag+(count+count*32);
-7 0-
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
Even though the only difference between the two is spacing, the second is obviously better. Use lots
of spaces.
Immediate Solutions
Using Statements
A statement is the combination of variables, operators, and meth od calls in one Java sentence that
represents a complete unit of execution. Table 3.1 shows the common Java statements you'll
encounter.
Type Example
Empty statement ;
Y carPrice = 38933.72;
FL
Assignment statement
AM
System.out.print("Welcome" + employeeName);
TE
{statements}
Block statement
-7 1-
Team-Fly®
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
Type Example
Defining Blocks
Statements can contain expressions and even other statements. A block is defined as a bunch of
statements and local -variable declaration statements within curly braces, { and }. Blocks have the
following form:
statement_1;
statement_2;
statement_3;
The empty statement does nothing. It is useful when you want a placeholder for a construct that
requires a statement, but you aren't ready to write the code yet. For example:
Defining Scope
The scope defines where, in a program, you can refer to a variable— in other words, its accessibility.
Also, the scope defines when the variable is created and destroyed. The location of a variable's
declaration defines the variable's scope.
The scope of a variable is anything to the right of the declaration (including other declarations on the
same line) and down within the rest of the block (including all nested blocks ) in which it was declared.
-7 2 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
In Chapter 4 you'll see that another consideration is a variable's (and a class's) visibility. This affects
how other classes can interact with the variables you declare.
The if statement executes a set of statements if a Boolean expression is true. The if statement has
the following forms:
//Simple if:
if (condition)
statements;
if(condition)
statement(s);
}else
statement(s);
if(condition_1)
statement(s);
} else if(condition_2)
statement(s)
}else if(condition_3)
statement(s);
}else
-7 3 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
statement(s);
}
The following program is an adaptation of Sun's random number generator. There is one if-else
statement that tests for a user-provided seed number for the generator. If there isn't a seed number,
then the program generates its own seed as an integer (a long) based on the system time in
milliseconds (the num ber of them since January 1, 1970, 00:00:00):
import java.util.*;
if (args.length > 0)
seedInitializer = Long.parseLong(seedString.trim());
} else
seedInitializer = date.getTime();
System.out.println( output );
-7 4 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
//returns:
// seed 87658
It is very common to use an if statement to set a variable to one of two values based on some logical
expression. For example:
minimumValue = firstValue;
} else
minimumValue = secondValue;
}
This construction is used so often that Java has a shortcut notation for it. The shortcut is called the
conditional operator , having the fo rm:
minimumValue =
shortValue = negative ?
new Short((short)-inputString.shortValue()) :
new Short((short)inputString.shortValue());
The switch statement evaluates an expression and attempts to match it with any number of case
statements. When Java finds a matching case statement, execution begins at that point. Execution
continues until the end of the switch statement or until a break occurs. (You'll find more about the
br eak statement later in the "Using the break Statement" section). Without the break statement, Java
continues executing even if it encounters more case statements. If no case statements match, you
can add a default label to specify code to execute. The default label is really a special form of case
statement that matches anything.
A switch statement has the following form:
switch (expression)
-7 5 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
case ABC:
statements;
case DEF:
statements;
statements;
}
You can use a switch statement to test for a valid character within a string. Do this by using a
switch-based test to parse a token of only alphanumeric characters. The following shows just the
switch portion of this test:
switch ( testCharacter )
case 'A': case 'B': case 'C': case 'D': case 'E':
case 'F': case 'G': case 'H': case 'I': case 'J':
case 'K': case 'L': case 'M': case 'N': case 'O':
case 'P': case 'Q': case 'R': case 'S': case 'T':
case 'U': case 'V': case 'W': case 'X': case 'Y':
case 'Z':
if ( convertToLower )
testCharacter =
Character.toLowerCase( testCharacter );
case 'a': case 'b': case 'c': case 'd': case 'e':
case 'f': case 'g': case 'h': case 'i': case 'j':
case 'k': case 'l': case 'm': case 'n': case 'o':
case 'p': case 'q': case 'r': case 's': case 't':
case 'u': case 'v': case 'w': case 'x': case 'y':
case 'z':
case '0': case '1': case '2': case '3': case '4':
-7 6 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
case '5': case '6': case '7': case '8': case '9':
token.append( testCharacter );
break;
default:
isCharacter = false;
break;
Tip One of the most limiting things about switch is that the case statement takes
only a constant primitive value. You can't write a switch statement, for example,
that matches strings (note that the previous example uses characters, not
strings).
while (condition)
statements;
}
Java evaluates the condition expression (which must be Boolean). If the expression is true, Java
executes the block. When the block execution is finished, Java reevaluates the condition expression.
If it is still true, the block repeats. This process continues until the condition is false. For example, this
code would print numbers from 5 down to 1:
int i=5;
while (--i!=0)
System.out.println(i);
Consider a program that uses a while loop to compare two strings based on the Unicode value of
each character in the strings. The program prints a negative number if the first String precedes the
second string in dictionary order. The program prints a positive integer if the opposite is true. The
program prints zero if the strings are equal. Here is a while loop that does the work:
char c1 = char1[position];
char c2 = char2[position];
if (c1 != c2)
-7 7 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
result = c1 - c2;
break;
++position;
char c3 = char3[position];
char c2 = char2[position];
if (c3 != c2)
result = c3 - c2;
break;
++position;
//returns:
The while loop always tests the condition before it executes any code. That means that if the
condition is initially false, the while loop's body will never execute.
Tip If you are certain that the loop must execute once, then use the do… while
statement instead of the while loop . Also, be careful about specifying an
expression that is never false so that the loop never terminates.
-7 8-
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
A do… while statement is the same as the while loop except for this one important difference: The
do… while loop always executes its statements at least once because the termination test doesn't
happen until the end of the loop. Here's an example:
int index;
do
System.out.print(i);
//prints: 12345678910
Tip Use the do loop when the number of loops to execute is uncertain. If you want to
loop a fixed number of times, use the for statement.
statements;
When Java first encounters a for statement, it executes the initialization clause. This can set an
initial value for a loop variable (i=0, for example), or you can declare a unique variable for the loop and
initialize it (int i=0). If you declare a variable here, its scope is just the body of the loop.
The next step is to evaluate the condition expression. If the condition is false, the loop does not
execute. Java repeats this test when the loop repeats.
If the body of the loop executes, the update clause evaluates at the end of the block, and then Java
tries the c ondition expression again. If the condition is true, the block repeats. If the expression is
false, the loop is over; Java skips the block and continues execution. This loop will print the numbers 1
to 10 on the console:
-7 9 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
The following program demonstrates using a for loop to march through the characters of a string to
build a hash value for the string:
System.out.println( output );
//returns:
You don't have to specify all three parts of the for loop if you don't want to. For example, if the loop is
already initialized, you can omit the initialization clause:
for (;i<10;i++) . . .
Of course, that assumes that i and any other variables you need are already set before you enter the
loop. You can even omit all three clauses if you want to loop forever (or until a break statement
occurs, which is the topic of the next section):
-8 0 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
The break statement is used to exit a block contained within a switch, while, do, or for statement. By
default, execution continues after the controlling statement. For example, this loop will exit if the loop
variable becomes negative:
for (;i==5;i--)
if (i<0) break;
}
Presumably, this break statement will prevent the problem in which i was less than 5 already. When i
becomes negative, the break statement will cause Java to stop executing the loop.
You can also break out of multiple loops by using a label (see the "Using Labeled Statements"
section).
{
TE
if (i==2) continue;
System.out.println(i);
This loop will print only 1 and 3. When i is 2, the continue statement causes the loop to skip that
iteration.
Sometimes when multiple loops are nested, you'll want to continue an outer loop from within an inner
loop. You can do that with labels.
Statements can have labels. You can refer to these labels with the continue and break statements.
Unlike variables, labels can have the same name as a package, class, interface, method, field,
parameter, or local variable.
outerloop:
-8 1-
Team-Fly®
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
System.out.println(i*10+j);
Here, the continue statement causes the i loop to start again instead of the j loop (which would start
again if you didn't use the label). Of course, you can also use break with a label if you want to exit the
outer loop instead of continuing it.
Use return to terminate the current method. The return statement terminates a method and
(optionally) sends back a value to the calling statement. You'll see more about the returnType
method when you start to write your own methods in Chapter 4.
The following program computes the length of the hypotenuse of a right triangle, where the sides of
the triangle are side_1 and side_2 . The return statement returns the length as a double data type:
return hypotenuse;
Tip You can embed a return inside any statement (such as for, do, switch, or if),
and it will terminate the whole method rather than just that loop. However, a
finally block will still execute.
Defining Methods 97
The try statement executes a block of code and handles exceptions that might occur during execution.
For example, the following method calls another method, compute , that might throw an Arithmetic -
-82 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
Exception (perhaps from a divide -by-zero error). If an exception occurs, the method returns 0, as
shown at the top of the next page:
int process(int z)
try
return compute(z);
catch (ArithmeticException e)
return 0;
You can add as many catch clauses as you need, putting more specific types before more general
types. Java searches from the top down until it finds a match. If there is no match, the exception
propagates to the method that called process (in this example). This continues until a matching
handler is found. If there is no handler, Java reports an error and terminates the program.
You can add a finally block to a try block. When the block under the try statement exits for any
reason (including a normal exit), the finally block executes.
The following is an adaptation from a finally statement used in Java's Timer class:
try
mainLoop();
} finally
synchronized(queue)
newTasksMayBeScheduled = false;
-83 -
Java 2 Core Language Little Black Book Chapter 3: Blocks and Statements
Tip Use finally to ensure that certain cleanup tasks are executed regardless of any
exceptions.
A throw statement forces an exception. This transfers control to the next try-catch statement that
matches the object named in the throw statement. The following code shows you how to use it:
try
Tip You'll get a compile-time error if you attempt to throw an object that is not
throwable. For example, you can't throw an int or a String.
-84 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
In Brief
Although primitive data types and control structures comprise the details of Java programming,
classes form the backbone of all Java programs. Although previous chapters have mentioned classes
and objects, they have not yet been discussed in detail. This chapter describes how Java uses
classes to create objects and why these ideas are important in all modern programming languages.
About Objects
§ Reuse— You'd like to be able to reuse code in multiple places both inside and outside
your program.
§ Encapsulation— Information about details should be accessible on a need-to-know
basis. For example, if you read a phone number from a database, only one part of
your program should know if the p hone number resides in a text file, in a SQL
database, or on a remote Internet server. Objects that provide uniform access to a
resource are said to encapsulate that resource. Suppose your program has one
object that knows how to retrieve phone numbers. If the source of the phone numbers
changes, only the one phone -number object requires modification.
§ Polymorphism— Polymorphism allows you to handle items as though they were of a
more generic type. For example, chocolate chip cookies and oatmeal cookies are
both types of cookies. For many purposes, the fact that they are cookies is enough
information. I might create a generic class that represents all cookies. Subclasses of
this object would represent specific kinds of cookies, but my program could treat the
specific types as the generic cookie class when it is handy to do so.
If you aren't familiar with object-oriented concepts, think of objects as smart data. Consider a program
that looks up phone numbers. In an object -oriented world, the phone number is likely to be an object.
The main program doesn't store phone numbers per se. Instead, it stores one or more phoneNumber
objects. When you construct a phoneNumber object, you provide a name. The details about how the
name is transformed into a number is up to the object. That's encapsulation .
An object like the phoneNumber object might be useful in several parts of your program. For
example, you might want to use a separate set of phoneNumber objects to handle fax numbers. If
you plan the class correctly, you'll also be able to pull it out of one program and put it in another
program with a minimum of hassle. That's reuse.
Suppose your program starts with a simple phoneNumber class that reads numbers from a text file.
As your user base grows, you decide you need to handle different databases and Internet servers.
-85 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
You can write specialized versions of the phoneNumber class to handle each case. One type of
phone number knows how to read data from the Windows address book. Another type of phone
number reads from Oracle databases. A third class looks up the number via a special Internet server.
There are two important points to know about this scenario. First, the main program doesn't need to
know about the details because of encapsulation. As long as the main program's interface to the
phone number remains unchanged, you don't care how it works.
The second point is that if you design the host of PhoneNumber classes correctly, your program can
treat all the specializations as a plain phone number. The fact that some use one database and others
use a different one is not material. That's polymorphism.
In Java, objects will expose variables (known as fields ) and functions (often called methods). Some of
these fields and methods will be visible to the outside world. These fields and methods constitute an
object's public interface. In the phone-number example, the object might expose one method called
lookup and another method called getNumber (or it might simply have a number field). Any object
that provides this functionality would work with your main program. Other methods and fields would
not be public, so the main program would not have access to them.
Inside Classes
In Java, everything you write (except import and package statements) will reside inside a class. It is
easy to think of classes as objects, but that isn't accurate. Classes aren't objects any more than
cookie cutters are cookies. A class provides a pattern that you can use to create one or more objects.
The items that make up the class are known as members. Members are accessible by only certain
parts of your program. For example, a class can declare a member private. Then only code in the
same class definition can access that member. A public member is visible to all programs. Members
can also be protected— something you'll read about shortly.
If you don't specify public , private, or some other access modifier, the member is visible to any class
that shares your class's package. Packages allow you to group related classes together.
Don't confuse local variables with fields. The placement of a variable determines its scope. If the
variable's declaration appears inside a method, the variable is local. If the declaration appears within
the class but outside any method, however, then you have a field (some-times called a member
variable). You don't specify the access to local variables because they have a well-defined scope and
are not accessible by any other part of your program anyway.
You can use a variety of modifiers to control the scope of a member. Table 4.1 shows the possible
modifiers (some of these modifiers apply only to methods).You'll see many of these used in the
"Immedia te Solutions" section.
Modifier Definition
-86 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
public
Accessible by any class in any package.
private
Accessible only to the class in which it is declared.
static Indicates a class variable (all objects that belong to the class
share it), rather than a variable maintained by each object.
final
Indicates a constant.
transient Indicates that the member won't be serialized nor the state saved.
volatile
Omits this member from certain compiler optimizations.
abstract
Marks a method as a placeholder; derived classes must supply
an implementation.
You can declare any variable to be final. Doing this enforces the rule that the value of this member
cannot change. The following variable declaration defines a variable that remains constant. This
variable is named MONA_LISA_PAINTER , whose value is Leonardo da Vinci:
You'll get a compile-time error if your code tries to change the value of MONA_LISA_PAINTER. By
convention (this is not a rule), the name of a constant is written in uppercase letters.
The static modifier indicates that the member belongs to the class, not to a particular object. Suppose
you wanted to track how many phone numbers the phoneNumber object retrieved. Where would you
store that value? It doesn't belong with any one phone number because the value applies to all phone
numbers. To solve this problem, you could store the number in a static variable. To extend the
cookie-cutter analogy, if a class is a cookie cutter and an object is a cookie, static variables might
include a counter built into the cookie cutter to count cookies and a timer to measure elapsed time.
These things apply to all the cookies, not just to one.
-87 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
Constructors
When you create an object, you use the new operator to instantiate an object from a class. A String is
an object, so you might write:
This statement creates a new, empty string. The second occurrence of the word String is a call to a
special method known as a constructor. The constructor's name is always the same as the class
name. Java allows you to have multiple methods with the same name (as long as they have different
parameters), so one class can have many different constructors.
As with any method, you can also provide arguments for this special constructor. You could write:
When you write your own classes, you'll provide a constructor for every case you want to handle. If
you don't provide any constructors, Java creates a default constructor (a constructor method with no
arguments) for you. If you provide any constructor, however, Java won't add a default for you; you'll
have to code it if you want a default constructor. Of course, some objects always require construction
arguments and therefore don't have default constructors.
A Simple Object
public class T
System.out.println(msg);
test.printMsg();
This is a complete program (it includes a test main to exercise the method within the object). Notice
that there is no constructor; the program uses the default constructor. This is possible because you
-8 8-
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
can initialize member variables without using a constructor (in this case, setting msg to "Wow!" during
the variable's declaration).
You could specify a constructor to allow the main program to set the message:
public class T
System.out.println(msg);
test.printMsg();
The msg field is protected. This status is similar to private. In the next section, however, you'll see
that the protected modifier allows subordinate objects to access this field.
In this case, if you wanted to continue to allow a default constructor, you'd have to specifically write it,
adding this line, for example:
Extending Objects
Many times you need to create an object that is almost like an existing object but with slight
differences. In this situation, you can extend the existing object. When you extend an object, you
inherit all of its members marked as public (unless you choose to override them). You can also add
new public members. In addition, your new class can access items in the original class marked as
protected (but not private).
For example, suppose the simple class from the last example (T) is almost what you need, but you
want another method to print the string in uppercase. You can write:
public Tupper(String s)
-89 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
System.out.println(msg.toUpperCase());
In this case, you say that class Tupper extends T. That makes T the base class for Tupper , and
Tupper derives from T.
This new class is just like T but includes an extra method. The Tupper class has the same members
as the T class (except for the constructor). Notice that each class must provide its own constructors
(unless the base class has a default constructor).
You could just as easily replace printMsg with a new version instead of creating a new method. For
example:
public Tupper(String s)
System.out.println(msg.toUpperCase());
The super keyword refers to the base class. As a special case, you can use this keyword as the first
line in a constructor to call a particular constructor in the base class. You can also use this keyword
anywhere in any method to access methods in the base class. For example:
-9 0-
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
super.printMsg();
System.out.println(msg.toUpperCase());
}
This is a good example of polymorphism. Consider this main method:
test.printMsg();
Notice that the variable test is of type T. When you run the program, however, it will execute Tupper 's
printMsg method. Here, Tupper is a kind of T. In fact, any class that extends T is a kind of T.
Moreover, classes that extend Tupper are not o nly kinds of Tupper, but they are also kinds of T.
Interfaces
Using the extends keyword not only supports polymorphism but also handles code reuse— two major
Y
goals of object-oriented programming. However, sometimes you want an object that has attributes of
FL
two different base classes. Java doesn't directly support this capability; each class can have only one
base class (although that base class might, of course, extend another class).
AM
Suppose you build a class named Vehicle . Classes such as Car , Truck , and Motorcycle would be
obvious subclasses. You might construct another class named Appliance. Subclasses of Appliance
would include Dishwasher, Stove , and Freezer . These class hierarchies don't seem to have much in
TE
common at first glance, but what about an ice cream truck? It is a truck, but it is also a freezer. Which
class would you extend — Truck or Freezer? You must pick one.
To work around this problem, Java introduces the idea of an interface . You define an interface in a
similar way to defining a class, but you don't provide any code for the interface. Classes that should
be polymorphic with other objects must implement the interface— that is, supply the code. Programs
can treat any object that implements an interface as though it were an object of the nonexistent class
that corresponds to the interface.
interface Printable
-9 1 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
int n;
String s;
System.out.println("String=" + s);
public class T1
p.print();
p=new T3("Coriolis");
p.print();
Because both classes (T2 and T3) implement Printable , they must include the methods defined in
that interface (one method; in this case, print). What these classes do in that method is their own
business, but they must include it. (Not including the interface methods will earn you a compile-time
error.) Because each object contains a print method, the main method can treat them both as a
Printable object (which isn't really an object at all). So T2 and T3 are polymorphic, but they don't
share any code or base classes (except, of course, for Object, which is the eventual base class of all
objects).
Another interesting point about the previous code is that the constructors use the same parameter
name as the field they set. For example:
-9 2-
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
int n;
Packages
When you don't specify any package, your class belongs to the default package. However, most
classes you use will belong to a package. For example, every time you use a String object, you are
using an object from the java.lang package.
You can create your own package by simply placing a package directive at the start of your source
file. When you create a class in a package, the generated class file must reside in a subdirectory of a
directory listed in CLASSPATH or in the same subdirectory of a JAR (or ZIP) file that resides in a
directory named in the CLASSPATH.
For example, if you create a class in the package com.coriolis, then a directory or JAR or ZIP file in
your CLASSPATH must contain a subdirectory called /com/coriolis (or \com \coriolis, if yo u prefer). By
convention, you should select a package name that includes your domain name (if you have one)
reversed (in other words, com.coriolis, not coriolis.com ). This convention allows most packages to
reside in one of a few top-level directories (com, net, org, and so on). You can have arbitrary levels in
a package, so you can put anything you like after the reversed domain name
(com.coriolis.jlbb.samples, for example).
When your class is in one package and you want to use a class in a different package, you must
specify the entire name (for example, com.coriolis.jlbb.samples.testClass). The alternative, of
course, is to import the class or the entire package. You don't need to fully specify classes in your
own package or in java.lang.
Immediate Solutions
Fields may be public , protected, package , or private. These modifiers control how fields are used
outside of the class that defines them — their visibility. Before we can discuss visibility directly, we
must first revisit the idea of scope. Say you have a variable named phoneRinger:
int phoneRinger = 5;
This declaration defines phoneRinger as an integer and initializes it to 5. The parts of the program
that can use this variable are determined by its placement in the source code. You can determine
what can access phoneRinger by checking the nearest preceding curly brace. Everything between
that brace and its matching closing brace has access to the variable.
-9 3-
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
If you place your variable declaration inside a method, then the variable is reachable only inside that
method. Listing 4.1 demonstrates the scope of variables.
int minValue = 1;
System.out.println("testVariableScope.minValue = " +
newMinValue );
int minValue = 2;
System.out.println("testVariableScope.minValue = " +
minValue );
return minValue;
//returns:
// main.minValue = 1
//testVariableScope.minValue = 2
//main.minValue = 1
-9 4 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
//testVariableScope.minValue = 2
You can see that the original declaration of minValue in main is 1. A variable with the same name
also appears in a second method named testVariableScope . Although these two variables have the
same name, they are completely unrelated.
The scope of the minValue variable is the main method. That means that every statement in main
can use this variable. It also means that if a statement in main changes the value, then all subsequent
statements that access that variable will see the new value. This also applies to the separate variable
by the same name in the testVariableScope method. All statements in the testVariableScope
method can see its own minValue . The two variables are oblivious to one another.
One occurrence of minValue has no effect on the other. You can pass the value between methods,
however. This happens when the testVariableScope method is called, and it returns the value of its
own minValue variable to the calling statement in the main method. Still, the scope or accessibility of
each variable is confined to its own method.
These two variables are local variables. This means that they can be used only in the method in which
they are declared. The program in Listing 4.2 demonstrates the scope of variables, whether local or
member, and shows how the access modifiers affect them.
import java.lang.reflect.*;
class Trunk
//privateModifier, defaultAccessLevel
} {
-9 5-
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
//privateModifier, defaultAccessLevel
pineTrunk.TrunkVariables();
pineTrunkBranch.BranchVariables();
//error-packageModifier,protectedModifier,privateModifier
//print pineTrunk.publicModifier,pineTrunk.packageModifier
// pineTrunk.protectedModifier,pineTrunk.protectedModifier
// pineTrunk.privateModifier = error
-9 6 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
// pineTrunkBranch.publicModifier
// pineTrunkBranch.packageModifier
// pineTrunkBranch.protectedModifier
// pineTrunkBranch.privateModifier = error
// defaultAccessLevel );
try
Class c = Class.forName("Trunk");
int m = c.getModifiers();
if (Modifier.isPublic(m))
System.out.println("pineTrunk=public");
if (Modifier.isPrivate(m))
System.out.println("pineTrunk=private");
int mod = 0;
index++)
mod = declaredFields[index].getModifiers();
System.out.println(declaredFields[index].toString());
-97 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
//returns:
//java.lang.String Trunk.packageModifier
-9 8 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
//java.lang.String Trunk.defaultAccessLevel
This program shows you how to control access to variables with access modifiers. Other modifiers are
covered later in this chapter.
Often, it is useful to define a constant value. For example, you might want to create a variable named
pi that contains the value 3.1415927. Of course, you could just use a simple variable. When the value
is a constant, however, using a simple variable has two drawbacks. First, an errant part of the
program might accidentally change the value. And second, the compiler might be able to generate
more efficient code if it knows the value of a constant can't change.
Because you can't change a final value, you must supply an initial value when declaring this type of
variable. You can also apply final to classes. In this context, final means that you can't extend the
class to form a new class. A final method is one that subclasses can't override.
Keep in mind that for reference types (objects and arrays), a final modifier makes only the reference
final. You can still alter the contents of the object or array. For example, consider this declaration:
iary[4]=10;
Sometimes you want a field to apply to all instances of a class. You can do this with the static
modifier. A static (or class) field exists even when no object instances exist. When you do instantiate
the object, all the instances share the same static variable. Suppose you have a simple object, and
you want to track how many times you've created it. Listing 4.3 shows a solution using a static field,
newCount.
class StaticDemonstration
-9 9 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
StaticDemonstration() { newCount++; }
work();
System.out.println(StaticDemonstration.newCount);
}
Related solution: Found on page:
Defining Methods
In Chapter 3 , you encountered blocks and statements. You've also seen methods throughout the
book. A method is a group of variables and statements that functions together as a logical unit. Like
fields, methods can have modifiers (like private , public, or static). Methods also have a return type
(which may be void if the method returns nothing) . This return type can be a reference type (such as
an object or an array).
A method can have any number of parameters or arguments. When another part of the program calls
the method, Java copies the arguments and passes the copies to the method. For simple types, the
method gets a private copy. For reference types, any changes the method makes to the parameter
will appear in the calling program as well.
-100 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
class methods
y=33;
ary[0]=50;
int v=100;
a[0]=22;
x(v,a);
Y
System.out.println("V=" + v + " a[0]=" + a[0]);
FL
}
AM
You'll notice that method x changes the array (as seen by main) but doesn't affect the simple integer
TE
because the method is changing only a local copy of the data. The following rules apply to
parameters:
§ You can declare a method without parameters by using an empty pair of parentheses.
§ No duplicate parameters are allowed in a method.
§ A final parameter cannot be assigned within the body of the method.
§ You can refer to a parameter with the simple name in the body of the method.
§ The scope of a parameter is the entire body of the method.
§ If a parameter has the same name as a class member, it is the parameter (not the
class member) that is referred to within the body of that method. The class member is
hidden by the parameter.
§ Parameter names cannot be redeclared as local variables or as parameters of catch
or try clauses.
Within a class, each method must have a unique signature. The signature is the method's name and its
argument types. So, for example, you can write a method named print that takes an integer argument,
and then you can write another method named print that requires a String argument. Still another version
might accept two integers and a floating -point number. This is known as overloading a method . Of course,
-101 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
methods in different classes can have the same name w ith no restrictions.
A method has two primary parts— the declaration and the body. The declaration defines the attributes,
including access level, return type, name, and parameters. The body contains all the statements.
Let's look more closely at the elemen ts of a method declaration, as shown in Table 4.2.
Modifier Definition
private
Accessible only to the class in which the method is declared.
final
Indicates a method that cannot be overridden by subclasses.
synchronized
Prevents multiple threads using this method from stepping on each
other.
returnType Indicates the data type of the return value. Use void if nothing is
returned.
methodName
Can be any legal Java identifier.
exceptions
Indicate the exceptions your method throws.
-102 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
Earlier, you saw that you can control access to a field by using public, protected, package, and
private modifiers. These access modifiers also apply to methods. The program in Listing 4.4
demonstrates the effect they have on a method.
import java.lang.reflect.*;
class Apple
{ System.out.println( accessor ); }
{ System.out.println( accessor );
appleMethod ("applePieMethod"); }
class Orange
{ System.out.println( accessor ); } }
class Grape
-103 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
{ System.out.println( accessor ); }
//applePieMethod("MethodAccessLevel.main"); //error
apple.appleMethod("MethodAccessLevel.main");
applePie.applePieMethod("MethodAccessLevel.main");
grape.grapeMethod("MethodAccessLevel.main");
//orange.orangeMethod("MethodAccessLevel.main"); //error
report.methodReport("Apple");
report.methodReport("ApplePie");
report.methodReport("Grape");
report.methodReport("Orange");
-104 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
class MethodReporter
try
Class c = Class.forName(className);
index++)
Class[] exceptions =
declaredMethods[index].getExceptionTypes();
count++)
{ System.out.println( exceptions[count] ); }
Class[] parameters =
declaredMethods[index].getParameterTypes();
-105 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
count++)
{System.out.println( parameters[count].getName());}
//declaredMethods[index].getReturnType().toString()
System.out.println(declaredMethods[index].toString());
//________________________
//class = Apple
//java.lang.String
//void
//________________________
-106 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
As you can see, using the access level is a nice way to control which classes can use each other. The
access levels for methods parallel very closely the access levels for fields.
Another option you can specify in a method is the throws clause. This clause informs Java which
checked exceptions the method might throw (and therefore, which exceptions the caller must catch).
For example:
}
You can read more about exception handling in Chapter 3.
You can declare a method as final. Whereas final makes a field into a constant, it has a different
meaning for a method. A final method can't be overridden in a derived class. An example looks like
this:
// do something here
We have covered variables, statements, blocks, and methods. Many of the previous sample
programs have included classes. Now it is tim e to formally define a class and then use one. When we
talk about objects, we are technically talking about the use or instance of a class, not the class itself.
Before we get to objects and object-oriented programming topics (inheritance), we must begin w ith
the class. The following is a simple class:
-107 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
{ this.size = initialSize; }
The first line starts with the access modifier public. This is followed by the class name ApplePie. The
keywor d class tells the compiler that this is, of course, a class. The keyword extends indicates that
this class will inherit the Apple class. The implements keyword means that this class will include the
methods defined in the Fruit interface. Table 4.3 lists the elements of a class declaration.
Element Description
public Indicates that the class can be used by all classes in all packages; if a
class is not public , only other classes in the same package can use it.
final
Indicates that the class cann ot be subclassed.
class
Tells the compiler that what follows is a class.
implements
Implements one or more interfaces (you supply a comma-separated list
of interfaces).
The public modifier says that this class can be used by any class in any package. Without it, the class
can be used by other classes in the same package only, not by classes from other packages. An
abstract class is one that cannot be instantiated. Why would you do that? An abstract method is
useful as a base class that represents something that isn't a real object. For example, an object for
dogs and another for cats might share a common base class (Animal). There's no such creature
called "animal." An animal is an abstract category of other, specific creatures (such as dogs and cats).
You could make the Animal class abstract to prevent instantiation of the object.
-108 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
The final modifier prevents a class from being extended. This enforces programming discipline and
can help the compiler generate better code.
You can make a class abstract with the abstract modifier. The following code shows you how:
{ return (byte)intValue(); }
{ return (short)intValue(); }
An abstract class acts like a template for other classes. It becomes the superclass of classes that
inherit it (said to be subclasses). This example is adapted from Java's Number class. This Number
class is actually the superclass for the BigDecimal, BigInteger, Byte , Double, Float, Integer, Long,
and Short classes. These are the wrappers for the actual primitive data types of the same name
(such as int and short ). There is no such thing as a Number type; there are only specific types of
Numbers represented by subclasses of this abstract class.
Methods can also be abstract, and a class with abstract methods must be an abstract class.
Marking a method as abstract means that derived classes must override the method, and you are not
required to provide a definition for it in the abstract class.
All Java classes have constructors. If you don't explicitly write one, Java will automatically provide a
default constructor. It doesn't do anything, but it's there anyway. You use cons tructors to ensure that
an object is prepared for use. Generally, you place initialization code in a constructor. When that class
is instantiated somewhere, the constructor is automatically called as part of the instantiation. Because
-109 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
this happens first, it's your chance to set up variables to your liking before the calling class can do any
damage.
Suppose you have a class called Car . You can provide a constructor for it like this:
tank = condition;
tires = condition;
}
This class has two class members: tank and tires. The constructor sets these variables based on a
parameter (condition):
You can control the visibility (which other objects can see it) of your class with an access modifier in
the constructor's declaration. Table 4.4 lists these constructor modifiers.
Tip Use constructors to ensure that you control how your objects start life.
Modifier Description
protected
Only subclasses and classes in the same package can instantiate the constructor.
public
Any class in any package can instantiate the constructor.
default Any class within only this package can instantiate the constructor.
-110 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
Declaring an Interface
Interfaces can extend other interfaces. Here's how you can declare an interface in your program:
statement(s);
§ An abstract class can have method bodies (implemented), but an interface cannot.
§
Y
A class can have only one superclass (extends one abstract) but many interfaces
FL
(implements a comma-separated list of interfaces).
§ An interface is not subclassed and so is not part of the class hierarchy. Any class can
implement any interface.
AM
If a class implements an interface, then the class must use all the methods exactly as they are found
in the interface. The interface body includes a group of method declarations without a body (a
TE
Tip You cannot use the private , protected, transient, volatile, or synchronized
modifiers in a member declaration in an interface.
Using Packages
Every Java program uses at least one package. If you compiled the program listings in this book, you
were automatically using the default package (not named). This is the way to group classes and
interfaces (specialized classes) together. A package groups classes and interfaces together, allowing
access and namespace management.
package fruit;
{ statement(s); }
-111 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
{ statement(s); }
{ statement(s); }
You do not use braces around the package— it applies to the entire file. All classes and interfaces in
this source file are considered part of the package declared at the top with the package keyword and
the package name terminated with a semicolon.
Tip Program mers strive to make package names unique, as Internet addresses are.
Many programmers begin their package names with their reversed Internet
domain name, like so: com.coriolis.publishPackage. This is done to avoid
name collisions. The reversal prevents you from having many top-level
directories that all have com subdirectories.
The compiler and the JVM (Java Virtual Machine) use the package name by simply looking in the
directory of the same name. So, for example, a class in the com.coriolis.publishPackage package
will be in the com\coriolis\publishPackage directory. Alternatively, you can store the class file in a
subdirectory stored inside a JAR file.
The most important effect on classes lies in how the package controls access. As you have seen
earlier in this chapter, the class access modifier public allows classes from any package to access
the class; if you omit the public modifier, however, then only classes within the same package can
access that class.
If you want to use classes outside of a given package, you'll usually import them like this:
import java.util.Dictionary;
import java.util.Enumeration;
Without these imports, you'd have to fully qualify the package name each time you use it. The
previous import statements can be condensed to just the following:
import java.util.*;
The wildcard (*) tells Java to get all the classes in the package. This approach isn't as efficient at
compile time, but it doesn't affect the runtime performance of your program. The compiler grabs what
it needs from o ther packages only when it comes across the import statement. It is a good idea to
import explicitly just the actual classes you need. Not only does it make your compiles faster, but it
-112 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
also prevents ambiguity that might needlessly arise if you import two packages that have identically
named classes.
Tip Sometimes you need two classes from two packages that have the same name.
In this case, just use the fully qualified name instead of using import.
Understanding Inheritance
A subclass inherits variables and methods from its parent or super-class. If the superclass is a
subclass of another class, then the subclass of the superclass also inherits variables and methods
from the super-class of the superclass (the grandparent). This inheritance works for all ancestors. A
class that is a subclass can use the superclass's members (variables and methods) in one of three
ways. It can use them as is, hide them (sometimes known as shadowing ), or override them.
Tip The super keyword allows a subclass to access hidden variables and overridden
methods of the superclass, like this: super.color().
Overriding Methods
Sometimes you inherit a method that doesn't meet the requirements for a subclass. When this
happens, you can override the method. This means that you write a new method (the overriding
method) with the same return type, name, and parameter list (same signature) as the inherited
method (the overridden method). A method signature is the name of the method and its parameters
(in other words, foo(int) is different from foo(float) or foo()). Listing 4.5 shows you how to override
one method in a superclass with another method of the same signature in a subclass.
import java.lang.reflect.*;
class Apple
{ System.out.println( accessor ); }
-113 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
{ System.out.println( accessor ); }
{ super.appleMethod("applePie.superAppleMethod()"); }
apple.appleMethod("MethodAccessLevel.main");
applePie.appleMethod("MethodAccessLevel.main");
applePie.superAppleMethod();
You can see that the two method signatures are the same. This approach is contrasted with
overloading, in which the method name is the same but the parameter list differs by at least one
parameter type or name.
-114 -
Java 2 Core Language Little Black Book Chapter 4: Methods, Classes, and Packages
Overloading Methods
Earlier in this chapter, we saw how the signature of a method is defined (name, parameters).
Overloading allows you to have multiple methods with the same name but different parameters. The
return value is not considered, so you can't write two methods that only differ in their return types.
There is no explicit declaration for overloading. Java just figures it out like this:
statements(s);
int offset)
statements(s);
}
You can see that the two method signatures are the same except for the extra offset parameter in the
second one. That one difference is enough to create two entirely different methods in Java. This is
very handy. If you need a method that can be called with various parameter lists, then overload it. A
good example of overloading is the System.out.print method. You can pass it any primitive -type
variable, and the method will create a string for it.
-115 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
In Brief
In earlier chapters, you examined various control structures such as if and while. These control how
your program executes. Another crucial element of most programs is the way they represent the data
they manipulate. Selecting the proper data structure can make your program virtually write itself.
Conversely, an incorrect choice of data structures can make a simple program difficult to write.
In a way, Java's classes are super-sized data structures — they contain not only data but also the
programming instructions that operate on the data. In fact, you can model any data structure with a
class, and Java's library is full of data-structure classes.
In Chapter 2 , you learned something about simple data types, such as int, and you learned about
arrays. An array is a simple form of data structure, but arrays are not always the perfect data structure.
For example, suppose you want to store a list of phone numbers and retrieve them by name. You
could do this with arrays, but a more sophisticated data structure might do a better job.
Collections
Java has had collections classes for some time, but Sun beefed up support in Java 2 SDK 1.2 — the
version that added the collections framework. In particular, the framework provides a common
interface to a variety of collections (sometimes known as containers). Having a common set of
methods that apply to different collections makes it easy to interchange collections classes and
reduces the learning curve because you have only a few unique methods to learn.
Java provides several collections classes. Each type has a special focus (such as quick insertion or
quick lookup) that makes it better for some applications but a poor choice for others. For example, if
you are building an electronic phonebook, you have two primary functional considerations: The
creation and deletion of new entries can be slow, but the lookup must be extremely fast. Given these
two constraints, Hashtable is the best collection to use for your phonebook. Using the correct data
structures is crucial because each one is optimized for a different operation.
Table 5.1 lists methods common to most collections. Of course, each class might have specific
features that relate to its special features. Many collections implement the methods that appear in
Table 5.2, for example, but these don't apply to all collections.
-116 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
hashCode() int Returns the hash code's value for this collection.
-117 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
One limitation of ordinary arrays is that they are fixed in size. Arrays are very fast, but they have
limitations. How do you insert an element into the array? How do you ensure that there are no
duplicate elements? How do you sort all the elements? These operations require you to write
code— often inefficient code (inserting an element, for example, requires that you move all the
subsequent entries in the array).
Collections can do all of this and more. They fall into three broad categories. List-type classes store
data in some sort of sequence. The Set grouping of classes create s objects that store unique values.
You can't create duplicate entries. Finally, the Map grouping of classes creates objects that create a
dictionary where your program can look up a value by providing a unique key (which might, for
example, be a string that contains a name).
As you might expect, each of these broad categories has its own interface (see Chapter 4). In addition
to the interfaces, a number of actual classes provides implementations for these interfaces.
A collection contains elements, just as an array does. The Collection interface generalizes behavior,
such as adding, removing, and counting elements. Underneath this master interface are three
subinterfaces:
List, Set, and Map. Within these three interfaces are many concrete implementations (classes),
shown below with descriptions of their primary uses:
§ List— A collection that has a distinct order of elements.
-118 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
Some of the collections are actually arrays underneath, wrapped in a class that adds functionality.
Other collections use a different internal representation, but, thanks to encapsulation, you needn't be
concerned about that.
Immediate Solutions
Copying Arrays
Internally, many collections store data in an array. You can use some special techniques to copy
arrays more efficiently (and the Java library does use these special techniques). For instance, when
you want to copy an array, or only a portion of it, to anothe r array, use the arraycopy method. The
arraycopy method requires five arguments. Two of the arguments are the arrays you are copying to
and from. The other three arguments indicate the starting location in both arrays and the number of
elements to copy. Here is a template:
int copyFromArrayIndex,
Object copyToArray,
int copyToArrayIndex,
int numberOfElementsToCopy);
-119 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
The following program shows you how to copy a portion of an array (elements two, three, and four in
the third row of EmployeeNames) into another array (EmployeeNamesWhoGetRaises ):
String[][] employeeNames =
};
System.arraycopy(employeeNames[2], 1,
employeeNamesWhoGetRaises, 0, 3);
int employeeNamesWhoGetRaises_Length =
employeeNamesWhoGetRaises.length;
System.out.println();
index++)
-120-
Java 2 Core Language Little Black Book Chapter 5: Data Structures
System.out.print(employeeNamesWhoGetRaises
//returns:
Found
Related
on
solution:
page:
45
Declaring
Variables and
Arrays
http://w ww.inforobo.com/javacorelanguage/) demonstrate all the actions you can take on an array of
primitive data types:
TE
System.out.println(" -- integerArray");
int[] integerArrayCopy;
-121-
Team-Fly®
Java 2 Core Language Little Black Book Chapter 5: Data Structures
integerArray);
areArraysEqual = Arrays.equals(integerArrayCopy_2,
integerArray);
Arrays.sort(integerArray);
//returns:
//519 332 172 993 492 789 994 180 414 521 -- randomValues
//172 180 332 414 492 519 521 789 993 994 -- Arrays.sort()
// 2 -- Arrays.binarySearch(integerArray, 18)
Tip If you assign one array to another, they remain equal. What you do to one will
appear to be done to the other. This occurs because they actually point to the
same object.
Using Vectors
The Vector class is the most like a normal array. Remember that ordinary arrays are fixed in size, but
you can easily change the size of a Vector object whenever you want. As you can with an array, you
can access items in a Vector object by using an integer index.
-122 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
The Vector class holds objects, not primitive types. Java provides wrapper classes for all the primitive
types you could use to store those types in a Vector class (for example, the Integer class wraps an
int). Listing 5.1 shows an example of using a Vector class.
Listing 5.1: Using the Vector class.
import java.util.* ;
"Brass", "Percussion"};
band.addElement(firstArray);
band.addElement(lastArray);
System.out.println();
-123 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
System.out.println();
//returns:
As you add and remove items from a Vector object, it resizes to fit. You will need to manage this
resizing yourself for projects where performance is crucial (using fewer resizes results in faster
programs). Here are some example Vector manipulations, taken from the
VectorDemonstration.java program (found at the previously cited http://www.inforobo.com Web site):
import java.util.* ;
class VectorDemonstration
System.out.print("empty vector" );
-124 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
employeeNames.addElement("Laura");
employeeNames.addElement("Patricia");
employeeNames.addElement("Devyn");
employeeNames.addElement("Marianne");
employeeNames.addElement("Shane");
employeeNames.addElement("Kasienne");
employeeNames.addElement("Ann");
employeeNames.trimToSize();
//employeeNames.contains("Devyn") );
//employeeNames.indexOf("Devyn") );
//employeeNames.removeElement("Devyn") );
//employeeNames.contains("Devyn") );
//employeeNames.lastElement() );
//employeeNames.firstElement() );
-125 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
//returns:
//.contains("Devyn"): true
//.indexOf("Devyn"): 2
//.removeElement("Devyn"): true
//.contains("Devyn"): false
//.lastElement(): Ann
//.firstElement():Laura
(oldCapacity + capacityIncrement) :
(oldCapacity * 2);
newCapacity = minCapacity;
-126 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
}
The previous routine illustrates how Java grows a Vector. The highlighted lines show where Java
figures out how big to make the Vector. Remember that underneath, a Vector is just an array. This
routine is designed to calculate how big to make the array. When the Vector runs out of room, it
doubles in size. You can plainly see there is no
magic here. A new array is created that is double the size of the old one. Then Java calls the
System.arraycopy method to copy the elements from the old array to the new one.
modCount++;
ensureCapacityHelper(elementCount + 1);
elementCount - index);
elementData[index] = obj;
elementCount++; }
The previous method reveals the Vector 's internal algorithm. When you insert an element into a
Vector, all the elements at the point of insertion are moved up one spot (copied with
System.arraycopy), leaving an open spot into which the new element is placed. This is
straightforward, but you can see how this operation could affect your program's performance.
The ArrayList class (covered shortly) works in nearly the same way as a Vector .
Tip Inserting elements into a Vector is a slow process, so use one of the List
collections.
You often need a way to process each element in a collection. Java provides an Iterator interface to
simplify this task. Each collection has an iterator method that returns some object that implements
the Iterator interface. You don't know the exact type of the object, but then again you don't care— it
implements Iterator , so you can treat it as though it were an Iterator object.
Armed with this object, you can call the hasNext method to see if there are more elements to process,
and then call next to retrieve the next element. In addition, you can use remove to ask the object that
implements Iterator to delete the current element from the collection. Sure, you could remove the
-127 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
item directly, but that might confuse the Iterator; asking the Iterator to delete the item provides
consistent results.
Listing 5.2 shows how you can iterate through each element of a Vector . Regardless of the collection,
the code remains essentially the same.
Listing 5.2: Iterating a Vector.
import java.util.*;
Iterator i ;
v.addElement(new Integer(10));
v.addElement(new Integer(5));
v.addElement(new Integer(40));
// iterate
for (i=v.iterator();i.hasNext();)
Integer n = (Integer)i.next();
System.out.println(n);
-128 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
Using a Stack
Stack is a class that extends a Vector class and acts like a last -in-first-out stack of objects. It does
this with the following five additional stack methods:
§ empty()— Tests whether the stack is empty.
§ peek() — Looks at the object at the top but doesn't remove it.
§ pop()— Returns the top object and removes it.
§ push()— Adds an object to the top of the stack.
§ search()— Returns an element's p osition (the first position is 1, not 0).
If you examine the code that performs the pop operation, you'll see that Stack is little more than an
enhanced Vector class:
removeElementAt(len - 1);
The StackDemonstration.java program (from the previously cited Web site) demonstrates how to use
a stack. The following is an excerpt:
import java.util.* ;
class StackDemonstration
beefedUpVector.push(new Integer(3));
beefedUpVector.push(new Integer(2));
beefedUpVector.push(new Integer(5));
beefedUpVector.push(new String("Patricia"));
beefedUpVector.push(new String("Kasienne"));
//beefedUpVector.empty();
//beefedUpVector.size();
//beefedUpVector.search(new Integer(1));
//beefedUpVector.search(new Integer(4));
//beefedUpVector.pop();
//beefedUpVector.pop();
//beefedUpVector.peek();
-129 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
//returns:
// .push 1: [1]
//.push 3: [1, 3]
//.push 2: [1, 3, 2]
//.push 6: [1, 3, 2, 5]
//.push "Patricia":
//.push "Kasienne":
//.empty() : false
//.size(): 6
//.search 3: 6
//.search 4: -1
//.pop(): Kasienne
//.pop(): Patricia
//[1, 3, 2, 5]
//.peek(): 5
//[1, 3, 2, 5]
Stacks are common in many programs such as RPN (Reverse Polish Notation) calculators, certain
types of queues, and some areas of accounting programs.
You can use the ArrayList or LinkedList classes when the order of the collection's elements is
important. These lists have more methods than do the other collections. An ArrayList is just a Vector
except that the ArrayList methods are not synchronized, whereas most of the Vector meth ods are
synchronized. Synchronization makes the Vector thread-safe, but it also makes Vector somewhat
slower.
Tip If you need a thread-safe LinkedList, use a synchronized wrapper from
Collections.synchronizedList(List).
As a general rule, the ArrayList class is better at providing random element access than a
LinkedList is. The LinkedList class has more methods (addFirst, addLast, getFirst, getLast,
removeFirst, removeLast) and is better at inserting and deleting elements from the middle of the
List. The following program demonstrates the primary methods that are available for List collections
but not available for other collections:
import java.util.* ;
class ListAlgorithms
-130-
Java 2 Core Language Little Black Book Chapter 5: Data Structures
aList.add(new Integer(index));
Collections.sort(aList);
Y
FL
Collections.reverse(aList);
AM
Integer i = (Integer)Collections.min(aList);
TE
i = (Integer)Collections.max(aList);
}
The previous program uses the ArrayList class, but the program would work the same way if it used
a LinkedList class in the declaration on the h ighlighted line. In practice, you'd select one or the other
depending on which operation on the collection will be most common. An ArrayList is fast to access,
but insertions and deletions are faster in a LinkedList. The following code snippet is from Java's
ArrayList class:
-131 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 5: Data Structures
elementData[index] = element;
}
Notice that the ArrayList class simply makes sure there is room (adding a bucket, if necessary), shifts
the array, starting from the index and moving to the end, and then adds the object to the now-open
element. The remove method does the same thing, only in reverse. This is why the ArrayList isn't
fast at inserting or removing into the middle.
The following code from the ListDemonstration.java program (which you will find in full on the
previously cited http://www.inforobo.com Web site) shows the performance of some ArrayList
operations:
import java.util.* ;
class ListDemonstration
aList.add(new Integer(index));
// lList.add(new Integer(index));
// testVector.addElement(new Integer(index));
aList.get(index);
-132 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
// lList.get(index);
// testVector.contains(new Integer(index));
// aList.remove(0);
// lList.remove(0);
// testVector.removeElement(new Integer(index));
int low = 0;
-133 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
if (cmp < 0)
low = mid + 1;
high = mid - 1;
else
}
The algorithm compares the target element to the element in the middle. If the middle value is too high,
then the algorithm searches the middle of the lower half, and continues this divide-and-conquer
approach until it finds a match. Of course, this assumes the list is sorted. The advantage of this
standard search technique is that the speed is good (log n time). The BinarySearch code is a nice
example of how you can traverse List collections.
Using a Hashtable
A Hashtable maps keys to values where the key and the value can be any non-null object. This map
acts like a dictionary (actually extending the Dictionary class) in which you use a key to look up a
corresponding value. We use this type of associative data structure every day in the form of
phonebooks and Web addresses.
Hash tables use an algorithm to transform the key into an index. However, some keys might generate
the same hash index (this duplication is known as a collision). The larger the hash table, the less likely
it is that collision will occur. Collisions require special handling, which slows performance, so you'd
like to minimize them if possible.
A hash table has two parameters that affect its performance: capacity and load factor. Capacity refers
to the number of entries available, and load factor is a measure of how full the hash table is allowed to
get. When the table level begins to fill up, it is automatically resized (or, in other words, rehashed).
The more empty entries are available, the less likely it is that two keys will clash. But there is a lot of
wasted space. Increasing the load factor trims space but slows execution. Java uses a default load
factor (.75) as a fair tradeoff between performance and space. You can override the default by
choosing your own load factor. If you are not concerned about using too much memory, use a low
load factor. If space is paramount, though, use a high load factor.
The following program demonstrates most of the methods you will use with Hashtable:
import java.util.* ;
-134 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
HTMLtableElements.put(HTMLtableTags[index],
HTMLtableTagDefinitions[index]);
while (eTags.hasMoreElements())
System.out.println( eDefinitions.nextElement() );
if (definition != null)
System.out.println( HTMLtableElements.size() );
HTMLtableElements.remove(tag);
System.out.println( HTMLtableElements.size() );
-135 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
definition = (String)HTMLtableElements.get(tag);
(definition!=null?definition:"gone") );
//System.out.println( HTMLtableElements.toString() );
//returns:
//10
//9
//<colgroup> = gone
The Hashtable is superseded by the HashMap. Even though the HashMap is really using a
Hashtable underneath, Sun recommends using HashMap in new programs.
You use HashSet for a fast collection of unordered but unique values. The hash is computed for each
key and stored for fast retrieval, as is shown in the following code snippet:
args[0].hashCode()); }
The command java HashCodeTest "Little Black Book" yields:
import java.util.* ;
class HashSetDemonstration
-136 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
picnicSigned.add( "Kasienne" );
picnicSigned.add( "Patricia" );
picnicPaid.add( "Patricia" );
picnicPaid.add( "Devyn" );
picnicInterested.addAll( picnicSigned );
picnicStillOweFee.addAll( picnicSigned );
picnicStillOweFee.removeAll( picnicPaid );
picnicPaidButNeedToSign.addAll( picnicPaid );
picnicPaidButNeedToSign.removeAll( picnicSigned );
picnicPaidButNeedToSign );
picnicAttending.addAll( picnicInterested );
picnicAttending.removeAll( picnicStillOweFee );
picnicAttending.removeAll( picnicPaidButNeedToSign );
-137 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
//returns:
You can see that using the idea of mathematical sets is useful when you need to obtain the union and
intersection between lists.
A TreeSet is the same thing as a HashSet except that, in a TreeSet, the keys are kept in order. The
following adaptation of the program given in the HashSet section demonstrates the difference
between the two collections:
import java.util.* ;
class TreeSetDemonstration
picnicSigned.add( "Kasienne" );
picnicSigned.add( "Patricia" );
picnicSigned.add( "Ann" );
picnicSigned.add( "Devyn" );
picnicSigned.add( "Joseph" );
picnicSigned.add( "Donna" );
sortedEmployees.addAll( picnicSigned );
-138 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
//returns:
Both the HashMap and WeakHashMap require the same steps except for the subtle differences that
occur when garbage collection (Java's automatic reclamation of unused memory) cleans up the map.
Each map has the same methods; the only difference is the way garbage collection occurs. A
WeakHashMap does not hold a reference on its keys. So if the key isn't used anywhere else, the
garbage collector may reclaim it even though it is still a key in the WeakHashMap. This does not hold
true for values, by the way— the WeakHashMap holds a reference to the values, so they are not
subject to reclamation.
The following program (Listing 5.3 ), using methods that work for both maps, shows you how to pl ace
a value pair into a HashMap. Listing 5.3 also demonstrates how you can print the contents of the
HashMap by using System.out.print. Finally, the listing shows you how to get the pair value for a
given key value.
Listing 5.3: Using a HashMap.
import java.util.*;
-139 -
Java 2 Core Language Little Black Book Chapter 5: Data Structures
System.out.println(wordIntegerMap);
System.out.print("{One=" + wordIntegerMap.get("One"));
System.out.print(", Three=" +
wordIntegerMap.get("Three"));
System.out.print(", Four=" +
wordIntegerMap.get("Four"));
System.out.print(", Five=" +
wordIntegerMap.get("Five") + "}");
//returns:
These maps store a hash of the key and then discard the key. When you perform a lookup, the map
does the reverse— it hashes the provided key and looks for the hash value that was calculated upon
insertion. If the map finds a match, it returns the associated value (for example, the hash of "Four"
gets the integer 4).
The following code uses two maps (WeakHashMap) to create a constants table. The first map pairs
the name of the constant with its numerical value, and the second map pairs the name with the
symbol. This code demonstrates the methods you normally need to use for maps:
import java.util.*;
-140-
Java 2 Core Language Little Black Book Chapter 5: Data Structures
usefulConstantUnits.put("Avogadro",
usefulConstantUnits.put("Boltzmann",
Y
String[] names = {"Avogadro", "Electron mass",
FL
"Planck constant"};
AM
constant = (Float)usefulConstants.get(names[index]);
TE
symbol = (String)usefulConstantUnits.get(names[index]);
//returns:
-141 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
In Brief
Without files, computers wouldn't be nearly as useful as they are. Files store data in a persistent way
and give users a way to exchange data with other users. From a programming point of view, files
represent data storage that is not part of the program. Because of this, many things that are not actual
files present themselves as files to a program. For example, a network connection or a printer might
look like a file.
Java allows you to work with files, as you'd expect. In addition, Java uses the idea of
streams— sequences of bytes or characters— to allow easy access to files or anything that might
appear to be a file.
File Objects
One of the hallmarks of object-oriented programming systems is that they abstract common
functionality into base classes. A common operation in any programming language is to process or
emit a sequence of characters. For example, your program might read data from a disk file. Programs
often want to w rite data to a network socket or a printer.
Java abstracts a source of characters or a destination for characters in its stream classes. At an
abstract level, a stream is just the processing logic used to read or write a sequence of characters.
Other classes provide features such as buffering portions of the file in memory. Finally, a set of core
implementation classes associates streams with particular items, such as files, strings, the user's
console, or network sockets. You can connect these objects together to fit your needs. Therefore, a
stream that reads a file might feed a stream that performs buffering. That stream might, in turn, feed a
stream that interprets basic data types (such as int of float).
All the stream classes (and many other related classes) are in the java.io package. This package
contains two major groups of stream-related classes. The original set of streams (based on
InputStream and OutputStream) deals with byte-oriented entities such as ASCII files or network
sockets. A newer set of streams (based on the Reader and Writer base classes) deals with Unicode
characters. Because it is possible to map bytes into Unicode, some classes will convert an
InputStream into a Reader and some will convert an OutputStream into a Writer.
At first, th is abstraction of streams from actual devices might seem superfluous. After all, most
operating systems already abstract devices as files, right? So printers and consoles look like files
anyway. Thanks to the way Java handles streams, however, a stream can even read from or write to
a String object, a network socket, or even another program, for example.
Consider the StringReader class. This class is just a wrapper around a string with extra methods to
help you march along the string, retrieving or skipping characters. Remember, a string is really just an
array of characters with some built-in methods. The following snippet is an excerpt from the
StringReader.readmethod:
-142 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
synchronized (lock)
ensureOpen();
return -1;
return sourceString.charAt(next++);
}
This method returns a single character from the stream or returns - 1 if it reaches the end of file. The
expression sourceString.charAt (next++) simply picks off the character at the next position in the
string. Keep in mind that any sequence of characters, no matter the source, can be a stream.
One stream class you have been using throughout this book is the System.out stream. In particular, it
is a special type of stream that handles many different data types. At the top of the next page, you will
see some code that shows how versatile this stream is:
System.out.println(Byte.MAX_VALUE);
System.out.println(Short.MAX_VALUE);
System.out.println(Integer.MAX_VALUE);
System.out.println(Long.MAX_VALUE);
System.out.println(Float.MAX_VALUE);
System.out.println(Double.MAX_VALUE);
}
The println method has overloaded versions that handle a wide variety of data types. In practice, the
one you use most is the one that accepts a String . When you write:
int x;
-143 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
x=somefunc();
FileWriter Writes
characters
to a file.
FileOutputStream
Writes bytes
from a file.
PrintWriter Writes
Printing
formatted
data to a
Unicode
stream
(known as a
writer).
PrintStream Writes
formatted
data to a
stream.
-144 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
CharArrayWriter Writes to a
character
array.
ByteArrayOutputStream
Writes to a
byte array.
StringWriter Writes to a
string.
StringBufferInputStream
Reads from
a string
buffer.
PipedReader Reads
Pipe
characters
from a pipe
(a pipe is a
stream
connecting
two
threads).
PipedWriter
Writes
-145 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
characters
to a pipe.
PipedInputStream
Reads bytes
from a pipe.
PipedOutputStream
Writes bytes
to a pipe.
ObjectOutputStream Writes
objects to a
stream.
BufferedReader
Buffering Buffers data to
improve
performance
(resulting in fewer
actual hardware
accesses).
BufferedWriter
A writer that
buffers output
data in a memory
buffer to improve
performance.
BufferedInputStream Similar to
-146 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
BufferedReader,
but operates on
byte streams.
BufferedOutputStream Similar to
BufferedWriter ,
but operates on
byte streams.
PushbackReader
Peeking ahead Allows the caller
to read characters
and then decide
to put them back
so that later reads
will return the
same characters.
FilterWriter
Is a base class
that simplifies
writing filters that
process one
stream and
produce a second
-147 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
FilterInputStream
Is a base class
that simplifies
writing filters that
process one
stream and
produce a second
stream and attach
to an input
stream.
FilterOutputStream
Is a base class
that simplifies
writing filters that
process one
stream and
produce a second
stream and attach
to an output
stream.
LineNumberReader
Counting Tracks line
numbers while
reading.
LineNumberInputStream Is a stream
version of
LineNumberRea
der.
-148 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
Working with Java input/output (I/O) reminds me of plumbing. You take two pipes, put them together,
and then find an adapter that makes them fit. You can join many pipes together if you have enough
different adapters. It's perfectly acceptable to mix more than one adapter to fit the plumbing pipes
together. For example, suppose you're writing a network pr ogram that uses the Socket class. You
can read from or write to the socket by using streams (you can get a stream that corresponds to a
socket using the getInputStream and get-OutputStream methods). You might use an
InputStreamReader to convert the stream to a reader object. Then you would pass the
InputStreamReader to the constructor for a LineNumberReader.
If you're a Unix user, this technique might remind you of the way you perform many tasks in Unix: by
using pipes. So while the Unix command cat foo|more shows you a file, cat foo|sort|more shows
you the same file with its lines sorted. Using small building blocks together to perform large tasks is
such a powerful idea that you'll probably want to write your own plug-in modules that can alter a
stream of input or output.
Filtering modules are so commonplace that Java makes it easy to produce them via special prototype
classes that you can subclass. In particular, the FilterInputStream, FilterOutputStream,
FilterReader, and FilterWriter classes preprocess data for Input-Stream , OutputStream, Reader ,
or Writer objects, respectively.
You won't use the prototype classes (such as FilterReader) directly. Instead, you'll create a subclass
to do whatever specialized processing you need. Although each class has several functions, you'll
mostly need to override the read and write methods. You can usually write one function to handle
single characters, and then you can define the remaining functions in terms of those two
character-oriented functions.
For example, you can create a class called UCWriter that forces all of the output to a writer into
uppercase letters. When the filter class wants to write to the underlying writer, it uses the protected
out field from FilterWriter . Nothing actually appears on the output stream until the class specifically
writes to the out writer. You can find UCWriter in Listing 6.1.
Listing 6.1: This filter class converts characters to uppercase.
import java.io.*;
super(out);
-149 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
super.write(Character.toUpperCase((char)c));
throws IOException
while (len--!=0)
write((int)cbuf[off++]); }
throws IOException
while (len--!=0)
write((int)str.charAt(off++));
-150 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
console.flush();
The test main method converts the System.out stream to an OutputStreamWriter object and then
attaches it to a UCWriter. Finally, the program attaches the entire set of writers and streams to a
PrintWriter (which performs the formatting). The result is a stream that prints everything in uppercase
to the system console.
Immediate Solutions
Many programs n eed to open files for reading or writing. Of course, a file might really map to a device
(such as a printer or the console); that depends on your operating system. Listing 6.2 shows how to
Y
use a FileReader object to read a file (and, in this case, display the contents on the console).
FL
Listing 6.2: A simple file-reader program.
AM
import java.io.*;
TE
if (args.length != 1)
System.exit(1);
-151 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
try
String fileLine;
BufferedReader bufferedReader =
new BufferedReader(fileReader);
System.out.print(fileLine);
catch (IOException e) {
System.out.println(e);
The highlighted lines are where all the stream action happens. You use the FileReader class to open
up the file (filename) and read characters. Although they are all considered streams, remember that
those classes that have Reader or Writer in their names take characters, whereas classes with
Stream in their names take bytes.
To improve performance, the code connects a BufferedReader object to the FileReader . The
program would work without this layer, but it would be less efficient because the BufferedReader
object reads large chunks from the FileReader and buffers them for faster access.
The program in Listing 6.3 shows an example of both reading and writing to a file. The program
requires two file names at the command prompt. The program then copies the contents from the first
file into a newly created second file. If the second file already exists, it gets overwritten. Finally, the
program reports the details on the second file, demonstrating a few of the File class methods:
Listing 6.3: A file stream demonstration program.
-152 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
import java.io.*;
readFileName = args[0];
writeFileName = args[1];
//text files
//text files
//byte files
//byte files
-153 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
fileWriter.write(character);
character = fileReader.read();
if( writeFile.exists() )
fileReport(writeFile);
fileWriter.close();
fileReader.close();
System.out.println(fileObject.getName() +
System.out.println(fileObject.getParent() +
" = getParent()");
System.out.println(fileObject.canWrite() +
" = canWrite()");
-154 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
System.out.println(fileObject.isAbsolute() +
" = isAbsolute()");
System.out.println(fileObject.isDirectory() +
" = isDirectory()");
System.out.println(fileObject.isHidden() +
" = isHidden()");
System.out.println(fileObject.lastModified() +
System.out.println(fileObject.setLastModified(currentTime)
System.out.println(fileObject.setReadOnly() +
" = setReadOnly()");
System.out.println(fileObject.toString() +
" = toString()");
//fileObject.renameTo(newFile);
-155 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
//System.out.println(fileObject.delete() +
//System.out.println(fileObject.createNewFile() +
//java FileStreamDemonstration
"files/inputfile.txt""files/outputfile.txt"
//java FileStreamDemonstration
"files/inputfile.txt""files/outputfile.txt"
//returns:
//files = getParent()
//files\outputfile.txt = getPath()
//true = canRead( )
//true = canWrite()
//false = isAbsolute()
//false = isDirectory()
//true = isFile()
//false = isHidden()
-156 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
//true = setReadOnly()
//files\outputfile.txt = toString()
The file stream classes handle all the dirty work of figuring out the native file directory system. You
can append text to a file by passing true as the FileWriter constructor's second argument. This
indicates that you want to append the data you write to the existing file. Here's an example:
fileWriter.close();
As a final example, consider Listing 6.4. This program combines many techniques and classes
covered previously in the book. The program counts all the unique words in all the files in a directory
(you give the directory name as a command-line argument):
Listing 6.4: A SequenceInputStream demonstration program.
import java.util.*;
import java.io.*;
-157 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
System.exit(1);
System.out.println(files[i]);
SequenceInputStream allFiles =
new SequenceInputStream(fileEnumerator);
int wordCount = 0;
int nextLetter;
-158 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
{ // its a letter
isWord=true;
subToken.append(letter);
} else
if (isWord)
token = subToken.toString();
subToken.setLength(0);
if (token.length()==1) {
if (!(token.equalsIgnoreCase("i") ||
token.equalsIgnoreCase("a"))) token="";
++wordCount;
if(wordMap.contains Key(token))
-159 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
((Frequency)wordMap.get(token)).frequency++;
} else
isWord=false;
}//end while
System.out.println(wordMap);
class Frequency
int frequency = 1;
return Integer.toString(frequency);
-160-
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
//returns:
//files\genesis_1.txt
//files\Matthew_1.txt
//wordCount = 1263
quietly=1, father=39,
Y
FL
AM
This listing used the SequenceInputStream class. This stream simply joins multiple streams together
sequentially. Using this object allows the rest of the program to process one long file instead of
handling each input file separately.
TE
The class in Listing 6.5 is adapted from a sample in the Java documentation. This class is required by
the word-counting program. The File Enumerator class allows you to enumerate the files in a
directory. The enumeration does not continue into subdirectories, although you could write the
program recursively to descend into subdirectories.
Listing 6.5: This class enumerates the files in a directory.
import java.util.*;
import java.io.*;
-161 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
this.listOfFiles = listOfFiles;
return true;
} else
return false;
if (!hasMoreElements())
} else
-162 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
fileCount++;
try
} catch (FileNotFoundException e)
return fileStream;
Rewinding a Stream
Typically, once you read data from a stream, the data is gone. You can't randomly access the
stream's data at an arbitrary position, but some streams do allow you to mark a position and return to
it later. The mark method marks the current position of the stream for later use. Later, you can call
rese t to return to that mark. The mark method takes a limit argument (an integer). This limit tells Java
to invalidate the mark if the program reads the specified number of characters past the mark. This is
important because Java may have to buffer everything from the mark to the current position in order
to make reset work properly.
Not all streams support the mark method. Use markSupported to determine if you can use mark at
runtime. A return value of true means you can use mark safely.
The program in Listing 6.6 illustrates the use of mark and reset . The program opens the file and
determines its size. The program then uses the skip method to jump to a point you specify on the
command line (use a percentage). At the specified position, the stream is marked using the mark
-163 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
method. Now, the program prints the rest of the file to the console. Finally, the program issues a reset
call to jump back to the mark, and then it prints the entire file.
Listing 6.6: A skip and mark program.
import java.io.*;
if (args.length != 2)
System.exit(1);
BufferedInputStream inputStream =
System.out.println("skipTo=" + skipTo);
inputStream.skip(skipTo);
-164 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
if (inputStream.markSupported())
inputStream.mark(length);
int tempCharacter;
System.out.print((char) tempCharacter);
inputStream.reset();
System.out.print((char) tempCharacter);
//java SkipMarkDemonstration"files\genesis_1xs.txt" 99
//returns:
//skipTo=4062
//
-165 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
Filtering Streams
One common stream operation is creating a filter class. This class is really no different from any other
stream class except that a filter class's input is one stream and its output is another stream. For
example, you might want to connect a PrintWriter object to a special class that converts all the
characters written to uppercase. The uppercase class then connects to a FileWriter that actually
stores the data in a file. The class in the middle is a filter.
Listing 6.7 shows a class, HackOutputStream, that performs this filtering on a byte stream (you can
find a similar class for writers in Listing 6.1). The example program (in StreamFilterDemonst ration)
writes its output to the file outputcase.txt.
Listing 6.7: A filtering stream program.
import java.io.*;
if (args.length != 2)
System.exit(1);
caseChoice = Integer.parseInt(args[1].trim());
-166 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
caseChoice = HackOutputStream.CAPITAL;
try
FileOutputStream output =
new FileOutputStream("outputCase.txt");
HackOutputStream hackStream =
bs.read(b, 0, 1000);
hackStream.write(b);
hackStream.flush();
hackStream.close();
catch(FileNotFoundException e)
System.out.println(e);
-167 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
catch(IOException e)
System.out.println(e);
super(stream);//send to superclass
this.changeFlag = choice;
-168 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
case UPPERCASE:
out.write( (int)Character.toUpperCase(
(char)streamByte ) );
break;
case LOWERCASE:
out.write( (int)Character.toLowerCase(
(char)streamByte ) );
break;
case CAPITAL:
if (Character.isLetter( (char)streamByte ) )
if (lastByteWasNonLetter)
out.write( (int)Character.toUpperCase(
(char)streamByte ) );
} else
out.write( (int)Character.toLowerCase(
(char)streamByte ) );
lastByteWasNonLetter = false;
-169 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
} else
lastByteWasNonLetter = true;
out.write( streamByte );
break;
Related Foun
solution: d on
page:
108
Understandin
g Inheritance
When you are dealing with files, you often don't want to handle bytes or characters. Instead, you want
to read either Java objects (covered later) or groups of characters. For example, if you were writing a
program to format Java code, you'd want to read the Java keywords, variable names, and so forth.
Reading groups of characters is often known as tokenizing, and Java provides the StreamTokenizer
class for this purpose. By default, this class splits words on white-space boundaries. It also
differentiates between words and numbers. You can even make the class handle quoted strings and
Java comments. Listing 6.8 shows a word-counting program that uses the StreamTokenizer class.
Listing 6.8: A StreamTokenizer demonstration program.
import java.util.*;
import java.io.*;
-170 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
BufferedReader br = null;
try
br = new BufferedReader(new
Y
FileReader("files\\genesis_1.txt"));
FL
token = new StreamTokenizer(br);
AM
} catch(FileNotFoundException e)
{
TE
int wordCount = 0;
try
-171 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
if (token.ttype == StreamTokenizer.TT_WORD)
++wordCount;
if(wordMap.containsKey(token.sval))
((Frequency)wordMap.get(token.sval)).frequency++;
} else
//{
//}
} catch(IOException e)
e.printStackTrace();
-172 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
if(newWordRate > 5)
class Frequency
int frequency = 1;
return Integer.toString(frequency);
//returns:
Although you usually think of streams as containing characters (either bytes or Unicode characters),
you can also process raw data in streams. Of course, it doesn't make sense to deal with Unicode
streams and binary data (unless you plan to write textual representations of the numbers). Instead,
you'll use DataInputStream and DataOutputStream.
-173 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
These two classes are filters; you'll use an InputStream or OutputStream in the constructor when
you instantiate the class. Then you can use methods like readByte , readFloat, or writeInt . Here's a
simple example:
try {
int x;
float y;
x=dis.readInt();
y=dis.readFloat();
Naturally, it is up to you to read and write the data in the correct order. Java will dutifully read an
integer when you ask it to, even if the program that wrote the file placed a floating -point number at that
point in the file.
Of course, a more object-oriented method for writing raw data to a file is serialization, which is coming
up next.
Serializing Objects
Java I/O can also serialize objects. Serialization is the process of saving to disk the state of an object
with the intention of reconstructing that object in the same state. The serialization classes can read or
write a whole object to and from a raw byte stream. Serialization allows Java objects and primitives to
be stored and rebuilt.
The Serializable interface (java.io.Serializable) identifies a class that supports serialization.
Interestingly, this interface is just a marker, so it doesn't have any methods. Any class that says it
implements Serializable does implement it because it has no methods at all. The code in Listing 6.9
demonstrates a simple example of serializing a few objects and then deserializing (reconstructing)
them.
Listing 6.9: A serialization demonstration program.
import java.io.*;
import java.util.*;
-174 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
try
String[][] employeeNames =
{"Jan","Frank","Wess","Pat","Donald" },
{"Stan","Beth","Harold","Kevin" },
{"Harold","Greg","Les","Karen","Tom","Abe" },
{"Pete","Claire","Seth","Arnold","Abdul" }
};
ObjectOutputStream oldObject =
new ObjectOutputStream(f);
oldObject.writeObject(employeeNames);
oldObject.writeObject(new Date());
oldObject.flush();
String stringArray[][] =
(String[][]) newObject.readObject();
-175 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
System.out.println(oldString);
System.out.println(date);
System.out.print(stringArray[dim_1][dim_2] +"");
System.out.println();
ex.printStackTrace();
//returns:
-176 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
You should see that the class is doing a lot behind the scenes. Serialization is important anytime you
want to store an object and reconstitute it later. Of course, this includes saving and reading from files.
Serialization is also useful for passing objects across a network. Because an ordinary stream can
write to a String, you can create a String that represents a serialized object that you can store, for
example, in a database.
Related Found
solution: on
page:
284
Serializing
an Object
Java's LineNumberReader class reads a file and tracks the line number it is reading. This is useful
when you want to report an error in the file, for example. You can include the offending line number
with the error. The class counts lines by marking the line terminators. A line terminator is a line feed
('\n'), a carriage return ('\r'), or a carriage return followed immediately by a line feed. Otherwise, this
class is identical to a BufferedReader class (which it extends). Listing 6.10 shows how to use the
LineNumberReader class.
Listing 6.10: A StreamLineNumber demonstration program.
import java.io.*;
if (args.length != 1)
-177 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
System.exit(1);
try
LineNumberReader reader =
String text;
System.out.println(reader.getLineNumber() +
catch(IOException e) {
System.out.println(e);
//returns:
//1
//3
//5 {
-178 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
//7 {
//8 if (args.length != 1)
You can use the RandomAccessFile class for random reading and writing of files. The program in
Listing 6.11 shows you how to use this class. Unlike other classes in this chapter,
RandomAccessFile does not extend any of the other stream classes. It is a completely separate way
to handle files.
Listing 6.11: A random access demonstration program.
import java.io.*;
class RandomAccessFileDemonstration
File file;
RandomAccessFile raf;
try
raf.writeBytes(
-179 -
Java 2 Core Language Little Black Book Chapter 6: Files and Streams
raf.writeBytes(
raf.close ();
"rw");
raf.close ();
} catch (Exception e)
The RandomAccessFile class uses the same methods to read and write that DataInputStream and
DataOutputStream use. In fact, it implements the same interfaces: DataInput and DataOutput.
However, this class also allows you to call seek to set the current file position to any arbitrary position.
-180 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
In Brief
Computer programs manipulate data. Because data typically resides in databases, it's a good bet
you'll need to write a program that accesses a database. The problem is: which database? There are
probably a dozen major players in the database game and many lesser-known databases in use. Do
you really want to learn all of them?
JDBC Overview
Fortunately, you don't have to learn all of the databases. Java provides a package known as Java
Database Connectivity (JDBC), which acts as an object -oriented wrapper around most common
databases. If you know how to work with JDBC, you can work with practically every database you
might encounter.
JDBC under Windows often cooperates with another high-level wrapper: the Open Database
Connectivity (ODBC) standard. ODBC is the Windows abstraction of databases. This standard
Y
increases the number of databases that JDBC can use because many database vendors provide
FL
ODBC drivers.
This chapter focuses on the more important classes and techniques of JDBC and on how to use Java
AM
with JDBC; the chapter will not focus on specific database issues. General database theory deserves
at least a book of its own (and many database books are available). To get the most from this chapter,
you should already know something about tables, SQL (Structured Query Language), and simple
TE
queries, which are database issues and are not really related to Java.
Consider a real program. The code in Listing 7.1 connects to a database. You simply supply an
ODBC data source name on the command line. For example, you might use the Northwind example
database that ships with Microsoft Access (if you are using Windows).
Listing 7.1: Connecting to a database.
import java.sql.*;
-181 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
if (args.length != 1)
System.exit(1);
source += dataSource;
try
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
} catch (Exception e)
return;
try
Connection conn =
DriverManager.getConnection(source,
-182 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
username, password);
if (dmd == null)
} else
dmd.getDatabaseProductName());
dmd.getDatabaseProductVersion());
conn.close();
} catch (Exception e)
e.printStackTrace();
The previous program constructs a database URL of the form jdbc: subprotocol:subname. This
URL allows access to the database.
-183 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
Not all Java installations include JDBC, and not all JDBC installations have the particular driver you
want. Therefore, the program tests to be sure that the ODBC-to-JDBC bridge is present. That's the
purpose of the following line:
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
If the JDBC class is not present, this statement will throw a ClassNot-FoundError exception.
The actual database code begins in the second try block. The Connection object creates a session
with the database. Through this connection, you can execute SQL statements, retrieve results, and
get information describing the database. For example, you might want to know if the database
supports a particular operation (such as UPDATE).
One thing to beware of with connection objects: They automatically commit changes after executing
each statement. You can override this behavior by turning off the autocommit feature (simply pass
false to the setAutoCommit method). If you do disable this feature, you'll have to call the commit
method to save any database changes.
Note If the autocommit feature is turned off, you will lose all changes unless you
explici tly commit transactions.
Next, the program calls the getMetaData method. This call provides the information about this
particular database. The call returns a DatabaseMetaData object, which has many methods
describing details about the database (for example, the database engine in use and the version
number). Notice that the program isn't querying the data itself— that will come shortly.
JDBC 3
Sun Microsystems ships JDBC 3 with Java 1.4. JDBC 3 supersedes both the JDBC 1.22 and JDBC
2.1 specifications. Most companies are using JDBC 2.1 or even 1.22. If you are using one of these
older versions, dump it and go with JDBC 3 (which is compatible with JDBC 2). When you upgrade,
you get three things:
§ Performance — JDBC 3 is faster, is more reliable, and fixes bugs .
§ SQL-99 compliance— JDBC doesn't support the entire standard, but the SQL subset
that it does support complies with the standard.
§ More features— JDBC 3 offers advanced features (such as named parameters and
connection pooling) not available in earlier releases.
Remember that JDBC will help you talk to the database. JDBC is not a database itself. Therefore,
JDBC addresses what you can do with the data after the database hands it to you. Java can't do
anything about what the database does with the data you give it. This brings up a subtle, but
significant, issue. Is database functionality in the database or in the application? To answer that
question, you have to look at the SQL -99 specification.
Starting in 1978, the H2 committee (part of ANSI, the American National Standards Institute) started
working on a standard for databases. After much bureaucratic processing, the standard became an
American National Standard in 1986. Since then, this committee has given us SQL-89, SQL-92, and
the latest standard, SQL-99.
-184 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
The purpose of a standard like SQL-99 is to allow database users to switch between different
database systems without fear of incompatibility. Most major database vendors (including Oracle,
Microsoft, and IBM) comply with SQL -99, although many offer their own nonstandard extensions.
What this means is that JDBC is like a telephone— you can use a telephone to call anyone in the
world. Once you connect, though, there is no guarantee that you'll understand the language of the
person on the other end. Consider this query:
LastName, Department
FROM Employees
Driver-Database Discrepancies
One other problem you m ight encounter is that of slight syntax differences. The SQL that a driver
understands is sometimes different from what the database is expecting. The driver and the database
don't always speak the same language. Mostly they do, of course, but not exactly. For example,
Access uses an asterisk (*) for a wildcard character. The wildcard matches any number of characters
("wh*" finds "what," "white," and "why"). But the ODBC driver that ships with Windows doesn't accept
this character. Instead, you must use the percent sign (%). So code you develop for a native database
application might require modifications before passing through an ODBC driver (or through a JDBC
program that uses an ODBC driver).
You might wonder why you'd even bother writing native SQL code instead of ODBC code. There are
several reasons. First, ODBC is not especially efficient. You might have a choice of using a native
JDBC driver that directly interfaces with the database. Also, it is possible to partition your program so
that some of the database work occurs on the database server.
-185 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
For example, most modern database programs support stored procedures. Your JDBC program
might do little more than trigger a stored procedure to carry out some operation. The stored procedure
would use the native SQL syntax because it executes directly on the server.
When you are executing a program in a client/server environment, placing code in stored procedures
might increase performance because less network traffic is required for this approach. However,
stored procedure code makes your program more of a hybrid and less of a Java program. This can
make maintenance more complex.
Types of Drivers
You'll often hear people refer to a JDBC driver type . This is an arbitrary division of drivers based on
their internal workings. A type 1 driver, for example, is the JDBC-to-ODBC bridge we discussed
earlier in this chapter.
A type 2 driver, on the other hand, is a Java class that calls a native database API (for example, client
APIs for Oracle or Sybase). These are not very different from type 1 drivers; they still use an external,
non-Java bridge to work with the database.
Type 3 drivers are all Java and use a network transport to communicate with a database server using
a database-independent protocol. Since many database vendors offer this network service, a type 3
driver is a flexible option. The driver can be pure Java and still interface with a proprietary database
format.
Finally, there are type 4 drivers. These classes directly interface to a proprietary network protocol.
They are specific for a particular database, as you would expect.
You can search for different drivers based on their type and levels of support at the Sun Web site (see
http://www.industry.java.sun.com/products/jdbc/drivers).
Immediate Solutions
JDBC 3 has greatly expanded the database interrogation capabilities of Java. The program in Listing
7.2 doesn't need much commentary thanks to Sun's descriptive method names. The program
connects to the database and then prints what information it can find. Calling getMetaData returns a
DatabaseMetaData object that contains plenty of information about the database. You simply make
method calls to retrieve the information you want.
In a real program, you'd probably use only a few of these methods to find the information you needed
to tailor your processing to the database you were using.
Listing 7.2: Interrogating a connection.
import java.sql.*;
-186 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
if (args.length != 1)
System.exit(1);
source += dataSource;
try
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
} catch (Exception e)
return;
-187 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
try
username, password);
if (dmd == null)
System.out.println(
} else
/*
* use ResultSet.TYPE_FORWARD_ONLY
/* use ResultSet.TYPE_SCROLL_INSENSITIVE
* made by others.
-188 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
/* use ResultSet.TYPE_SCROLL_SENSITIVE
displayDBproperties(dmd, TYPE_FORWARD_ONLY );
conn.close();
} catch (Exception e)
e.printStackTrace();
int cursor_type)
try
dbMetaData.getDatabaseProductName());
-189 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
true_false = dbMetaData.isCatalogAtStart();
System.out.println( true_false +
true_false = dbMetaData.isReadOnly();
System.out.println( true_false +
true_false = dbMetaData.nullPlusNonNullIsNull();
System.out.println( true_false +
" NULL and non-NULL values NULL? For SQL -92 " +
true_false = dbMetaData.nullsAreSortedAtEnd();
System.out.println( true_false +
true_false = dbMetaData.nullsAreSortedAtStart();
System.out.println( true_false +
true_false = dbMetaData.nullsAreSortedHigh();
System.out.println( true_false +
-190-
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
true_false = dbMetaData.nullsAreSortedLow();
System.out.println( true_false +
true_false = dbMetaData.storesLowerCaseIdentifiers();
System.out.println( true_false +
true_false =
dbMetaData.storesLowerCaseQuotedIdentifiers();
System.out.println( true_false + Y
FL
": Does the database treat mixed " +
AM
true_false = dbMetaData.storesMixedCaseIdentifiers();
System.out.println( true_false +
true_false =
dbMetaData.storesMixedCaseQuotedIdentifiers();
System.out.println( true_false +
-191 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
true_false = dbMetaData.storesUpperCaseIdentifiers();
System.out.println( true_false +
true_false =
dbMetaData.storesUpperCaseQuotedIdentifiers();
System.out.println( true_false +
"upper case?");
true_false =
dbMetaData.supportsAlterTableWithAddColumn();
System.out.println( true_false +
true_false =
dbMetaData.supportsAlterTableWithDropColumn();
System.out.println( true_false +
true_false = dbMetaData.supportsANSI92EntryLevelSQL();
-192 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
System.out.println( true_false +
true_false = dbMetaData.supportsANSI92FullSQL();
System.out.println( true_false +
true_false =
dbMetaData.supportsANSI92IntermediateSQL();
System.out.println( true_false +
true_false = dbMetaData.supportsBatchUpdates();
System.out.println( true_false +
true_false =
dbMetaData.supportsCatalogsInDataManipulation();
System.out.println( true_false +
true_false =
dbMetaData.supportsCatalogsInIndexDefinitions();
System.out.println( true_false +
-193 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
true_false =
dbMetaData.supportsCatalogsInPrivilegeDefinitions();
System.out.println( true_false +
true_false =
dbMetaData.supportsCatalogsInProcedureCalls();
System.out.println( true_false +
true_false =
dbMetaData.supportsCatalogsInTableDefinitions();
System.out.println( true_false +
true_false = dbMetaData.supportsColumnAliasing();
System.out.printl n( true_false +
true_false = dbMetaData.supportsConvert();
System.out.println( true_false +
true_false = dbMetaData.supportsCoreSQLGrammar();
System.out.println( true_false +
-194 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
true_false = dbMetaData.supportsCorrelatedSubqueries();
System.out.println( true_false +
true_false =
dbMetaData.
supportsDataDefinitionAndDataManipulationTransactions();
System.out.println( true_false +
true_false =
dbMetaData.supportsDataManipulationTransactionsOnly();
System.out.println( true_false +
true_false =
dbMetaData.supportsDifferentTableCorrelationNames();
System.out.println( true_false +
true_false = dbMetaData.supportsExpressionsInOrderBy();
-195 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
System.out.println( true_false +
true_false = dbMetaData.supportsExtendedSQLGrammar();
System.out.println( true_false +
true_false = dbMetaData.supportsFullOuterJoins();
System.out.println( true_false +
true_false = dbMetaData.supportsGroupBy();
System.out.println( true_false +
true_false =
dbMetaData.supportsGroupByBeyondSelect();
System.out.println( true_false +
true_false = dbMetaData.supportsGroupByUnrelated();
System.out.println( true_false +
-196 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
true_false =
dbMetaData.supportsIntegrityEnhancementFacility();
System.out.println( true_false +
true_false = dbMetaData.supportsLikeEscapeClause();
System.out.println( true_false +
true_false = dbMetaData.supportsLimitedOuterJoins();
System.out.println( true_false +
true_false = dbMetaData.supportsMinimumSQLGrammar();
System.out.println( true_false +
true_false = dbMetaData.supportsMixedCaseIdentifiers();
System.out.println( true_false +
-197 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
true_false =
dbMetaData.supportsMixedCaseQuotedIdentifiers();
System.out.println( true_false +
true_false =
dbMetaData.supportsMultipleResultSets();
System.out.println( true_false +
true_false = dbMetaData.supportsMultipleTransactions();
System.out.println( true_false +
" connections)?");
true_false = dbMetaData.supportsNonNullableColumns();
System.out.println( true_false +
-198 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
true_false =
dbMetaData.supportsOpenCursorsAcrossCommit();
System.out.println( true_false +
"across commits?");
true_false =
dbMetaData.supportsOpenCursorsAcrossRollback();
System.out.println( true_false +
"across rollbacks?");
true_false =
dbMetaData.supportsOpenStatementsAcrossCommit();
System.out.println( true_false +
"across commits?");
true_false =
dbMetaData.supportsOpenStatementsAcrossRollback();
System.out.println( true_false +
"across rollbacks?");
true_false = dbMetaData.supportsOrderByUnrelated();
true_false = dbMetaData.supportsOuterJoins();
-199 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
System.out.println( true_false +
"join supported?");
true_false = dbMetaData.supportsPositionedDelete();
System.out.println( true_false +
true_false = dbMetaData.supportsPositionedUpdate();
System.out.println( true_false +
true_false =
dbMetaData.supportsSchemasInDataManipulation();
System.out.println( true_false +
true_false =
dbMetaData.supportsSchemasInIndexDefinitions();
System.out.println( true_false +
true_false =
dbMetaData.supportsSchemasInPrivilegeDefinitions();
System.out.println( true_false +
true_false =
-200 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
dbMetaData.supportsSchemasInProcedureCalls();
System.out.println( true_false +
true_false =
dbMetaData.supportsSchemasInTableDefinitions();
System.out.println( true_false +
true_false = dbMetaData.supportsSelectForUpdate();
System.out.println( true_false +
true_false = dbMetaData.supportsStoredProcedures();
System.out.println( true_false +
TE
"syntax supported?");
true_false =
dbMetaData.supportsSubqueriesInComparisons();
System.out.println( true_false +
true_false = dbMetaData.supportsSubqueriesInExists();
-201 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
System.out.println( true_false +
true_false = dbMetaData.supportsSubqueriesInIns();
System.out.println( true_false +
true_false =
dbMetaData.supportsSubqueriesInQuantifieds();
System.out.println( true_false +
true_false =
dbMetaData.supportsTableCorrelationNames();
System.out.println( true_false +
true_false = dbMetaData.supportsTransactions();
System.out.println( true_false +
-202 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
" TRANSACTION_NONE.");
true_false = dbMetaData.supportsUnion();
System.out.println( true_false +
true_false = dbMetaData.supportsUnionAll();
System.out.println( true_false +
true_false = dbMetaData.usesLocalFilePerTable();
System.out.println( true_false +
true_false = dbMetaData.usesLocalFiles();
System.out.println( true_false +
true_false = dbMetaData.updatesAreDetected(cursor_type);
System.out.println( true_false +
true_false =
dbMetaData.supportsTransactionIsolationLevel(
-203 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
cursor_type);
System.out.println( true_false +
true_false = dbMetaData.supportsResultSetType(
cursor_type);
System.out.println( true_false +
true_false =
dbMetaData.insertsAreDetected(cursor_type);
System.out.println( true_false +
"calling ResultSet.rowInserted().");
true_false =
dbMetaData.othersDeletesAreVisible(cursor_type);
System.out.println( true_false +
true_false =
dbMetaData.othersInsertsAreVisible(cursor_type);
System.out.println( true_false +
-204 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
true_false =
dbMetaData.othersUpdatesAreVisible(cursor_type);
System.out.println( true_false +
true_false =
dbMetaData.ownDeletesAreVisible(cursor_type);
System.out.println( true_false +
true_false =
dbMetaData.ownInsertsAreVisible(cursor_type);
System.out.println( true_false +
true_false =
dbMetaData.ownUpdatesAreVisible(cursor_type);
System.out.println( true_false +
int INTEGER = 4;
int FLOAT = 6;
-205 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
System.out.println( true_false +
true_false =
dbMetaData.supportsResultSetConcurrency(INTEGER,
CONCUR_UPDATABLE);
System.out.println( true_false +
} catch (Exception e)
e.printStackTrace();
Listing 7.3 shows a program that demonstrates how to use the DriverManager class and the Driver
class together. The DriverManager tries to decide what Driver class to use for a particular database.
Users can add to the list of drivers without changing the program. This is good practice because you'd
like to be able to change your database code quickly and easily with minimal disturbance to the rest of
-206 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
your program. The program shown in Listing 7.3 is a good skeleton that you can copy and paste to
start building your application's connection objects.
import java.sql.*;
import java.util.*;
if (args.length != 1)
System.exit(1);
credentials.put("user", username );
credentials.put("password", password );
DriverManagerDemonstration DMD =
new DriverManagerDemonstration();
-207 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
try
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
} catch (Exception e)
return;
try
url, credentials);
DMD.drivermanager(url);
System.exit(0);
conn.close();
} catch (Exception e)
e.printStackTrace();
-208 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
Driver driver;
try
//get timeout
loginTimeout = DriverManager.getLoginTimeout();
//set timeout
DriverManager.setLoginTimeout(maxTimeout);
""+loginTimeout ;
System.out.println(timeoutMessage);
while (driverList.hasMoreElements())
driver = (Driver)driverList.nextElement();
driverReport(driver, url);
-209 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
catch (Exception e)
int version;
boolean true_false;
DriverPropertyInfo[] driverProperty;
try
System.out.println("jdbcCompliant()=" + true_false );
true_false = driver.acceptsURL(url);
System.out.println("jacceptsURL()=" + true_false );
version = driver.getMajorVersion();
System.out.println("getMajorVersion()=" + version );
-210 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
version = driver.getMinorVersion();
System.out.println("getMinorVersion()=" + version );
/* java.sql.SQLException:
System.out.println("name" + driverProperty[index].name);
System.out.println("description" + Y
FL
driverProperty[index].description);
AM
System.out.println("required" +
driverProperty[index].required);
TE
System.out.println("value" + driverProperty[index].value);
*/
-211 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
} catch(SQLException e) //108
System.out.println(e);
//returns:
//0
//jdbcCompliant()=true
//jacceptsURL()=true
//getMajorVersion()=2
//getMinorVersion()=1
The DriverManager object manages the JDBC drivers available for your application. This object tries
to make life easier for you. For example, during initialization, the DriverManager object attempts to
load the driver classes referenced in the jdbc.drivers system property (multiple drivers are separated
by a colon). This allows a user to cus tomize the JDBC drivers used by your applications at runtime (no
recompile is necessary). Without direction, Java tries to find an appropriate driver when you call the
getConnection method.
Note ODBC drivers are notorious for being finicky. Often, the drivers do not come
from the database vendors themselves but come from third parties (such as
Microsoft). If you suspect that your driver is misbehaving, try updating it from
the driver vendor or see if the database vendor has a version that is newer than
your driver vendor's version.
Although Java has several date formats available, the database library uses a unique format. That
means that databases don't understand dates formatted by java.util.Date, so you have to use
java.sql.Date instead. The java.sql.Date class is simply a SQL date formatter (it extends
java.util.Date) used so that JDBC can work with real SQL DATE values. The java.sql.Time class is a
convenience, but Sun has deprecated most of its methods. The following methods of th is class should
be avoided: getDate, getDay, getMonth, getYear , setDate, setMonth, setTime, and setYear.
Some databases support these functions, and others don't. You don't want to rely on methods that
might not work at runtime.
-212 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
Note Even if getDate works, it returns the date of the machine the database is on,
not the date of the machine the application is on. This is also true of dates that
might originate from a stored procedure. Be careful comparing dates when
some dates might originate from the serve r and others might originate from the
application.
The program shown in Listing 7.4 demonstrates how to use dates in java.sql.Date.
import java.sql.*;
import java.util.*;
java.sql.Timestamp time =
new java.sql.Timestamp(startTime);
System.out.println( time.toString() );
//compare to Calendar:
anotherDate.setTimesDates();
anotherDate.printCalendarDate();
anotherDate.prettyPrintCalendarDate(startTime);
-213 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
class AnotherDate
*/
/* Doesn't work
* void setTimesDates()
-214 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
*{
* java.sql.Time times =
* new java.sql.Time(System.currentTimeMillis());
* java.sql.Date dates =
* new java.sql.Date(System.currentTimeMillis());
* year = times.getYear();
* month = times.getMonth();
* day = times.getDay();
* hour = dates.getHours();
* minute = dates.getMinutes();
* second = dates.getSeconds();
*}
*/
void setTimesDates()
year = 2002;
month = 10;
day = 9;
hour = 2;
minute = 34;
second = 22;
void printCalendarDate()
-215 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
System.out.println( timestamp );
//System.out.println( Calendar.toString());
char digit[] =
digit[0] = Character.forDigit(year/1000,10);
digit[1] = Character.forDigit((year/100)%10,10);
digit[2] = Character.forDigit((year/10)%10,10);
digit[3] = Character.forDigit(year%10,10);
digit[5] = Character.forDigit(month/10,10);
digit[6] = Character.forDigit(month%10,10);
digit[8] = Character.forDigit(day/10,10);
digit[9] = Character.forDigit(day%10,10);
digit[11] = Character.forDigit(hour/10,10);
digit[12] = Character.forDigit(hour%10,10);
digit[14] = Character.forDigit(minute/10,10);
digit[15] = Character.forDigit(minute%10,10);
-216 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
digit[17] = Character.forDigit(second/10,10);
digit[18] = Character.forDigit(second%10,10);
for (int pos = 20; value > 0 && pos < 29; pos++)
digit[pos] = Character.forDigit(value/divisor,10);
value %= divisor;
divisor /= 10;
//returns:
2001-09-17 12:20:05.033
2002-10-9 2:34:22
2002-10-09 02:34:22.027025065
It is strange, but the approach taken within java.sql.Date to get the time components involves calling
deprecated methods in java.util. Date (such as getHour ). The methods within java.util.Date, in turn,
are calling the same methods in the Calendar class; this is the preferred technique. This practice
ensures that older programs still run with Java 1.4 (or that this program works with older versions).
Once you establish a connection with the database, you'll usually want to execute queries and work
with the results. The program in Listing 7.5 is simple, but it performs all the steps required by a typical
database program: It connects to the database, executes a query, and processes the result set.
-217 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
import java.sql.*;
try
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
} catch (Exception e)
return;
try
username, password);
-218 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
query(sql, conn );
conn.close();
} catch (Exception e)
e.printStackTrace();
throws Exception
try
if (!results.next())
while ( results.next() )
-219 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
System.out.println(lastName);
stmt.close();
catch (SQLException e)
//returns:
//Connected to jdbc:odbc:northwind
//Fuller
//Leverling
//Peacock
//Buchanan
//Suyama
//King
//Callahan
//Dodsworth
-220 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
The next section will further discuss result sets. For now, concentrate on the formation of the query.
The previous program uses the connection object's createStatement method to create a Statement
object. The executeQuery method actually accepts the SQL statements and processes them.
Notice that the end of the program contains a call to close that releases the Statement object's
resources. This is a good practice because you can be certain to minimize resource use.
Sometimes you need to know information about statement execution. You also might want to set
information about a statement. For example, you might limit the number of rows a statement can
return or set a timeout value. You can learn and set this type of information about a query by using
members of the Statement object (which physically represents your query and its attributes), as you
can see in Listing 7.6 .
Listing 7.6: Modifying the Statement object's properties.
import java.sql.*;
{
Y
FL
public static void main (String args[])
AM
try
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
} catch (Exception e)
return;
-221 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
try
username, password);
max = statement.getMaxRows();
//error on MS Access
//statement.setEscapeProcessing(true);
//column max
//max = statement.getMaxFieldSize();
//max = statement.getQueryTimeout();
-222 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
"no warnings":warning.toString();
System.out.println(warn);
statement.close();
conn.close();
} catch (Exception e)
e.printStackTrace();
//returns:
//Connected to jdbc:odbc:northwind
//max rows: 0
//max rows: 10
//no warnings
Because Microsoft Access doesn't implement some of the features that JDBC supports, we
commented the offending statements out of Listing 7.6. If you are using another database, you can try
running these lines and see if they work.
-223 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
Listing 7.7 shows a more complete example. Here, the program uses the query's result set to
populate a Java object.
Listing 7.7: Creating table objects in Java.
import java.sql.*;
int maxRows = 5;
try
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
} catch (Exception e)
return;
-224 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
try
conn = DriverManager.getConnection(source,
username, password);
statement = conn.createStatement();
result = statement.executeQuery(sql);
//optional
//System.out.print( result.getInt("EmployeeID") );
employee.setEmployeeID(result.getInt("EmployeeID"));
employee.setLastName(result.getString("LastName"));
employee.setHireDate(result.getDate("HireDate"));
-225 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
employee.setDelimiter(", ");
//optional
//System.out.println( employee.toString() );
employeeList[row] = employee;
DisplayEmployee showEmployee =
new DisplayEmployee(employeeList);
showEmployee.print();
} catch (Exception e)
-226 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
e.printStackTrace();
finally
try
} catch(SQLException sqlE)
class DisplayEmployee
this.employeeList = employeeList;
-227 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
void print()
class Employee
-228 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
return this.Delimiter;
this.Delimiter=delimiter;
return this.EmployeeID;
this.EmployeeID=EmployeeID;
-229 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
return this.LastName;
this.LastName=LastName;
return this.FirstName;
this.FirstName=FirstName;
return this.HireDate;
this.HireDate=HireDate;
-230 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
if (this.EmployeeID != 0)
if (this.LastName != null)
if (this.FirstName != null)
if (this.Title != null)
if (this.TitleOfCourtesy != null) Y
FL
{ output += this.TitleOfCourtesy + del; }
AM
if (this.BirthDate != null)
if (this.HireDate != null)
if (this.Address != null)
if (this.City != null)
if (this.Region != null)
if (this.PostalCode != null)
-231 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
if (this.Country != null)
if (this.HomePhone != null)
if (this.Extension != null)
if (this.Notes != null)
if (this.ReportsTo != null)
{ output += "\n"; }
return output;
//returns:
//Connected to jdbc:odbc:northwind
-232 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
The previous program raises a question about result persistence. When you want to create objects in
Java to manipulate the data within an application, sometimes Java affords you many more options
than the database will. You have more control over the data this way. Also, it is usually faster to fetch
the data from the object fields (as is done in the Employee.toString method) than to work directly
with the ResultSet.
Warning If you create your own objects th at are equivalent to a database table, be
very careful about changing the data. What you do to your object will not be
reflected in the database (unless you write code to modify the database
appropriately). The reverse is also true: If you update the datab ase, your
objects will not reflect these changes automatically.
In Listing 7.7, notice the highlighted finally block. This will always execute after the associated try
block. The finally block will execute if there is no exception thrown or if an exception is processed.
This block is an ideal place for closing database objects because it will always execute, even under
unusual conditions.
Notice that there are many get methods, one for each data type. The method you call must match the
data type in the database. So, for example, getString retrieves a String object, and getInt returns an
integer. Unfortunately, the mapping of database types to Java types is driver dependent.
Related Found
solutio on
n: page:
66
Defining
Blocks
Interrogating a ResultSet
In addition to the data in a ResultSet, you frequently need to know details about the results (for
example, the number of rows in the set or the names of each column). Listing 7.8 shows you how to
use the ResultSetMetaData object to learn about a result set.
Listing 7.8: Interrogating a result set.
import java.sql.*;
-233 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
try
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
} catch (Exception e)
return;
try
conn = DriverManager.getConnection(source,
username, password);
statement = conn.createStatement();
result = statement.executeQuery(sql);
-234 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
resultsinfo.print();
} catch (Exception e)
e.printStackTrace();
finally
try
} catch(SQLException sqlE)
class ResultsInfo
-235 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
this.resultset = resultset;
void print()
ResultSetMetaData columnInfo;
try {
columnInfo = this.resultset.getMetaData();
col++) {
System.out.println("getTableName()=" + tableName);
System.out.println("getCatalogName()=" + catalogName);
System.out.println("getSchemaName()=" + schemaName);
System.out.println("getColumnName()=" + columnName);
System.out.println("getColumnLabel()=" + columnLabel);
-236 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
/* Optional:
* switch (columnType)
* {
* case Types.DOUBLE:
* do? columnInfo.getDouble(i);
* break;
* case Types.FLOAT:
* do? columnInfo.getDouble(i));
* break;
* case Types.INTEGER:
* do? columnInfo.getInt(i));
* break;
* //ARRAY,BIGINT,BINARY,BIT,BLOB,BOOLEAN
* //CHAR,CLOB,DATALINK,DATE,DECIMAL,DISTINCT
* //DOUBLE,FLOAT,INTEGER,JAVA_OBJECT
* //LONGVARBINARY,LONGVARCHAR,NULL
* //NULL,NUMERIC,OTHER,REAL,REF
* //SMALLINT,STRUCT,TIME,TIMESTAMP
* //TINYINT,VARBINARY,VARCHAR
*}
*/
-237 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
String columnTypeName =
columnInfo.getColumnTypeName(col);
System.out.println("getColumnTypeName()=" +
columnTypeName);
int columnDisplaySize =
columnInfo.getColumnDisplaySize(col);
System.out.println("getColumnDisplaySize()=" +
columnDisplaySize);
System.out.println("getPrecision()=" + precision);
System.out.println("getScale()=" + scale);
boolean autoIncrement =
columnInfo.isAutoIncrement(col);
System.out.println("isAutoIncrement()=" +
autoIncrement);
boolean caseSensitive =
columnInfo.isCaseSensitive(col);
System.out.println("isCaseSensitive()=" +
caseSensitive);
System.out.println("isCurrency()=" + isMoney);
boolean surelyWritable =
columnInfo.isDefinitelyWritable(col);
-238 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
System.out.println("isDefinitelyWritable()=" +
surelyWritable);
switch(nullType) {
case columnNoNulls:
System.out.println("isNullable()=NoNulls");
break;
case columnNullable:
System.out.println("isNullable()=Nullable");
break;
case columnNullableUnknown:
System.out.println("isNullable()=
NullableUnknown");
break;
System.out.println("isReadOnly()=" + readOnly);
System.out.println("isSearchable()=" + searchable);
System.out.println("isSigned()=" + signed);
-239 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
System.out.println("isWritable()=" + writable);
this.resultset.close();
} catch(SQLException e) {
System.out.println(e);
//returns:
//getTableName()=employees
//getCatalogName()=
//getSchemaName()=
//getColumnName()=ReportsTo
//getColumnLabel()=ReportsTo
//getColumnType()=4
//getColumnTypeName()=INTEGER
//getColumnDisplaySize()=11
//getPrecision()=10
//getScale()=0
//isAutoIncrement()=false
//isCaseSensitive()=false
//isCurrency()=false
//isDefinitelyWritable()=true
//isNullable()=Nullable
-240 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
//isReadOnly()=false
//isSearchable()=true
//isSigned()=true
//isWritable()=false
Java provides many ways to update data on a table. The ResultSet object is the recommended way
to change data. The easiest way to do this is with a SQL UPDATE statement, like this:
update employees
where EmployeeID = 4
Y
FL
This SQL code will change records that have an EmployeeID of 4 so that they have an ID of 3092. In
Java, you can pass this SQL to the executeUpdate method of the Statement object. Here's how you
AM
resultSet.updateInt("EmployeeID", 392);
resultS et.updateRow();//commit it
The previous code moves the ResultSet to record 298 (which happens to be the one we want to
change). The program updates the EmployeeID to 392. You can also insert rows with new data by
using a similar technique. An updatable ResultSet object has a set of methods that, together, allow
you to insert a row into the database. The code looks like the following:
resultSet.updateString("LastName", "Cox");
resultSet.updateString("FirstName", "Perry");
resultSet.updateInt("EmployeeID",3093);
-241 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
The PreparedStatement object stores statements before you execute them. This can improve
efficiency if you will execute the same sequence of statements more than once. The
PreparedStatement object is Java's equivalent to a database stored procedure. Both are
precompiled, which means they don't have to be parsed after their first execution. Like a stored
procedure, a PreparedStatement acts like a method that needs only a few parameters (the only part
that changes between executions). You use question-mark placeholders as the parameter list (which
can include output parameters). You identify each parameter by its count. Therefore, the first question
mark is 1, the second is 2, and so on. Once you give the PreparedStatement object the query, you
provide the values to replace the question marks, like this:
updateEmployee.setString(2, newFirstName);
updateEmployee.setString(3, newLastName);
A stored procedure is a precompiled collection of SQL statements that run as a unit. Stored
procedures reside in the database server and are the counterpart to Java prepared statements.
Stored procedures execute very quickly on the database, especially in client/server environments.
The following code shows you how to look up an employee from a stored procedure rather than by
simply executing a SQL statement:
"(" +
")" +
-242 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
"AS " +
"BEGIN" +
statement.executeUpdate(procedure);
CallableStatement executeSP =
conn.prepareCall("{Call sp_getEmployee(?)}");
executeSP.setInt(1, 83);
while (results.next())
System.out.println(rs.getInt(1));// EmployeeID
System.out.println(rs.getString(2));// FirstName
System.out.println(rs.getString(3));// LastName
The CallableStatement class is actually an interface that refers to some other object (which is driver
dependent). The object represents a stored procedure, as you could probably guess. This code
creates the stored procedure using executeUpdate. Of course, you can omit this initial part after you
create the procedure once or if the procedure already exists.
Some stored procedures have output parameters. Consider this stored procedure:
as
begin
if @oldID = 0
begin
return 0
end
else
-243 -
Java 2 Core Language Little Black Book Chapter 7: Java Database Connectivity
begin
return 1
end
end
You can use the registerOutParameter method to mark certain parameters as output parameters
and then retrieve them by using the usual get methods. Here's an example:
CallableStatement executeSP =
executeSP.registerOutParameter(1, Types.INTEGER);
executeSP.setInt(2, 5);
executeSP.registerOutParameter(3, Types.INTEGER);
executeSP.execute();
-244 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
In Brief
Java is one of the first widely used programming languages built to be Internet-aware. Java makes it
simple— almost too simple— to write network programs. However, there is one catch: Java recognizes
certain network protocols. If you want to work with one of thes e protocols, everything is simple. If you
want to work with something more exotic, however, you'll have to do a great deal of work. You might
even have to resort to nonportable code. Fortunately, Java does handle the most common protocols,
and that makes most network programming very simple.
Java does a great job of hiding low -level networking details from you, but sometimes you really need
to know what is going on at the low level of a network transaction. Most of these details appear in
various Requests for Comments (RFCs) maintained by the groups that are responsible for the
Internet's operation. Many of these RFCs are actually standards that Internet hosts must follow. You
can find a list of the commonly used RFCs in Appendix D.
Traditional socket programs use C. However, Java offers many high-level ways to handle sockets,
and these ways make writing network programs much easier. The downside is that it is very difficult to
circumvent this built-in support. For example, Java sockets support User Datagram Protocol (UDP)
and Transmission Control Protocol (TCP) connections. If you want something else— for example,
Internet Control Message Protocol (ICMP) for a ping program— you'll have to resort to native method
calls (probably written in C).
Java's network support— not surprisingly— is in the java.net package. Many of the classes in this
package aren't meant for ordinary use. You'll likely use the following classes:
-245 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
We'll address some of these classes in later chapters. The primary classes of interest in this chapter
deal directly with sockets.
The basic idea behind socket communications is simple. A client establishes a connection with a
server. Once the connection is made, the client can write to the socket to send data to the server.
Conversely, the server sends data to the socket that the client will read. The details can be complex,
but the idea is just that simple.
Java provides three main types of socket classes. DatagramSocket is the class that implements the
UDP protocol. UDP sockets don't use connections, don't ensure data delivery, and don't preserve the
data's sequence. Data in and out of the socket resides in a DatagramPack et object.
The other two socket classes are Socket and ServerSocket, and they both support TCP connections.
If you are connecting to a server, you'll use Socket. If you are writing a server, you'll use
ServerSocket . Why the difference? A client socket doesn't really care what port it uses locally. The
client socket does need to connect to a specific port on another computer. On the other hand, a server
is very concerned with its local port assignment (that's how clients find it). Servers also have to listen
for incoming connections.
Listening for an incoming connection isn't an intuitive process. Suppose you are a Web server
listening on port 80. When a client connects to you, it makes sense to think that you'd be using port 80
to talk to the client, right? That's not how it works, however. If it did work this way, only one client
would be able to connect at a time. Internally, the networking software arranges it so that when a
client connects on a port, the request goes to another socket that has a randomly assigned port. The
client doesn't really care as long as it connects to the server, and the server's main socket is free to
continue listening for incoming connections.
Addressing
No matter what kind of socket you plan to use, you'll need a way to specify the address of the socket.
You might think you could just pass a hostname or an IP address to the socket's constructor, but
that's not quite the case. Instead, you'll use InetAddress to represent the remote computer's address.
InetAddress doesn't have any public constructors. So how do you get an instance of the object? You
can use one of three static methods to create a new instance for you:
§ The getLocalHost method returns an InetAddress object that refers to your local
computer.
§ The getByName method returns an object for the specified host. The name can be a
string that represents the IP address, or it can be the actual hostname.
§ The getAllByName method finds all addresses that match a specified name. The
name might be a case-insensitive machine name (http://www.coriolis.com ) or a
string that contains an IP address (if you specify an IP address, then the method
-246 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
will return that IP address only after checking to see that it is a valid address). This
method returns an array.
Making any of these calls will either return an InetAddress object (or objects, in the case of
getAllByName) or throw an Unknown-HostException if the name is not resolvable. Usually, you'll
just pass the InetAddress object to a socket constructor. However, you can also use the object as a
way to resolve hostnames to IP addresses (sort of an interface to DNS). You can call the instance
methods getHostName and getHostAddress to return the hostname and IP address. You can also
use getAddress to return the IP address as a byte array, not as a string.
Listing 8.1 shows a simple console program that can resolve a name or IP address. When you pass
an IP address on the command line, the program will work, but it might or might not look up the
corresponding name. If Java can't resolve the hostname, the socket's name is simply a string that
represents its IP address.
Listing 8.1: A simple console program that can resolve a name or IP address.
import java.net.*;
InetAddress address=null;
if (args.length==0) {
System.exit(1);
try {
address=InetAddress.getByName(args[0]);
catch (UnknownHostException e) {
System.exit(2);
-247 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
System.out.println(address.getHostName() + "="
+ address.getHostAddress());
System.exit(0);
Listing 8.2 shows how to use the getAllByName m ethod. This method returns an array of all the
InetAddress objects that apply to the host. Armed with that array, you can iterate through the array
and determine the characteristics of all the InetAddress objects. For example, you can determine if
the address refers to the local computer, or if it is a multicast address.
import java.net.*;
System.out.println(addr[i]);
The InetAddress class is not very complex, but you can use it when you connect to another machine
by using a socket. The constructors also accept hostnames, so you rarely have to use this class; it is
useful when you want to resolve addresses yourself, however.
A TCP Client
When you want to connect to a server, you use the Socket class. The simplest way to create a
Socket is to provide a hostname (or InetAddress object) and a port number to the constructor.
Listing 8.3 shows a simple program that connects to a Web server. You sup ply the hostname or IP
-248 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
address on the command line. The program doesn't transfer any data, but it does check to see if
some server, presumably a Web server, is listening on port 80, and then the program connects to it.
import java.net.*;
import java.io.*;
try {
InetAddress addr;
addr=sock.getInetAddress();
System.out.println("Connected to " +
addr);
sock.close();
catch (java.io.IOException e) {
System.out.println(e);
If you are running a Web server on your local machine, you can test this program against the
localhost computer. The output will look something like this:
Connected to localhost/127.0.0.1
-249 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
Notice that the implicit call to InetAddress.toString (made by println) prints the hostname and the IP
address automatically. You can, of course, obtain the hostname and the IP address and format them
yourself.
A TCP Server
The most common type of socket you'll use is a TCP socket. When TCP is used, one computer acts
as a server, and the other computer acts as a client. You'll use ServerSocket to write a server. You
construct a ServerSocket object by calling the constructor with a port number. If you are writing a
standard server, you'll use the well-known port number associated with that server type. For example,
a Web server would use p ort 80. If you aren't writing a standard server, you can select a port number
that isn't in use on your system (typically higher than 1023).
It is very likely that the program will report that it can't connect to that port. If the port is in use, just
select another number. Now look at the program in Listing 8.4 . This program provides a server on port
8123. The server doesn't do anything; however, if you run this program, the Telnet program will be
able to connect to port 8123.
import java.net.*;
import java.io.*;
try {
while (true) {
System.out.println("Listening");
InetAddress addr=sock.getInetAddress();
-250 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
+ addr.getHostAddress() + ")");
pause(5000);
sock.close();
catch (IOException e) {
try { Y
FL
Thread.sleep(ms);
AM
catch (InterruptedException e) {}
TE
The constructor for ServerSocket accepts the port number. You could easily modify the code to
accept a port number from a property file or from the command line, if you thought the port number
might change. Once you have the server socket, you can call accept to listen for incoming
connections. This call will block the program's execution, so the program will halt un til a client
connects. If this is unacceptable, you'll have to make the call from within a thread, a topic covered
later in this chapter (see "Creating a Multithreading Server," in the Immediate Solutions section).
Because this server doesn't do anything, it just pauses for five seconds when someone connects. If
you try to run two copies of the server, the second copy will throw an exception. Only one program
can listen to a port at once. If you connect to the host while it is busy, the system will complete the
connection when the server calls accept again. The limit on how many clients can be waiting for the
server varies by system. You can ask for a certain queue size by using a different ServerSocket
constructor, but the underlying system is not obligated to fulfill your request.
-251 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
If the port number you want is already in use, the constructor will throw an IOException. You can use
this to discover the ports that are already in use on your machine (see Listing 8.5).
Listing 8.5: A program that can be used to scan your computer for ports in use.
import java.net.*;
testPort(i);
System.out.println("Completed");
try {
catch (java.io.IOException e) {
}
Note If you are running under Unix, you'll probably need to be running as root- to-start
servers on reserved port numbers (those lower than 1024).
The Socket classes allow Java networking at a relatively low level. Even then, the techniques do not
require you to know about arcane details such as Internet Protocol (IP) headers and source routes.
However, Java provides an even higher -level interface to networking that you can often— but not
always — use to get quick results.
-252 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
This higher-level interface works great for Web pages. For other protocols, however, it isn't very
programmer-friendly, so you might want to continue using the Socket object as you have in the earlier
examples.
The URL class represents a resource in Universal Resource Locator format, such as
http://www.coriolis.com. Usually, you'll construct the object with the URL, although a variety of
constructors will allow you to specify the URL in pieces instead of in one string, if you prefer.
Once you have a URL object, you can retrieve the contents of the URL in several ways. For example,
you can call openStream to fetch an InputStream that corresponds to the document. You can also
call getContent, which returns an object. The object's type is dependent on the document's
Multipurpose Internet Mail Extension (MIME) type.
That means you can retrieve a Web page with just a few lines of code (see Listing 8.6). However, you
don't get access to the headers, nor can you send data to the server. If you need to access the
headers or send data, you need a URLConnection object (discussed shortly).
import java.net.*;
import java.io.*;
int c;
do {
c=html.read();
if (c!=-1) System.out.print((char)c);
} while (c!=-1);
-253 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
Here's another problem with using URL (and, more specifically, getContent): The classes that
represent data are Sun-specific classes unless you provide your own. These Sun-specific classes are
not documented, and you can't be sure that Sun will continue to provide them in future versions. If
Sun does make major changes to the classes (it might, because they are not documented), you could
find yourself making major program changes to adapt to a new Java version.
Reading a URL with the URL object is easy. However, what do you do if you want more control over
the Hypertext Transport Protocol (HTTP) transaction? Perhaps you want to pass data to a server -side
script or read headers. Then you probably want to use the URL object's openConnection member.
This function returns a URLConnection object. If the URL actually uses the HTTP protocol (in the
case of a Web page, as opposed to, say, an FTP download), the object returns a subclass of
URLConnection known as an HttpURLConnection. This connection object lets you set headers and
requests before submitting the URL request.
For example, suppose you want to submit a request to a form on a Web server. You might use code
like that shown in Listing 8.7. This code creates the URL object as usual (in this case, it opens
InterNIC's WHOIS form). The program casts the URLConnection object into a specialized subclass
(the HttpURLConnection object, covered shortly).
import java.net.*;
import java.io.*;
class insearch
HttpURLConnection conn=
(HttpURLConnection)url.openConnection();
-254 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
int c;
conn.setDoInput(true);
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-type",
"application/x-www-form-urlencoded");
conn.connect();
PrintWriter( new
OutputStreamWriter(conn.getOutputStream(),
"8859_1"), true );
pout.print("whois_nic=" + URLEncoder.encode(argv[0]) +
"&submit=Search&type=domain");
pout.flush();
// read results
System.out.println(conn.getResponseMessage());
InputStream is=conn.getInputStream();
do
char x;
c=is.read();
x=(char)c;
if (c!=-1) System.out.print(x);
} while (c!=-1);
-255 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
Before the program establishes a connection, it calls setDoInput and setDoOutput to signify that it
wants to read from and write to the URL. The setRequestMethod tells the URL to use the HTTP Post
method to submit form data. Finally, the setRequestProperty sets the request headers to indicate
that the server can expect form data.
After the program attends to these details, it connects, using the connect method. At this point, the
program uses getOutputStream to ask the URL for an OutputStream. Writing to this stream causes
data to flow from the program to the Web server. D ata going to the server should be encoded to
prevent special characters from confusing the server, and that's the purpose of the URLEncoder
object's static encode method. It replaces blanks with plus signs and replaces special characters with
hexadecimal escape sequences — just the way the Web server wants it.
The URLConnection class has many methods, some of which are not very useful. Here are the most
important ones:
-256 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
earlier in the chapter. The second version requires an array of Class objects. The
method will then attempt to return one of those types, if possible.
§ getContentLength, getContentEncoding, getContentType , getDate,
getExpiration, getLastModified— These methods all return values from the
corresponding headers of the document, if applicable.
§ setIfModifiedSince— This method sets the IfModifiedSince header.
§ getHeaderField, getHeaderFieldDate, getHeaderFieldInt,
getHeaderFieldKey— You can use these methods to retrieve arbitrary headers,
either as a String or as a specific data type (for example, Date or int).
§ setRequestProperty— You can use this call to set an arbitrary header. You might set
a header to authenticate with the server or simulate a form submission, for example.
§ setDoInput, setDoOutput, getDoInput, getDoOutput— By defa ult, the object will
handle only incoming data from the server. However, you can control the data
directions by using these methods.
§ connect— This method contacts the server. Before calling connect, you must have
any options and headers set.
§ getInputStream , getOutputStream— These methods return streams you can use to
communicate with the server. Keep in mind that these streams are subject to the state
of the setDoInput and setDoOutput methods.
URLConnection Subclasses
You can use a subclass of URLConnection— HttpURLConnection— which is abstract. This is the
class used earlier in Listing 8.7. The only way to get this subclass is to create a URL object with an
http://www. URL and then call openConnection on the object. You can then cast the returned
URLConnection to an HttpURLConnection.
This special subclass allows you to set the request type (for example, GET or POST) by using
setRequestMethod, get the response code by using getResponseCode, and perform other
HTTP-specific tasks.
In addition to the HTTP-specific subclass, you can use a special subclass for Java Archive (JAR) files,
which are the same JAR files you use to package Java classes. You can retrieve JAR files from a
local file or via HTTP. To create a JAR connection for a file named inside.htm in the nettest.jar file,
you again create a URL object. However, in this case, you provide a pseudo-URL, like these three:
§ jar:file://c%3A/lib/nettest.jar!/inside.htm
§ jar:http://www.coriolis.com/jars/nettest.jar!/inside.htm
§ jar:ftp://ftp.coriolis.com/jars/nettest.jar!/inside.htm
-257 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
In the first example, the JAR file is a local file named nettest.jar in the c:\lib directory. Note that the
colon requires encoding, but the slashes do not. In the second and third examples, the JAR file
resides on a server at the indicated URL. In all cases, you want the inside.htm file from within the JAR
file. The exclamation mark simply ends the pseudo-URL and is not part of the JAR file name. The
portion after the exclamation mark is the file name within the JAR file that you want to extract. There is
no need to encode the exclamation point because these have no special meaning within a URL.
Once you have the URL cons tructed with the special URL, you can read data from the file just as you
would any other URL. That means you can call openStream or extract a URLConnection object and
cast it to a JarURLConnection. Like any other input/output (I/O) — related call, if the file doesn't exist
(or if an error occurs) you'll get an IOException.
The URL and URLConnection objects rely on URLStreamHandler and URLConnection classes to
perform protocol-specific processing. In addition, a ContentHandler class understands how to
convert incoming data into a Java type. However, the official Java library doesn't have
implementations for any of these classes. The classes you use when you use common protocols,
such as HTTP or FTP, are actually classes in the s un package and are not part of the Java baseline.
Custom Protocols
Under the hood, the URL object examines the protocol portion of its URL and calls an object that
implements URLStreamHandler-Factory (you set this object with the static
URL.setURLStream-HandlerFactory method). This object is responsible for creating a
URLStreamHandler subclass that corresponds to the specified protocol. However, you can install
only one URLStreamHandler-Factory— once it is set, you can't change it.
The object that subclasses URLStreamHandler creates a corresponding URLConnection object (or
subclass of URLConnection). It also parses the URL, so you can define custom URL formats (such
as the jar: protocol that JarURLConnection object uses). The URL-Connection object
communicates with the server.
Ordinarily, you don't care about any of this because it just works transparently. If you want to add to a
custom handler, however, you can do so by creating your own objects. Why would you want to create
a handler? You might want to extend Java's URL object so that it understands, for example, the
Finger protocol. You could define custom URLs that point to database tables or other custom
resources. You'll have to do a bit of work at first, but after you have the classes available it will be easy
for you (or anyone else) to access your custom content. You can even load new handlers at runtime.
Listing 8.8 shows a subcl ass of URLConnection that opens a time server on port 13. The connect
method is where most of the work occurs. This method opens a socket on the correct port and sets
the connected flag (part of URLConnection). Because this connection directly wraps a socket, the
getInputStream method is trivial.
-258 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
import java.net.*;
import java.io.*;
if (!connected) {
int port=url.getPort();
if (port<=0) port=DEFPORT;
connected=true;
return "text/plain";
throws IOException {
connect();
-259 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
return conn.getInputStream();
How does the URL object know to use this particular connection object? The first part required is a
URLStreamHandler subclass. This object creates the correct URLConnection object and is quite
simple (see Listing 8.9).
Listing 8.9: A simple class that creates the correct URLConnection subclass on behalf of the URL
class.
import java.net.*;
import java.io.*;
return TimeURLConnection.DEFPORT;
throws IOException {
You still have to instruct the system to use this URLStreamHandler object. When you create a URL
object, Java first looks to see if you've installed a URLStreamHandlerFactory class. If you have,
Java calls the createURLStreamHandler method of this class. If you didn't provide this class (or if the
method returns null), the system then looks in the system property named
java.protocol.handler.pkgs. This property might contain a list of package names, separated by the
vertical -bar character (|) — sometimes called a pipe character .
If this property has a value, Java looks for a class that matches the protocol you are trying to use. For
example, suppose the java. protocol.handler.pkgs property equals "com.al_williams.
-2 60 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
proto|com.coriolis.java.phandlers" and you are trying to load a mailto URL. Java will look for these
classes along the CLASSPATH :
com.al_williams.proto.mailto.Handler
com.coriolis.java.phandlers.mailto.Handler
This class, if it exists, is a subclass of URLStreamHandler (as shown in Listing 8.9). If you don't have
a class that fits this description, Java finally looks for a class named sun.net.www.protocol.mailto.
Handler (for the mailto protocol).
Of course, the custom URLStreamHandlerFactory offers the most control over the process, and it is
simple to write (see Listing 8.10). Just remember that you can install only one factory class.
Subsequent attempts to set the factory class will throw an exception.
Listing 8.10: The URLStreamHandlerFactory class selects a custom handler for a protocol.
import java.net.*;
public URLStreamHandler
createURLStreamHandler(String protocol) {
TE
if (protocol.equalsIgnoreCase("time"))
If you are using a custom factory class, you should set it by using the static
URL.setURLStreamHandlerFactory method, as the program in Listing 8.11 does.
Listing 8.11: This simple program uses the custom protocol handler
import java.net.*;
import java.io.*;
-261 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
URL.setURLStreamHandlerFactory(new MyStreamHandlerFactory());
InputStream is=url.openStream();
int c;
do {
c=is.read();
if (c!=-1) System.out.print((char)c);
} while (c!=-1);
is.close();
The class itself implements the getContent method, which returns the appropriate type. Alternatively,
the calling program can specify a list of classes, and getContent will return a type from this list, if
possible.
The process that Java uses to find appropriate content handlers is similar to the one it uses for
protocol handlers. First, the URL object calls the URLConnection object's getContent call. If you are
writing a custom URLConnection object, you can handle everything at this point.
The default processing for getContent, however, checks whether you have installed a
ContentHandlerFactory class by using the static setContentHandlerFactory m ethod of
URLConnection. If you have, Java calls the createContentHandler method to find a content handler.
If this class has not been installed or the method returns null, Java examines package names in the
system property java. content.handler.pkgs .
-262 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
If all else fails, Java looks for the default handler. For the example MIME type, the default handler
would be at sun.net.www.content. application.x_video. You'll find an example content handler in
the Immediate Solutions section of this chapter.
Immediate Solutions
Resolving a Hostname
If you want to transform a hostname to an IP address, you can use the InetAddress class. In many
cases, this same class can resolve an IP address to a hostname, although this is not always possible.
You can't construct an InetAddress object directly. Instead, you call one of three static member
functions: getLocalHost, getByName, or getAllByName.
Once you have an InetAddress object, you can call getHostName or getHostAddress to find the
corresponding name or IP address. You can also call getAddress to get the IP address as an array of
bytes. Listing 8.12 shows an excerpt of the code required to use InetAddress .
try {
address=InetAddress.getByName("www.coriolis.com");
catch (UnknownHostException e) {
System.exit(1);
System.out.println(address.getHostName() + "="
+ address.getHostAddress());
-263 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
When you create a Socket object, you specify the destination address and port in the constructor.
You can specify the destination address as a string or as an InetAddress object. If the computer has
multiple network interfaces, you can also specify the local port and the outgoing interface to use,
either as a string or as InetAddress.
When you construct a socket, you might trigger an exception if the hostname is unknown or if any
other error occurs. Listing 8.13 shows an example of opening the Web server at
http://www.coriolis.com.
try {
catch (UnknownHostException e) {
// not found
// other error
When you want to start a server, you can instantiate a ServerSocket object. The minimal constructor
requires a port number that the socket will use to listen for incoming requests. If you wish, you can
also suggest a queue size for incoming requests. Also, if there are multiple network interfaces, you
can specify an InetAddress object to select a specific address.
Once a ServerSocket is instantiated, you can wait for a connection with accept. This will return a
Socket object that you can use to communicate with the client. Client connections are possible only
when the server calls accept ; then a single client will connect. If no clients are waiting to connect, the
call will block (subject to any timeout set by soSetTimeout).
Industrial -strength servers usually create separate threads to handle incoming requests so that other
clients will not have to wait to connect. You'll find an example in Listing 8.14 .
-264 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
Listing 8.14: The ServerSocket class makes it easy to accept client connections.
try {
while (true) {
Socket sock=ssock.accept();
HandleClient(sock);
catch (java.io.IOException e) {
For some protocols, or for maximum efficiency, you might want to use UDP sockets instead of TCP.
UDP sockets do not ensure data delivery. There is also no guarantee that data will arrive in the order
in which it was sent. If you use these sockets, you'll have to provide an alternate way to deal with
transmission loss and sequencing.
When you send and receive data via UDP, you use a DatagramPacket object. This object allows you
to set an IP address (which can be a broadcast address) and a port number. The object also contains
a byte array that contains the data to be sent or received. You pass the packet object to the
DatagramSocket object's send or receive methods.
If you are doing multiple transactions with one server, consider calling DatagramSocket.connect to
set a connection to the remote computer. Doing this reduces the overhead involved with sending each
packet to the remote computer. However, then you can't send to other computers until you call
disconnect .
UDP sockets don't use streams. You simply send and receive arrays of bytes. You'll find an example
in Listing 8.15.
Listing 8.15: UDP sockets use DatagramPacket objects to send and receive data.
-265 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
if (reading) {
// read
sock.receive(pack);
System.out.println(word);
sock.close();
} else { // write
pack.setAddress(InetAddress.getByName(hostname);
pack.setData(dataString.getBytes());
pack.setPort(portnum);
sock.send(pack);
sock.close();
Once you have a Socket object (either from constructing one or as a result of a
ServerSocket.accept call), you can fetch a stream by calling getOutputStream. You can then write
data to this stream. The getOutputStream method, which is part of the java.io package, allows you
to write bytes (or a byte array) to the socket for reading by the other computer.
You normally won't use the stream directly. Instead , you'll add one or more stream filters to make
things simpler. For example, you might use BufferedOutputStream to buffer bytes to improve
performance. A DataOutputStream object allows you to write primitive data types, or an
ObjectOutputStream object can write entire objects as long as they are serializable. Listing 8.16
shows a simple example that opens a socket on a remote computer and uses the DataOutputStream
filter to send an integer.
-266 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
DataOutputStream os =
new DataOutputStream(sock.getOutputStream());
os.writeChar('X');
os.writeChar('Y');
os.close();
sock.close();
Receiving data requires you to call getInputStream . Once you have this input stream object, you can
use it to read raw bytes from the socket. If you issue a read and no data is available, the read call will
block unless you've set a timeout.
You might want to use filters to provide extra features, such as buffering (BufferedInputStream) or
data reception (DataInputStream). Listing 8.17 shows a simple function that receives data from a
TCP socket.
char c1,c2;
c1=is.readChar();
c2=is.readChar()();
is.close();
-267 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
Because you can add filters to input and output streams, you can perform sophisticated processing,
such as compression and decompression, with relative ease. The java.util.zip package has several
stream classes you can use to compress and decompress data on the fly.
Listing 8.18 shows a program that receives data from a socket and decompresses it by using
GZIPInputStream . This server accepts only one connection and terminates when the transaction is
completed. Start the server with a port number on the command line.
Listing 8.18: Using Java's compressions classes to reduce the amount of data sent over a socket.
import java.net.*;
import java.io.*;
import java.util.zip.*;
Integer.parseInt(args[0]));
System.out.println("Listening");
Socket sock=ssock.accept();
sock.getInputStream());
while (true) {
int c;
c = zip.read();
if (c==-1) break;
System.out.print((char)c);
-268 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
Listing 8.19 contains a companion client that sends a file to the server in Listing 8.18. S tart the client
with the hostname, the port number, and a file to send on the command line. This client and server
work just the same as if they did not compress the data stream. The only difference is that they filter
their streams with the special classes that compress data.
import java.net.*;
import java.io.*;
import java.util.zip.*;
sock.getOutputStream());
String line;
new FileReader(args[2]));
while (true) {
try {
line=bis.readLine();
if (line==null) break;
line=line+"\n";
zip.write(line.getBytes(),0,line.length());
-269 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
zip.finish();
zip.close();
sock.close();
When you make any call to read from a socket, the call normally blocks until the read is completed. If
you want a different behavior, you can call Socket.setSoTimeout. The timeout is expressed in
milliseconds and defaults to zero, which indicates that there's no timeout at all. If there is a timeout
value and the read is not completed in the specified interval, the read will throw an
InterruptedIOException.
As an example, suppose you made this call to set a 1 -second (1,000-millisecond) timeout:
Then, assuming you have an input stream named is, you might write:
try {
c=is.read();
If you find yourself using setSoTimeout, you should think about using threads instead. Usually, doing
reads in one thread and processing in another leads to a more robust solution. You can also use
getSoTimeout to read the value back.
When you call ServerSocket.accept, your program will stop until a client connects. If you want to set
a timeout, you can call Server-Socket.setSoTimeout to set a timeout in milliseconds. If you find
yourself doing this, however, you should rethink your design and use threads. By using threads, you
can wait for client connections without stopping your processing. However, if you want to use the
timeout, you can call getSoTimeout to read the value. Here's an example:
-270-
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
Then a call to accept will throw an IOException if a connection is not made within one second.
Setting SoLinger
Sometimes you might close a socket before all the data you've sent has been transmitted to the other
computer. In this case, you can call setSoLinger on the Socket object to set a time (in seconds) to
wait for the data to clear before closing the socket. You can call getSoLinger to retrieve the value.
The following code sets the linger time to five seconds, and it may throw a SocketException:
sock.setSoLinger(true,5);
If you set the first parameter to false, you'll turn the linger feature off; this is the default state.
Obviously, this call applies only to TCP sockets because UDP sockets don't have a connection to
close.
To make data transmission more efficient, the underlying operating system usually buffers data and
does not send a packet until the other computer acknowledges the previous transmissions. For some
applications— notably, those that are interactive— this might not be appropriate. If you want to change
this behavior, call socket. setTcpNoDelay(true). Call getTcpNoDelay if you want to determine the
current value of this flag.
Y
FL
Tip RFC896 defines Nagle's algorithm, which is the algorithm used to determine
AM
when to send packets. You'll find a list of commonly used RFCs in Appendix D.
Suppose that a client and server connect and then infrequently exchange data. The server could
crash, and the client wouldn't notice until the next time the client sends data. If you call
Socket.se tKeep-Alive and pass true as an argument, the sockets will periodically send meaningless
data just to see if the connection is still alive. Here's an example:
Your program won't see this data; if the sockets stop communicating, however, your program will
receive an exception, even if you're not actively transmitting data. You can call getKeepAlive to find
the current setting.
TCP sockets can buffer data, although the exact details are platform-dependent. You can make a
suggestion to the operating system by calling Socket.setReceiveBufferSize and
Socket.setSendBuffer-Size. These values are only suggestions. You can also call
getReceive-BufferSize and getSendBufferSize to read the buffer sizes. Here's an example:
sock.setSendBufferSize(sock.getSendBufferSize+1024);
Of course, these calls might throw a SocketException.
-271 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
Many socket operations can throw exceptions. Four common exceptions you might want to handle
are the following:
You can catch the last three exceptions by handling Socket-Exception, which is the base class for all
three.
If any significant processing is required, however, this approach isn't efficient. You'd like to let the
server handle eac h client in a separatethread. The easiest way to do that is to make your class extend
Thread. Then you can write your processing in the run method. In the main routine (usually static),
you can call accept, create a new instance of your class (probably passing it the socket returned by
accept ), and then call start to run the thread. You can find an example of this in Listing 8.20.
import java.net.*;
import java.io.*;
Socket csocket;
-272 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
while (true) {
new AMTServer(ssock.accept()).start();
Because the logic behind a multithreaded server is so predictable, you might be tempted to write a
common base class for all multithreaded servers. That's a great idea, but there is a problem. You'd
like to create a single base class that can instantiate your classes that perf orm client processing.
However, that's hard to do without some special tricks.
You'll see that the code in Listing 8.21 uses an unusual technique to allow one static member to
create an instance of the class— even if that class is a subclass of the MTServerBase class. The idea
is to pass a Class object into startServer. The method then uses the newInstance method to create
the object. This approach assumes that your subclass has a default constructor, although you can
use the reflection functions in java.lang.reflection.Constructor to call a nondefault constructor if you
want to modify the base-class code. This technique allows you to extend MTServerBase without
providing a custom version of startServer. You can find a class object for a particular class type by
appending .class to the ordinary name. If you have an instance of an object, you can use getClass to
do the same thing. Because you pass the startServer method your class object, startServer can
create an instance of your object by using the newInstance method. Therefore, you don't have to
replace the startServer method in your subclass.
import java.net.*;
import java.io.*;
-273 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
// client
try {
socket.getOutputStream().write(s.getBytes());
socket.close();
catch (Exception e) {
System.out.println(e);
ServerSocket ssock;
Socket sock;
try {
ssock=new ServerSocket(port);
while (true) {
Socket esock=null;
try {
-274 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
esock=ssock.accept();
MTServerBase t=(MTServerBase)clobj.newInstance();
t.socket=esock;
t.start();
} catch (Exception e) {
} catch (IOException e) {
MTServerBase.startServer(808,MTServerBase.class);
Listing 8.22 provides an example of how you can use this server base class to form another server.
This particular server, which accepts the port number on the command line, converts lowercase input
(from a Telnet program, for example) to uppercase. You can end the server by pressing Ctrl+C or
Ctrl+D.
-275 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
Notice that the only code in the subclass is the run method and a new main method to start the server
properly. You can make any number of servers that derive from MTServerBase and focus on just the
client interactions.
import java.net.*;
import java.io.*;
try {
InputStream is=socket.getInputStream();
OutputStream os=socket.getOutputStream();
while (true) {
char c=(char)is.read();
os.write(Character.toUpperCase(c));
socket.close();
catch (Exception e) {
System.out.println(e);
-276 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
int n = Integer.parseInt(args[0]);
startServer(n,UCServer.class);
import java.io.*;
import java.net.*;
-277 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
pageBuffer.append(html);
page.close();
html = pageBuffer.toString();
System.out.println(html);
System.out.println(date);
System.out.println(time);
//returns:
//01 -09-20
//06:05:22
-278 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
import java.io.*;
import java.net.*;
if (args.length == 1)
ticker = args[0].toUpperCase();
connection.setDoOutput(true);
connection.getOutputStream());
-279 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
out.close();
new InputStreamReader(
connection.getInputStream()));
pageBuffer.append(html);
yahooPage.close();
html = pageBuffer.toString();
System.out.println(quote);
-280 -
Java 2 Core Language Little Black Book Chapter 8: The Internet and Networking
//returns:
//96.00
This program is only a trivial variation of the time program, but there is one major difference. Notice
the highlighted lines. These lines are actually writing to the Web server. This is where we are sending
data that mimics Yahoo's stock -quote form. You can send any character data this way. If you are
reverse-engineering a Web service like this, it is useful to use the View Source menu on your browser
to look at the form's HTML directly.
Tip Use the PrintWriter to send text data, but the PrintStream to send binary. Sun's
documentation says you should use the PrintStream to send character data, as
bytes, but not use it for non-character data. Also, the PrintWriter methods never
throw I/O exceptions, so you use checkError().
Y
FL
AM
TE
-281 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 9: XML and Java
In Brief
Before Web browsers, the Internet was just a widespread computer network. There were lots of things
you could download— i f you knew where and how to find the information you were looking for. What
Web browsers— and, in particular, HTML— provided was an easy way for people to view information;
they also provided links to other information on the Web.
HTML focuses on displaying data and managing hyperlinks. It isn't good at actually describing data
(except for the data that relates to formatting a Web page). That's where XML comes in; it is used for
managing data instead of display.
Introduction to XML
Superficially, XML (Extensible Markup Language) files look like HTML (Hypertext Markup Language)
files. These markup languages function slightly differently, but the biggest difference is their intended
purpose. HTML allows you to describe a Web page's appearance. Browsers on multiple platforms
render this HTML in an appropriate way. For example, a browser running on a workstation (with a
resolution of 1,280×1,024) shows a page much differently than does a Windows CE handheld
computer and its credit card— size screen.
In contrast, XML does not describe data presentation at all. Rather, XML stores information. Of
course, plenty of database products exist for storing data. The difference between an ordinary
database and data in XML format is simple: XML is very portable. Not only can XML documents
traverse platforms, but programs can process XML without prior knowledge of an XML file's contents.
The XML specification (the official document is at http://www.w3.org/TR/2000/REC-xml-20001006 )
uses tags that are similar to HTML tags. Unlike HTML tags, XML tags are case-sensitive. Also, XML
defines few standard tags. Instead, you are free to make up any tags you like (with a few restrictions).
There are a few other minor differences. For example, HTML has many tags that don't have
corresponding closing tags (for example, <BR>), whereas XML always requires closing tags
(although there is a way to write a tag that opens and closes all at
once). In XML, for another example, attribu tes must have quotes, even if they don't contain spaces. In
HTML, quotes are optional if the attribute value doesn't contain spaces. As an example, the following
is legal HTML:
<A HREF=t.jsp>
In XML, however, anything after the equal sign (the attribute value) must be in quotes. So an XML
document might contain:
<XLINK URI="t.jsp">
Because XML doesn't prescribe tags, it is up to the data producer and the data consumer to agree on
the various tags. Because the tags have a rigorous format, however, tools that don't know specifics
-282 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
about the tags can still identify them. A tool might not understand what the tag means, but the tool can
still identify the parts of the document.
<item>
<ball id="97">
<color>blue</color>
<size units="mm">50</size>
<shippable/>
</ball>
</item>
The first element is one of the few predefined tags. This tag identifies this document as following XML
version 1 and as using the 8-bit Unicode Transformational Format (UTF-8). Apparently, the creator of
this file wants to describe an item. In particular, this item is a ball that has an ID of 97, a color of blue,
and a size of 50 millimeters. Each XML file has a single root tag (in this case, item), which contains all
the other tags.
The shippable tag is a special type of tag. XML requires that all tags have a corresponding closing
tag. In the previous example, the way the shippable tag appears indicates that it is both an opening
and a closing tag, all in one. This is equivalent to:
<shippable></shippable>
If that was all there was to XML, it would be simple, right? Actually, XML itself is just this simple. The
complexity arises in processing the XML, however.
I mentioned earlier that programs that don't know anything about our item document can still correctly
identify the pieces that make up the document. The downside is that the program can't tell if the
document meets any rules other than XML's basic rules. Suppose that you and I want to exchange
these item documents, and we agree that item is the root tag and the only other allowed tags are ball,
cube , and rod. Furthermore, each of these tags can contain only color, size, shippable , and price
tags. The shippable and price tags are optional, but the other tags are not. Each item has only one
sub-tag, and each sub-tag can have only one color , one size , one shippable, and one price tag
(balls don't have two prices). Of course, to be precise, we'd also need to agree on the format of an ID,
the acceptable units for the size tag, and the valid colors.
A program that processes generic XML can't test these rules because they constitute a private
agreement between us. However, there are two ways you can inform programs (and people) about
the format that an XML document should have. The original method is to use a Document Type
Definition (DTD). This is another file format that describes the rules for an XML document. A newer
-283 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
method, XSchema (sometimes simply called a schema), describes the document's form at with
another XML document (which has a specific, published format defined by a DTD). By examining a
document and its related DTD or schema, any program can verify that an XML document is correct,
even if the program doesn't understand what the document contains.
XML Processing
To simplify working with XML, you can use programs known as parsers, which can interpret an XML
document. Of course, you usually want to do more than just break the XML into its constituent parts.
You probably want to act on the da ta in the XML file. All parsers take the following general steps:
Naturally, the last step is the tricky part. The parser knows only how to identify pieces of the XML
document. Somehow it has to communicate those pieces to your custom code.
Parsers can communicate an XML document to your program in one of two ways. A SAX (Simple API
for XML) parser calls your program immediately each time it detects a unique XML element. Using a
SAX parser is fast and easy, but it adds extra overhead to your program if you want to work with
relationships between elements. After all, each call occurs in isolation from the others. If your program
wants to study multiple nodes, it will have to store information between calls from the parser.
More complex parsers follow the DOM (Document Object Model). They return the entire document in
one piece structured as a tree. The parser will return an object that represents the root tag of the
document. Using methods in that object, you can enumerate the immediately subordinate tags (also
as objects). Of course, those objects might also have subordinate tags. A DOM parser allows you to
process the entire document easily, but it also requires that the parser completely process the
document before calling your program. As you might expect, this takes more memory and requires
more time before you can start processing.
Immediate Solutions
For some purposes, you might just want to write your own simple XML parser. Suppose that you want
to call a method that is on another machine. This process is commonly called a Remote Procedure
Call (RPC), and there are many ways to handle these calls. For now, suppose that you want to make
a simple RPC system that uses XML to direct the remote machine's actions and receive a response
from the remote machine.
Tip One common model of RPC is the Open Software Foundation's Distributed
-284 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
We will keep our RPC schema and its associated markup language modest, however; employing
RPC makes the XML application more compelling. The following is our sample XML document:
<rpc>
<method>addition</method>
<argument>5</argument>
<argument>97</argument>
<argument>30</argument>
<argument>221</argument>
<argument>97</argument>
<argument>4813</argument>
</rpc>
The goal for our XML -based RPC project is to compile a list of numbers, send it to another machine
where the list is added, and have the result shipped back. The previous XML document has only five
parts:
§ Comment
§ Prolog (the ?xml tag)
§ Root (the rpc tag)
§ Method name (addition in the above example)
§ Argument list
For this example, two classes will simulate the two disparate machines and dispense with actual
network code. The "server" will have four tasks:
1. Validate the request; that is, verify that the XML is properly formed and has the
necessary content.
2. Choose the action category; that is, extract the method name.
3. Read the arguments.
4. Perform the requested action.
The code will verify the XML document in the same way that commercial parsers do it (minus niceti es
like ignoring white space), like this:
Now we need to know which version of XML is being used. You need this information because later
versions might require a change in your processing rules. The program performs an easy string scan:
-285 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
Now we need to find out if the document is encoded properly, like this:
import java.util.*;
"<rpc>" +
" <method>ADD</method>" +
" <argument>5</argument>" +
" <argument>97</argument>" +
" <argument>221</argument>" +
" <argument>97</argument>" +
" <argument>4813</argument>" +
"</rpc>";
-286 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
if ( isXML )
// get arguments
ArrayList( xmlhelp.getList("argument") );
// show result
System.out.println(result);
} else
-287 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
class mathHelper
double total = 0;
double d = Double.parseDouble(number);
switch (choice)
case ADD:
total = total + d;
break;
case MULTIPLY:
total = total * d;
break;
case SUBTRACT:
-288 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
total = total - d ;
break;
case DIVIDE:
total = total / d;
break;
return Double.toString(total);
class xmlHelper
xmlHelper(String xml)
-289 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
// get operation
"</method>",0,false,false);
return line.trim();
return this.xml;
count++;
moreList = false;
if (start > 0)
start,false,false);
-290 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
aList.add(line);
if(line.length() > 0)
moreList = true;
start += line.length();
return aList;
start = 0;
end = 0;
sb.setLength(0);
count++;
isComment = false;
-291 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 9: XML and Java
sb.append( xml.substring(end + 3) );
oldStart = end;
isComment = true;
if (sb.length() > 0)
xml = sb.toString();
return isComment;
-292 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
result = true;
return result;
if (!includeOpen)
if (includeClose)
-293 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
You can do many things to tidy up the parser. For one thing, it doesn't grab XML files over the Internet
or on the hard disk. Another obvious problem is that the parser doesn't handle white space properly.
The parser also does not accept some valid Unicode characters. The specification says that all XML
processors must accept UTF -8 and UTF-16 (encodings of ISO/IEC 10646, the mechanisms for
signaling which of the two formats is in use). We can fix a few of these limitations if we create a string
stream out of the XML document and read it one character at a time. One approach for parsing one
character at a time is shown with the following pseudo-code snippet:
for (i=0;i<xml.length();i++)
char c = xml.charAt(i);
switch (c)
case '<':
parseOpenTag();
continue;
case '/':
parseCloseTag();
continue;
case '\t':
case '\n':
space = true;
continue;
case 'A': case 'B': case 'C': case 'D': case 'E': case 'F':
case 'G': case 'H': case 'I': case 'J': case 'K': case 'L':
case 'M': case 'N': case 'O': case 'P': case 'Q': case 'R':
case 'S': case 'T': case 'U': case 'V': case 'W': case 'X':
case 'a': case 'b': case 'c': case ' d': case 'e': case 'f':
-294 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
case 'g': case 'h': case 'i': case 'j': case 'k': case 'l':
case 'm': case 'n': case 'o': case 'p': case 'q': case 'r':
case 's': case 't': case 'u': case 'v': case 'w': case 'x':
addLetterToElement(c);
continue;
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
addDigitToElement(c);
continue;
default:
doSomethingWithWeirdCharacter(c);
Sun Microsystems knows that many developers will want to download all the XML APIs and libraries.
That's why Sun built the Java XML (JAX) Pack, provided at http://www.java.sun.com/xml/jaxpack.html.
From this page, you can download one package that contains all of the following APIs and
architectures:
§ Java API for XML Processing (JAXP)— Reads and interprets XML files by using a
standard interface to a variety of parsers.
§ Java Architecture for XML Binding (JAXB)— Allows you to write a Java object as an
XML file and to read XML files into an object.
§ Java Document Object Model (JDOM)— Converts an XML file into a tree of Java
objects.
§ Java API for XML Messaging (JAXM)— Allows programs to exchange XML-based
messages.
§ Java API for XML Registries (JAXR)— Allows you to publish the existence of XML
services for other programs to find.
§ Java API for XML-based RPC (JAX-RPC)— Allows you to make RPC calls using XML.
To use JAXP, you'll have to have the jaxp.jar and crimsom.jar files in your CLASSPATH. In addition,
JAXP can interface with third -party parsers (or you can use Sun's parsers). If you use another parser,
you'll need to follow the instructions for the parser you are using. Typically, you'll need to include more
-295 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
Creating a Parser
When you want to create an XML parser, you'll follow these basic steps:
1. Create a factory class by calling a static method (newInstance) of the factory class.
2. Use the methods from the factory class to create a new instance of the parser.
3. Call the parse method of the parser.
When creating a parser, you ha ve two choices: using a SAX parser and using a DOM parser. A SAX
parser allows you to process an XML document serially. When the parser detects different elements
of the XML file, the parser calls methods that you specify. For this style of parser, you'll use the
SaxParserFactory class as the factory. The newSAXParser method then creates the actual
SAXParser object.
The process of using a DOM parser is similar. You use the Document-BuilderFactory class as a
factory object. The factory's new-DocumentBuilder method creates a DocumentBuilder object.
This object then creates a DOM from XML input (resulting in a Document object). Here's the code
that creates the parser (without exception handling):
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance();
The SAX parser was designed to be fast, so it sprints sequentially through a document and fires
events when it finds something interesting. This approach is efficient (in particular, it doesn't require
much mem ory), but it isn't conducive to manipulating the document as a whole. Because the DOM
parser builds an entire document tree, it doesn't have this limitation. However, this parser is slow and
consumes more memory.
One common use for a DOM parser is to read a document, change it, and write the document back to
a file or other location (such as a network connection). You can even start with an empty DOM tree
and build a new document from scratch.
-296 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
Use SAX if you want a quick read, and use DOM if you want to cha nge the document in any
significant way. You can change little things (such as capitalizing character data) with SAX. But if you
want to change the document structure (such as by adding or sorting nodes), you need DOM.
SAX is an event-based API. When the SAX parser identifies an XML element, the parser calls a
function you specify so you can process the element. The SAX parser reads each character,
marching through the document sequentially, and calls your code as it identifies various events in the
document. For example, when the parser finds the start of an element, it fires the startElement event.
The parser uses many event callback functions (see Table 9.1).
* characters char ch[], int start, int Is called to report each chunk of ordinary
length character data.
ignorableWhitespace char ch[], int start, int Reports a chunk of white space in
length element content (see the W3C XML 1.0
recommendation, section 2.10).
processingInstruction String target, String data Is called for processing instructions (tags
that begin with ?xml).
-297 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
Those methods preceded with an asterisk in Table 9.1 are the ones you will work with most often. The
others are used less frequently. Suppose that you parsed this XML file with a SAX parser:
<item>
<ball id="97">
<color>blue</color>
</ball>
</item>
Table 9.2 shows the first few XML elements and their corresponding SAX callbacks. Notice that the
ends of line characters (\n) are not part of anything, so the parser treats them as character data. You'll
find a complete example in Listing 9.2 .
Table 9.2: SAX events occurring while the previous XML document is parsed.
XML Method Call
< startDocument()
<item> startElement
\n characters
<ball> startElement
\n characters
<color> startElement
blue characters
</color> endElement
\n characters
-298 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
import java.io.*;
import org.xml.sax.*;
import org.xml.sax.helpers.DefaultHandler;
import javax.xml.parsers.*;
if (args.length != 1)
System.exit(1);
try
-299 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
} catch (Throwable t)
t.printStackTrace();
System.exit(0);
// SAX events
print("startDocument()");
print("endDocument()");
-300 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
if (attribute != null)
// Attr name
aName+"=\""+attribute.getValue(i)+"\"";
Y
FL
result = "<" + qName + ">\t" + result;
AM
print(result);
}
TE
print(result);
-301 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 9: XML and Java
throws SAXException
printWhiteSpace(s);
System.out.println(s);
System.out.println(s);
startDocument()
<item> , , item,
"" buf[],_46,_0
"^" buf[],_0,_1
-302 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
"___" buf[],_48,_3
<ball> , , ball,
"" buf[],_57,_0
"^" buf[],_0,_1
"_____" buf[],_59,_6
<color> , , color,
"blue" buf[],_72,_4
</color> , , color,
"" buf[],_84,_0
"^" buf[],_0,_1
"_____" buf[],_86,_6
<id> , , id,
"97" buf[],_96,_2
</id> , , id,
"" buf[],_103,_0
"^" buf[],_0,_1
"___" buf[],_105,_3
</ball> , , ball,
"" buf[],_115,_0
"^" buf[],_0,_1
</item> , , item,
endDocument()
The character method replaces each new line with a ^ and replaces spaces with underlines so we
can see them better. Be careful with this method. As I mentioned earlier, the character method
receives calls for new lines outside of meaningful data. One way to decide if the characters are really
data is to keep track of the events and then determine if the event immediately preceding the
character event was a startElement. If it was, then you are looking at characters inside a node.
Otherwise, the characters are garbage. Try this:
int lastEvent;
-303 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
} else
//garbage so ignore
Most of your work will usually occur in the startElement and character event methods. You will
probably poll for key tags and take action when you find a match like this:
startElement()
if (name.equalsIgnoreCase("color"))
htmlBuffer.append("<font color=\"");
characters()
if(lastEvent == STARTELEMENT)
htmlBuffer.append(characterData);//data=color name
htmlBuffer.append("\">");
endElement()
-304 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
if (name.equalsIgnoreCase("color"))
htmlBuffer.append("</font>");
We can also keep track of tags with a Hashtable . This is useful if you want to generate a count of tags,
for example. Of course, a real program would probably read its input from the Web.
Generating HTML
You can also improve the output by formatting the report as a Web page instead of as plain text.
Displaying HTML is easy with Java's Swing components. You'll find a simple browser in Listing 9.3.
import javax.swing.text.*;
import javax.swing.*;
import java.io.*;
import java.awt.*;
-305 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
browser.setEditable(false);
try {
browser.setPage(page);
catch (IOException e) {
System.err.println(e);
System.exit(-1);
frame.setDefaultCloseOperation(WindowConstants.
DISPOSE_ON_CLOSE);
frame.getContentPane().add(scroller);
frame.setSize(750, 550);
frame.show();
It is easy to add HTML generation code to the event functions. Your code could be this simple:
startDocument()
print("<html>");
print("<head>");
print("<style>");
print("<!--");
-306 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
print(styleSheet);
print("-->");
print("</style>");
print("</head>");
print("<body>");
endDocument()
print("</body>");
print("</html>");
startElement()
print("<b>");
print(lName);
print("</b>: ");
endElement()
print("<b>");
print(lName);
print("</b>: ");
characters()
print("<i>");
print(data);
print("</i>: ");
-307 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
The DOM Level 2 Specification defines a way to represent an XML document as a tree structure. The
analogy describes a root node from which branches extend. Each node is itself a root for its sub-tree.
This is a common structure in programming, and you've probably seen it before.
Tip The Document Object Model (DOM) Level 2 Core Specification is available at
http://www.w3.org/TR/2000/REC-DOM-Level-2-Core-20001113.
The earlier section titled "Building an XML Parser to Serve as an RPC Engine" shows a simple RPC
system that uses XML. However, the parser is quite simple and doesn't correctly handle all legal XML.
You can fix the program by rebuilding it using a DOM parser. First, you have to load the JAXP APIs:
//JAXP APIs
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.FactoryConfigurationError;
import javax.xml.parsers.ParserConfigurationException;
//parsing exceptions
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
//file reading
import java.io.File;
import java.io.IOException;
import org.w3c.dom.Document;
import org.w3c.dom.DOMException;
import org.w3c.dom.*;
The W3C packages are the standards set by the World Wide Web Consortium. Java implements
these standards through interfaces that define the structure of an XML document. The SAX packages
are used to handle the exceptions.
-308 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
When XML is parsed, the strictness of the document definition forces the program to handle many
exceptions. One of the main features of XML is guaranteeing the validity of a document; this is why
exception handling plays a bigger role in XML than in ordinary Java programming.
if (args.length != 1)
System.exit(1);
DocumentBuilderFactory factory =
DocumentBuilderFactory.newInstance ();
//factory.setValidating(true);
//factory.setNamespaceAware(true);
Now we nee d to create a Document object from the XML document so we can walk through its tree.
The Document object allows the program to handle a variety of input sources, including InputStream
objects, files, URLs, and SAX InputSources. Here's the code that creates the Document object:
try
Now, the document variable contains an object that represents the entire XML document. After the
call to builder.parse , the document object is completely populated and ready for analysis.
The first step is to locate the requested mathematical operation. To do that, the program creates an
Element object by calling getDocumentElement— this corresponds to the document's root tag. You
call getElementsByTagName to retrieve a list of the elements with a specific name (in this case, the
list has only one entry). Here's the code:
-309 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
String operation =
operationNode.item(0).getFirstChild().
getNodeValue ();
The order of the items in the NodeList is the sam e as their order in the document. You might think the
value of the method node would contain the operation (for example, addition). However, the actual
text will be a child node of the method node. That's why the code has to call getFirstChild after
locati ng the method node. The getNodeValue call retrieves the actual text.
Now we can move forward and get the list of numbers. This requires another call to the
getElementsByTagName method, like this:
NodeList nl =
element.getElementsByTagName("argument");
Node node;
Because there can be any number of these nodes, the code loops through the list, like this:
node = nl.item(i);
//argument
//TEXT_NODE
nodeTypeName = nodeType.getTypeName(type);
parameter.add(nodeValue);
-310 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
The highlighted line shows a helper class ( NodeType) that is not a part of Java XML. This class
illustrates how you can expand the JAXP yourself. In particular, it isn't easy to get the type name of
the node. This class converts the integer representation of a node type into the appropriate string:
class NodeType
switch (type)
case ELEMENT_NODE:
break;
case ATTRIBUTE_NODE:
this.typeName = "ATTRIBUTE_NODE";
break;
case TEXT_NODE:
this.typeName = "TEXT_NODE";
break;
case CDATA_SECTION_NODE:
this.typeName = "CDATA_SECTION_NODE";
break;
-311 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 9: XML and Java
case ENTITY_REFERENCE_NODE:
this.typeName = "ENTITY_REFERENCE_NODE";
break;
case ENTITY_NODE:
this.typeName = "ENTITY_NODE";
break;
case PROCESSING_INSTRUCTION_NODE:
this.typeName = "PROCESSING_INSTRUCTION_NODE";
break;
case COMMENT_NODE:
this.typeName = "COMMENT_NODE";
break;
case DOCUMENT_NODE:
this.typeName = "DOCUMENT_NODE";
break;
this.typeName = "";
break;
case DOCUMENT_FRAGMENT_NODE:
this.typeName = "DOCUMENT_FRAGMENT_NODE";
break;
case NOTATION_NODE:
this.typeName = "NOTATION_NODE";
break;
default:
this.typeName = "UNKNOWN_NODE";
break;
return this.typeName;
The last section of the progr am is calling on the mathHelper class (as was done in the "Building an
XML Parser to Serve as an RPC Engine" section), like this:
-312 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
System.out.println(result);
argument: TEXT_NODE = 5
argument: TEXT_NODE = 97
argument: TEXT_NODE = 30
argument: TEXT_NODE = 97
5263.0
What about changing the XM L document programmatically? You can add, remove, or change
elements quite easily. The following code can be added to the RPCdom program:
//this is how you can add an element and text node with it
newArgument.appendChild(document.createTextNode("10000"));
element.appendChild(newArgument);
Warning Be careful about changing the XML tree in memory. The tree is not saved;
it's temporary. If you want to make the changes permanent, then you must
overw rite the original file (or save the changed tree to another file).
If you do include the code that adds an element, you will see different output, like so:
argument: TEXT_NODE = 5
argument: TEXT_NODE = 97
argument: TEXT_NODE = 30
argument: TEXT_NODE = 97
-313 -
Java 2 Core Language Little Black Book Chapter 9: XML and Java
15263.0
Tip For a quick list of methods that represent the complete Java Language [Java]
binding for the Level 2 Document Object Model Core, refer to
http://www.w3.org/TR/DOM-Level-2-Core/java -binding.html.
-314 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
In Brief
Java is such a big language that you might never have to use whole areas of it. If you plan to build
professional applications, however, you'll undoubtedly need to use several techniques. In particular, a
competitive professional program requires several things:
§ Speedy execution
§ Robust error handling
§ The ability to accept data from older versions of the same program
Java has special features to help you accomplish these goals. For example, multithreading can make
your program seem faster (or at least more responsive). Profiling tools can help you plan ways to
speed up your program.
In this chapter, you'll investigate two major techniques that real-world programs often use:
§ Advanced serialization features can help you handle data even if it originated in a different
version of your program that stores data differently.
§ Multithreading and profiling attack performance issues from two directions. A program that
uses multiple threads can perform multiple tasks at once (at least, the user thinks the
tasks are executed concurrently). Profiling allows you to identify slow areas in your
program that would ben efit from some extra work to make them faster or more efficient.
You'll see several techniques that can speed up sluggish programs.
In addition, the use of custom and advanced exception handling can make error handling more robust
and consistent in a program. If you've ever had a program mysteriously crash and wipe out the
document you were using, you'll know how important exception handling can be to users. If you want
to read more about it, read Chapter 3 .
Installation Programs
Professional applications usually have one other important feature: an installation program. It is
possible to write an installer completely in Java. To run this installer, however, the users must already
have a Java Virtual Machine (JVM) installed on their computer. The best installer will load Java if
necessary, but it isn't possible to write an installer like that in pure Java.
Fortunately, a variety of commercial installers handles this problem, and you are just as well off if you
use these. One that we've used often— and that is available in a free version— is ZeroG's Install
Anywhere (http://www.zerog.com). This program creates native executables for many platforms;
these executables will install the Java runtime, if necessary, plus your program. Install Anywhere also
-315 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
creates platform-specific program launching devices (such as Start Menu icons for Windows, for
example).
How can you tell objects apart? Objects of the same type have the same methods but have different
data in their fields (sometimes called their attributes). Objects of different types, of course, have
different methods and fields. So by examining the methods and fields of an object, you can identify
the type of the object. The actual data in the fields distinguishes the objects themselves.
To save an object to a file (or other persistent storage), you only need to store the object's type and
the actual unique data in the object's fields. To read the object back, you simply create an object of
the appropriate type and restore its previous state by storing the saved values in the new object's
fields. Java supports this process by way of a mechanism known as serialization.
Serialization has many possible uses. If you need to save and load a file (like a word-processing
document), you can do so by serializing your program's objects and then restoring them later.
Serialization can allow two network prog rams (for example, a multimedia conference system) to
communicate in an object -oriented way. Java takes care of differences, such as byte ordering and
other nuances, so you can send data between a Windows program and a Unix program, for example.
The base support for serialization is in the Object class. However, not all objects support serialization.
Any object that allows serialization implements the Serializable interface. If your class derives from a
class that implements Serializable (for example, most of the Java standard classes), your class is
automatically serializable.
Serializable is a special interface because it doesn't contain any members. Any class that declares
the Serializable interface automatically implements it. Then the writeObject method writes out the
class state to an ObjectOutputStream. Each object that supports serialization can provide a
writeObject method to customize how Java serializes it. If that method is absent, Java provides a
default (the defaultWrite-Object method in the ObjectOutputStream class).
oos.writeObject(s);
String previousString;
previousString = (String)ois.readObject();
-316 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
The variable previousString now has the correct contents. You can serialize all the primitives, arrays,
native objects (such as dates), and even your own classes.
What can be serialized? Most objects, but not all of them. TheObject class itself isn't automatically
serializable. If you create a class that you want to serialize, you must implement the Serializable
interface. You can also explicitly prevent fields from being serialized with the transient modifier, like
this:
If you include your own arbitrary magic number, however, Java will always attempt to load the object,
even if the object's definition has changed (as long as the magic number remains the same). However,
major changes (for example, a change in base class) can still cause an error. Of course, if you add
members that are essential to your program's operation, you might not be able to work with the old
object anyway.
Understanding Multithreading
Java supports multiple threads of execution per program. When your program has multiple threads, it
can appear to do multiple things at once. Each thread is like a separate program, but it shares many
resources (variables, for example) with other threads in the same program. Java parcels out time
slices to each thread so that the y appear to execute simultaneously. Computers that have multiple
CPUs can even execute several threads concurrently.
At first glance, it might seem that this would do little to improve performance. However, your threads
are often waiting for something (a network connection, for example) while the other threads can
continue executing.
Each thread is— not surprisingly— represented by a Java object. The object must either extend the
Thread object or implement the Runnable interface. In either case, you'll provide a run method that
implements the programming logic you want that thread to execute.
If you derive your object from Thread, you can call the object's start method to begin execution. If you
don't extend Thread, you'll have to pass an instance of your object to the constructor of a Thread
object. Either way, you call start. A common mistake is to call run directly. Don't call run yourself. If
you do, you'll simply execute the thread's code in the current thread. You won't create a new thread,
as you intended.
-317 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
When you have multiple threads accessing the same variables, it is crucial that multiple threads don't
try to alter variables at the same time. You can declare the field in question as private and access it
only through methods. Then you can declare each method as synchronized.
This technique works because each object has a lock associated with it. When any thread attempts to
access a synchronized member, the thread must first acquire the associated object's lock. Once one
thread owns the lock, no other thread can acquire the lock until the owning thread releases it (which
happens automatically when the synchronous operation is completed). You can even make static
members synchronized. Then the lock affects all objects of a given class, not just one particular
instance.
Sometimes you don't want to lock an object for the entire duration of a method call. For these cases,
you can explicitly synchronize on an object. For example, suppose you want exclusive use of an array
named myList . Consider this code:
synchronized (myList) {
mylist[10]=0;
Because every object extends Object, all objects have wait and notify methods. When you call some
object's wait method from within a thread, the thread goes into an efficient wait state. It will not wake
up again until some other thread calls the object's notify method. This allows one thread to wait for
another thread to complete an operation. Of course, both calls must occur in synchronized methods
(or at least within a synchronized code block) to ensure that threads don't conflict with each other.
Calling wait automatically releases the lock on the object (otherwise, no other thread could ever call
notify). You can optionally provide a timeout to wait so that the thread will not stop indefinitely.
If more than one thread is waiting on an object, calling notify will release one thread (and you can't
predict which one it is). However, you can call notifyAll to release all threads waiting.
By default, your program will continue to execute until all threads are com plete. However, sometimes
you want a thread that executes until the reset of the program is done. In that case, you can call the
Thread object's setDaemon method with a true argument. This allows the program to exit even if this
thread is still executing.
There's an old saying that you can never be too rich or too thin. For computer programs, it might be
better to say that you can't be too fast or too small. Over the years, many people have tried to speed
up programs by using a variety of techniques collectively known as optimization. Even Java is not
immune to these attempts. Vendors have improved the Java Virtual Machine (JVM) and provided just
in time (JIT) compilation.
If you analyze programs in any language, you'll find that most of the execution time occurs in just a
small fraction of the code. For example, suppose you print a report that has a header line and 100
data items on each page. For a 10 -page report, you'll print 10 header lines and 1,000 lines of data.
Obviously, if you want to tune the program's speed, you are better off concentrating on the code that
-318 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
prints the data instead of the code that prints the header. Before you try to optimize code, ask yourself
what would happen if the code you are looking at simply disappeared. If it wouldn't make much
difference, then why are you optimizing it?
Java programs are more difficult to optimize than other types of programs because of Java's "write
once, run everywhere" philosophy. Java programs don't execute directly on the user's computer.
Instead, the computer's JVM executes the bytecode. That means the JVM determines, to a large
extent, how fast or slow your code will run.
Even on the same operating system, you might find different JVMs. Some JVMs inter pret code one
byte at a time. Others first compile the code (at least partially) into machine language, spending extra
time up front for potentially faster execution.
So is it worth your time to try to optimize Java programs? Yes. It just requires a little extra attention.
Compiler Optimization
One way to get some degree of optimization for free is to enable optimization during compilation.
Exactly how much optimization occurs depends on your compiler. For the standard JDK compiler
(javac), you can enable optimization with the -o switch. This causes the compiler to calculate some
expressions at compile time, and it eliminates some unnecessary code in your output classes. Other
compilers, of course, may differ. IBM offers the Jikes compiler, for example. It has an -o option that
has nothing to do with optimization (instead, it suppresses certain outputs).
Using compiler -based optimization is a great idea for released code, but the compiler can make only
very simple improvements to your programs. The optimization methods that really pay off are those
that enhance your program's efficiency. Compilers can't do that. Instead, you'll have to study your
program and make intelligent choices about algorithms and coding practices.
Optimization Strategies
Optimization is n't so much a science as it is an art. Instead of hard rules, most optimization strategies
are really heuristics. Some optimization heuristics are universal and apply to most programs,
including Java code.
For example, a common observation is that most programs spend 90 percent of their time executing
10 percent of their code. The first rule of optimization is to speed up that 10 percent. If a line of code in
your program normally requires 10 milliseconds to execute and it runs only once, your maximum
possible improvement to that line of code is losing 10 milliseconds (if you can eliminate it).
Consider the same line of code in a loop that executes a million times. Now eliminating that part of
your code saves 10,000 seconds. Even cutting the time in half will save 5,000 seconds (that's more
-319 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
than 1 hour and 20 minutes). This is an extreme case, of course, but it does illustrate how a simple
improvement can make a big difference.
How can you know which parts of your code are executing more frequently than others? Good
question. In some obvious cases, simple inspection will do the trick. The problem is what to do about
the more subtle cases. Many development tools provide some sort of profiling that can tell you where
your code spends most of its time. Even the s tandard Sun SDK has a crude form of profiling.
Generating a Profile
To generate a profile for your applet, you need to start the JVM with the -prof option. If you want to
test an applet named in the xyz.html file, you might run this command:
This will generate a file (java.prof) that tells you quite a bit about your program's execution. Too bad
it's about as easy to read as ancient Sanskrit. Several freeware tools on the Internet will help you
display the file in a friendlier format.
However you read it, the profiler data can help you decide where you should focus your optimization
efforts. You can also add println statements at key points in your code to trace your program's
execution to determine how many times a particular piece of code executes.
Another way to instrument your code is to time particular operations to determine how much time they
actually consume. Consider several things to ensure accurate results:
§ Other programs can interfere with your timing; try to run the subject program with as
few other programs running as possible.
§ If the JVM initiates garbage collection during a test, the results will be inaccurate. To
minimize the possibility of an unexpected collection, force garbage collection by
calling System.gc before starting a test.
§ Although Java provides the time down to the millisecond (via either the Date class or
the System.currentTimeMillis method), your computer might not provide the time
to this level of accuracy.
§ You should repeat the operation many times to provide a meaningful measurement
period and to average out unusually fast or slow operations.
§ Of course, timing tests shouldn't require user input because it is wildly variable.
Don't forget: A code sequence that runs fast on one platform (or JVM) might run slowly on another. Be
aware that not all optimizations will be effective on all platforms.
What to Do?
Once you know which parts of your code need optimization, what should you do? First, think about
the algorithm that part of the code employs. For example, if you're searching an array for data,
-320 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
perhaps you could use a binary search algorithm or an indexed search. These are the hard
optimizations because they usually require you to tear out a portion of your code and rewrite it.
In extreme cases, you might have to change significant portions of your program. For example, you
might decide to use a binary search algorithm, but that requires a sorted list. So not only does the
search code change, but the code that inserts entries into the array changes also.
What about simpler optimizations? It is possible to alter small bits of your code to realize performance
benefits. Most of these types of changes are either common sense or techniques that are well known
(in particular, many C compilers are very good at applying optimization rules to your C programs).
Often the built-in library will perform functions faster than you can by using code. Perhaps the library
uses a native method in C or assembly language. Perhaps the library author simply spent more time
optimizing code than you're willing to spend. As an example, consider this code fragment:
Y
starting position, a destination array, the destination's starting position, and the length. So you could
FL
rewrite the previous code to read:
System.arraycopy(b,0,a,0,100);
AM
Is this faster? There's only one way to know: Profile it. Your results will depend on your machine's
speed, the JVM, and the operating system.
TE
Number Tricks
If you remember a few rules when using numbers, they will help your program run at top speed. First,
always use integers where possible. Most modern computers handle integers much faster than
nonintegers. You should also try to compute common subexpressions. Consider this code fragment:
X=P*(discount/100);
Y=P*(1-discount/100);
A nonoptimizing compiler will calculate discount/100 twice, even though the result of the first
calculation will be the same as the second. You can save time if you perform the calculation once and
reuse the result, like this:
T=discount/100;
X=P*T;
-321 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
Y=P*(1-T);
Another common trick is to use strength reduction to replace multiplication and division with shift or
add operations (because these are usually faster than multiplication and division). This is easiest
when you're multiplying or dividing by a power of 2. For example:
For division, this is of no use unless you want to divide by a power of 2. However, multiplication can
often be rewritten to use shifts even if it takes more than one shift:
X=Y*10;
You can also apply a similar technique to get rid of multiplication inside loops. For example, consider
this loop:
for (i=0;i<10;i++) {
int z=i*10;
...
int z=0;
for (i=0;i<10;i++) {
...
z=z+10; }
Do all of these things really work? It depends. In informal testing, we found that shifting is usually
faster than multiplying; however, for the JDK 1.1.7 JVM for Windows, the multiplications are still faster.
For Internet Explorer 5, the shifts are faster. This just proves that you have to measure things instead
of guessing.
-322 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
Immediate Solutions
Serializing an Object
Listing 10.1 shows a program that creates an object (someObject), sets one attribute (color), and
then serializes it.
import java.io.*;
String previousState;
dyingObject.setColor("green");
previousState = dyingObject.getColor();
previousState);
try
-323 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
objectOutputStream =
new ObjectOutputStream(fileOutputStream);
objectOutputStream.writeObject(dyingObject);
objectOutputStream.flush();
fileOutputStream.close();
} catch(IOException ex)
ex.printStackTrace();
dyingObject = null;
System.out.println(
System.out.println();
try
objectInputStream =
-324 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
new ObjectInputStream(fileInputStream);
resurrectedObject =
(SomeObject)objectInputStream.readObject();
previousState =
(String)objectInputStream.readObject();
fileInputStream.close();
+ newState);
System.out.println(previousState);
} catch (Exception e)
-325 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
this.color = color;
return this.color;
The first two highlighted lines are where Java writes the two objects (instance of SomeObject and
String) to the file (object.ser). The second set of highlighted lines is where Java reads the file and
assigns the values it finds there to the object, or to objects if you serialized several to the same file. If
you look at the object.ser file, you'll find only four things you can read— namely SomeObject, color,
green, and Little Black Book. There are a few overhead bytes before each of these pieces of text.
These bytes encode information that Java needs in order to reconstitute the object correctly.
Customizing Serialization
If you provide your own objectWrite method, you can customize how serialization works. For
example, you might want to encrypt or compress data before saving it to disk. Of course, you'd also
have to provide a custom objectRead method to deserialize. The following code is what you would
add to the SomeObject class shown previously:
throws IOException
stream.defaultWriteObject();
this.color = this.color.substring(0,this.color.length()-3);
-326 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
stream.defaultReadObject();
this.color = this.color.substring(0,this.color.length()-3);
}
Adding the previous code to Listin g 10.1 would result in the following:
object color=green
serialized color=greenish
object color=green
deserialized color=greenish
object color=green
Creating a Thread
To make a thread, you subclass Thread and override its empty run method. The run method does
whatever task you want the thread to perform. Listing 10.2 shows you how to create the subclass.
Notice that to start the thread, you create an instance of the object and call start .
-327 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
new ColorThread("Green").start();
new ColorThread("Red").start();
new ColorThread("Purplish").start();
this.color = color;
System.out.println(this.color);
try {
Thread.sleep(1);
-328 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
catch (InterruptedException e) { }
In some cases, you don't want to derive your class from Thread. Remember, in Java your class can
only extend one base class. So if your class already has a base class, it can't also extend Thread.
Fortunately, you can make any object implement the Runnable interface (which has only one method:
run). Then you can pass your object to the Thread object's constructor to obtain a thread. After that,
everything is just like the example in Listing 10.2 .
{
The main method would change to look like this:
You place the method call in the thread that you want to have wait. You prefix the method with the
thread that you want to wait for, like so:
ThreadB.join(1000);
Suppose this statement was placed in one thread (ThreadA). Upon executing this statement,
ThreadA will pause until ThreadB dies. The 1000 is the number of milliseconds to wait. ThreadA will
resume when ThreadB dies or in 1 second (1,000 milliseconds), whichever occurs sooner.
You can force one thread to step aside for another with the yield method, which allows other threads
to execute. You can also put your thread to sleep for a number of milliseconds by using sleep. Listing
10.3 shows several operations involving threads.
-329 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
red.setName("Red Thread");
purple.setName("Purplish Thread");
//red.start();
//purple.start();
boolean true_false;
String string;
Thread current;
Thread[] allThreads;
ThreadGroup group;
-330 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
group = green.getThreadGroup();
current = Thread.currentThread();
System.out.println( current.getName() );
count = Thread.activeCount();
limit = Thread.enumerate(allThreads);
Y
string = allThreads[count].getName();
FL
System.out.println( string );
AM
// adjust priority
TE
red.setPriority(red.MAX_PRIORITY);
purple.setPriority(red.NORM_PRIORITY);
green.setPriority(red.MIN_PRIORITY);
System.out.println( red.getPriority() );
purple.setDaemon(true);
System.out.println( purple.isDaemon() );
System.out.println( red.isDaemon() );
-331 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
red.interrupt();
System.out.println( red.interrupted() );
System.out.println( red.isInterrupted() );
System.out.println( red.isAlive() );
Thread.yield();
try {
Thread.sleep(1000);
} catch(InterruptedException e) {
try {
green.join(1000);
} catch(InterruptedException e) {
Thread.dumpStack();
try {
green.destroy();
} catch(NoSuchMethodError e)
-332 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
//returns:
//main
//4
//main
//10
//true
//false
//false
//false
//false
Notice that the highlighted start statements have been commented out. If you don't do this in this
example, the threads will complete and exit before the rest of the code can execute. You can fix this
by increasing the time specified in the call to sleep in the Color class's run method.
You can also make one thread wait for another thread to signal it; you do this by using wait and notify.
When a thread calls an object's wait method, the thread goes into an efficient wait state. The thread
will not wake up again until some other thread calls the same obj ect's notify method. Both calls must
occur in a synchronized block to ensure that the threads don't conflict with each other. You can
optionally provide a timeout to wait so that the thread will not stop indefinitely.
If more than one thread is waiting for an object, calling notify will release only one thread (and you
can't predict which one it is). However, you can call notifyAll to release all threads waiting.
Optimizing Objects
Although object orientation is a powerful part of Java, it's also an elemen t where efficiency can suffer
if you aren't careful. Creating new objects is expensive. When possible, avoid calling new if you can
reuse an existing object instead. This is especially true inside loops. If you can create one object
outside of a loop and reuse it, your code will be faster than similar code that creates a new object
during each loop iteration.
Another expensive operation is calling member functions that might have overrides in a derived class.
Even if no class extends the current class, Java has to search for other functions on each call (this is
similar to using virtual methods in C++). However, if your function is private or final, or if the class
you're using is final, Java can directly call the function because no other class can override the
function. Because of this optimization, it is best to declare everything private or final when possible.
-333 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
test = X;
The code works, but it isn't very efficient because you have to create (and destroy) a temporary object.
If you want to make many changes in a string, you should consider using the StringBuffer class. For
example:
StringBuffer testbuffer;
String test;
testbuffer.append("Still no worse!");
test=testbuffer.toString();
How does the StringBuffer perform an append? The StringBuffer is essentially a character array
wrapped with helpful methods. Every time you call the append method, the StringBuffer code
compares the size of the proposed new string with the room available at the end of the array. If there
is room, the code just copies the new string to the free space. If there isn't room, a new character
array is created that is larger than the old buffer. The code moves the contents of th e old array to the
new array and then appends the string. Of course, in this case, the call still creates and destroys
arrays, but many times the call simply uses the available space.
The improved speed and memory efficiency are very important when string manipulations are
performed inside a loop. However, String-Buffer could be faster. One thing you can do to help
-334 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
StringBuffer is to try to anticipate how much space you'll need and then initialize the buffer
appropriately. Remember that if you run out of space Java will have to allocate and deallocate an
array, and that's what you want to avoid. Here is a buffer set to 1,024 characters:
One way to speed up the StringBuffer class is to write your own append method like this:
if (limit == buf.length)
buf = tempChar;
buf[limit++] = c;
}
This custom append method runs twice as fast as the native append method because the custom
method checks the array size locally rather than by calling a method as the Sun library does. Of
course, you will gain a lot of speed if you skip the array size check altogether (the highlighted code).
Then you have to be careful not to overrun the buffer.
The next best thing you can do to increase the StringBuffer speed is to replace Sun's synchronized
methods with your own unsynchronized ones (assuming that you don't need thread safety). You can't
just extend StringBuffer, however, because it is a final class.
-335 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
Instead, you can write your own version of the class with just a few methods that you will call the most
often. The two things you want to do with your version are to exclude synchronized methods and to
avoid the capacity check when appending. Calling a synchronized method takes several times as
long to complete as does calling an equivalent method that is not synchronized. You can copy the
method code from StringBuffer (you can download the source to the Java library from Sun's Web
site) and paste it into your class; then remove the synchronized modifier to gain a lot of speed.
One last note on processing strings faster: Avoid using the charAt method. You pay for the method
invocation overhead and the boundary check performed every time you call this method. We
recommend converting the string to a character array and marching through the array by using normal
indexing.
Optimizing Loops
Loops are an easy target for optimization because they are obviously repeating statements. The
common way to write for loo ps is like this:
// statements;
}
For most JVMs, however, comparing an int to a zero is very fast, so the loop will execute faster if you
rewrite it like this:
// statements;
}
Often, a for loop is used to iterate through an array. Java has built-in boundary checking, which
prevents you from going past the ends of the array. You can take advantage of exception handling to
skip the test, like this:
try
array[index] = expression;
catch (ArrayIndexOutOfBoundsException e) { ; }
Of course, throwing an exception has lots of overhead, so for a few iterations this is probably not
worth the effort. But if you are working with large arrays, this technique might be more efficient. To be
sure, you'll have to profile on the JVM you are interested in.
-336 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
Tip Use local variables in loops whenever possible. If you don't, the JVM has to do
extra work to get the reference. It is often useful to assign an object's fields to a
local variable before entering a loop so that the loop can work with the local copy.
Method calling involves overhead, particularly in a loop. You have many opportunities to speed things
up by writing your own code inline rather than calling a method. For example:
Optimizing I/O
If you are reading files, you should adopt a definite strategy. You want to read as many bytes or
characters at a time as possible. Avoid reading one byte at a time. You can use Java classes (like
BufferedReader)
that will read multiple characters and dole them out to you more slowly, if you like. The idea is to avoid
asking the hardware for more data when possible. The following code demonstrates the difference
between reading one byte at a time (DataInputStream ) and reading many bytes at a time
(BufferedReader):
import java.io.*;
int lineCount = 0;
try
byte c;
FileInputStream fis =
new FileInputStream("SlowFileReader.java");
DataInputStream dis =
new DataInputStream(fis);
while (true)
-337 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
c=dis.readByte();
if (c=='\n') lineCount++;
startTime = System.currentTimeMillis();
lineCount = 0;
try
FileInputStream fis =
BufferedReader buffReader
lineCount++;
fis.close();
} catch (Throwable e)
System.err.println("exception");
-338 -
Java 2 Core Language Little Black Book Chapter 10: Advanced Techniques
int iterations,
Stri ng event)
System.out.println(report);
-339 -
Java 2 Core Language Little Black Book Chapter 11: Security
In Brief
Java supports the encryption and decryption of data. For the purposes of this chapter, security has
several goals:
§ Confidentiality— By encrypting data, you ensure that only the intended recipient can read
the data.
§ Authenticity— Using a digital signature ensures that data is from the intended source.
§ Nonrepudiation — A digital signature prevents a sender from denying his or her origination
of the data.
§ Integrity— By using a digest (described later), a recipient can verify that data was not
modified since it was signed.
It is natural to think of these items in terms of email because that is where we encounter them most
often. However, any data might require security. For example, when you visit a secure Web site, you
need to know that the site really is the one it says it is. So even if I managed to hijack your bank's URL,
you would know that it was not your bank's Web site because I can't sign data w ith the bank's secret
key. For the purposes of this chapter, data that you want to encrypt or decrypt will be called a
message. That terminology doesn't presuppose any particular way of transmitting that message.
One thing that is central to securing data is a message digest. A digest is like a very long checksum.
You perform calculations on a message and generate a fixed-length signature that represents it
(similar to a hash code). While it is possible that two messages will have the same digest, it is ver y
unlikely. Digests are most important when it comes to signing messages. Signing a message allows
the recipient to verify the message originator and detect any tampering that might have occurred
during the message's transmission.
Security Overview
Most modern security schemes rely on algorithms that in turn rely on keys. These keys are nothing
more than unique numbers (perhaps very large numbers) that are used in an algorithm to scramble
(or unscramble) the bits in a message.
Companies like RSA Security (one of the big players in the security business) publish these
algorithms, so they are not secret (the algorithms might be copyrighted or patented, but they aren't
secret). The entire security, then, is in selecting keys that make it difficult to reverse the algorithm.
-340 -
Java 2 Core Language Little Black Book Chapter 11: Security
One of the strengths of this approach is that the algorithms are subject to public review; any possible
weakness will be quickly exploited (and fixed).
Your bank probably has better locks and alarms on its doors than you have on your house. Fort Knox,
Kentucky, where the United States stores its gold, probably has even better locks. No lock is
unbreakable, however, and that also applies to encryption methods. Given enough time and computer
power, any code is breakable. However, when the cost and trouble of breaking the lock exceeds the
cost of the contents, you can deem the lock safe enough.
In general, longer keys make for tougher security. For example, old Web browsers often used 56 -bit
keys. As computers have become faster, breaking keys of any length has become easier. Now,
128-bit keys are the standard for secure Web sites. As computers become even faster, longer keys
will become necessary.
Exactly how you use and select a key depends on the algorithm you are using. For most modern
algorithms, however, the key will have some relationship to a very large prime number. Also, nearly all
modern methods use something known as public key cryptography. In this scheme, there are two
related keys. One is secret and is known as the private key. The other key— the public key— can be
freely distributed to anyone. This allows someone to encrypt something with your public key that only
Y
you can decode. The mathematics are such that knowing the public key doesn't help you crack the
FL
message, nor does it help yo u guess the private key.
AM
Java's library has many routines you can use to generate and use keys without much trouble. The
library doesn't actually perform these tasks; instead, it interfaces with a security provider. Sun's
default implementations of the security routines (in java.security) can handle most common
TE
situations. However, it would be possible for sophisticated systems to use, for example, identity cards
read with special hardware to assist in key generation or authentication.
Immediate Solutions
A message digest is similar to a hash code. The digest typically contains more bits than an ordinary
hash code does, and a digest applies to a block of data. The digest algorithm should have these
characteristics:
§ The algorithm is one-way; you can compute a digest from the message, but you can't
recover the message from the digest alone.
§ Small changes in the message should result in large changes in the digest.
§ The algorithm should be fast and efficient to compute.
§ The same message must always generate the same digest.
§ The digest should be short (on the order of 1KB or so).
-341 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 11: Security
§ Ideally, no two messages should produce the same digest. In practice, this isn't
possible, but you'd like to have a wide distribution of digests for different messages.
You can write your own digest algorithm. For example, you can calculate the sum of all the Unicode
character values in a string, but this algorithm doesn't meet the previously stated goals very well. The
immediately obvious problem is that you can swap characters around and get the same digest (in
other words, the digest of AB is the same as the digest for BA). You can fix that problem by multiplying
each character by its position expressed as a number. Even then, small changes in the text cause
only small permutations in the digest. You can partially solve this problem by using the
random -number generator. At each character (times position), you seed the generator, and you use
the resultant random number as part of the digest.
Given the same seed, Java's random -number generator will produce the same number. For a set of
inputs, the random -number generator produces numbers that cover the entire output range. In this
context, random doesn't mean unpredictable; it means randomly distributed over the output range.
Listing 11.1 shows a Java digest function. The MessageDigestTest class uses the built-in digest
function known as the SHA-1 algorithm. The MessageDigest.getInstance call returns an object that
implements the specified algorithm.
import java.io.*;
import java.security.*;
import java.lang.StringBuffer;
try
FileInputStream fis =
BufferedInputStream bis =
-342 -
Java 2 Core Language Little Black Book Chapter 11: Security
// a ByteArrayOutputStream
ByteArrayOutputStream baos =
new ByteArrayOutputStream();
int iByte;
baos.write(iByte);
// there are other ways this could have been done, of course
MessageDigest algorithm =
MessageDigest.getInstance("SHA-1");
// compute digest
algorithm.update(buffer);
-343 -
Java 2 Core Language Little Black Book Chapter 11: Security
hexString.append(
hexString.append(" ");
// print it
System.out.println(hexString.toString());
catch(java.io.FileNotFoundException e) { }
catch(java.io.IOException e) { }
catch(java.security.NoSuchAlgorithmException e) { }
//returns: //33 b3 69 32 fc f1 3 34 ff 4d 82 e2 a1 a2 25 46 43 60 74 22
I added only one space to the input file and ran the program again. This time it returned the following:
cd e3 f db 6e 11 eb 94 51 f5 94 8c e7 17 16 e7 4d 35 2f d1
One extra space resulted in a very different digest. The program converted my 800-word test file into
a digest in the blink of an eye.
Digests are important when it comes to signing mess ages (covered later in this chapter). You'll
occasionally hear digests referred to as fingerprints because they tend to identify a message uniquely.
The example code uses the SHA-1 digest algorithm. This algorithm was developed by the National
Institute of Technology (NIST) and generates a 160 -bit key. Another popular algorithm, MD5 (from
Professor Ronald Rivest), generates a 128 -bit key and is therefore somewhat faster than SHA-1.
-344 -
Java 2 Core Language Little Black Book Chapter 11: Security
Of course, there is no completely unique way to represent a document of arbi trary length in 128 bits
(or even 160 bits). It is possible that two messages will generate the same digest, but the construction
of the algorithms makes this as unlikely as possible and also ensures that small changes to the
document will result in large changes in the document. Therefore, documents that do generate the
same digest should be very dissimilar. Changes made by an interloper, or garbling during
transmission, are almost sure to produce a different digest.
Many encryption algorithms require randomly distributed numbers. You can create random numbers
easily with the code in Listing 11.2 .
import java.util.Random ;
if (args.length != 2)
"howManyRandomNumbers maximumNumber");
System.exit(1);
-345 -
Java 2 Core Language Little Black Book Chapter 11: Security
//returns:
//87 35 76 24 92 49 41 45 64 50 79 59 72 83 36 75 46 2 23 41
Java 's random-number generator calculates numbers that are randomly distributed between two
extremes. The previous program prints numbers between zero and the maximum number provided at
the command (100 in Listing 11.2). Because the example uses the same seed every time, you will get
the same sequence of random numbers each time you run the program. If you do not provide a seed,
the default constructor uses the system clock as the seed. Using the system clock provides results
that are difficult for a human to guess but not hard for a computer to guess (this method is good for
things like games, but not good for encryption).
If you require a n unpredictable sequence (mandatory in security applications), you will need
something better than Java's Random class. Java also provides the SecureRandom class, which is
more suitable. In the previous program, you'd replace the Random object with a SecureRandom
object, like this:
Notice that the seed is now a byte array rather than the integer used with the Random object. This
small change produces the following result:
//returns:
//50 8 39 12 49 31 41 67 70 66 17 12 88 3 21 47 13 7 92 11
This sequence repeats, given the same seed. What's the advantage of using the SecureRandom
class instead of the plain Random class? The SecureRandom class has a default constructor that
-346 -
Java 2 Core Language Little Black Book Chapter 11: Security
doesn't use the system clock to get a seed. This class uses something that is system -dependent and,
presumably, harder to guess.
Keys are a crucial part of Java's security system. You generate keys in pairs: one private key and one
public key that go together. The idea is that you can give away your public key, but you keep your
private key a secret.
Listing 11.3 demonstrates how to generate the pair of public and private keys, separate the two keys,
and decompose each key into its constituent parts. (Each key has several parts, each represented by
a BigInteger.) The actual key is the x (private) or y (public) portion of the key. The p, q, and g parts
are different parts of the algorithm used to select the keys (the prime, subprime, and base numbers).
The exact format of the key depends on the algorithm you select. Although the KeyPair object
appears to contain PublicKey and PrivateKey types, these are abstract classes. In reality, the actual
type of the key will depend on the algorithm you select (in this case, the types are DSAPublicKey and
DSAPrivateKey).
import java.security.interfaces.*;
import java.security.*;
import java.io.*;
import java.math.BigInteger;
KeyPairGenerator kpg ;
BigInteger g;
BigInteger q;
-347 -
Java 2 Core Language Little Black Book Chapter 11: Security
BigInteger p;
BigInteger y;
BigInteger x;
String keyDescription;
DSAParams parameters;
DSAPublicKey publicKey;
DSAPrivateKey privateKey;
try
kpg = KeyPairGenerator.getInstance("DSA");
// key twice.
publicKey = (DSAPublicKey)keyPair.getPublic();
parameters = publicKey.getParams();
g = parameters.getG();
p = parameters.getP();
q = parameters.getQ();
y = publicKey.getY();
-348 -
Java 2 Core Language Little Black Book Chapter 11: Security
keyDescription = publicKey.toString();
System.out.println("\n" + keyDescription);
System.out.println("\n");
privateKey = (DSAPrivateKey)keyPair.getPrivate();
parameters = publicKey.getParams();
g = parameters.getG();
p = parameters.getP();
q = parameters.getQ();
x = privateKey.getX();
keyDescription = privateKey.toString();
System.out.println("\n" + keyDescription);
} catch(NoSuchAlgorithmException e)
-349 -
Java 2 Core Language Little Black Book Chapter 11: Security
System.out.println(e);
You can supply these keys to objects that need them, such as a Cipher object (see the next
Immediate Solution). The program returns the following results:
prime p = 132323768951986124075479307187577282674355270296234088
7224515603975771302903636871914645218604120423735052178524033704
8752071462798273003935646236777459223
subprime q = 857371293708094202104259627990318636601332086981
base g = 5421644057436475141609648488325705128047428394380474376
8346673007661082626139005426812890807137245973106730741193551360
85795982097390670890367185141189796
4527746796132910549161386659963553557065253699005275831735761530
887041401179490527327510693886724011471
Parameters:
bdc43ee7 37592e17
q:
g:
6c416e50 be794ca4
y:
-350-
Java 2 Core Language Little Black Book Chapter 11: Security
8372f697 1941f5cf
prime p = 132323768951986124075479307187577282674355270296234088
7224515603975771302903636871914645218604120423735052178524033704
8752071462798273003935646236777459223
subprime q = 857371293708094202104259627990318636601332086981
base g = 5421644057436475141609648488325705128047428394380474376
8346673007661082626139005426812890807137245973106730741193551360
85795982097390670890367185141189796
parameters: Y
FL
p:
AM
bdc43ee7 37592e17
TE
q:
g:
6c416e50 be794ca4
x: 3a04fefa00731ceb7d461ab7766e8f4964943521
The program selects a length of 512. The output would be twice as long if you selected 1,024 (the
only other choice in the Sun security implementation). Did you notice that the p, q, and g numbers are
the same? In the default implementation, these numbers are based partly upon hardware (such as a
network interface card's ID). For a full discussion of the math used with keys, please see RSA
Security's Web site (http://www.rsa.com).
-351-
Team-Fly®
Java 2 Core Language Little Black Book Chapter 11: Security
The two most frequently performed security actions are encrypting and decrypting messages. After
you have computed keys, you use them to alter data. For example, suppos e you have the letter A.
The Unicode value for A is 0x0041 (65 decimal). To encrypt it, you need to convert this value to
another value. The trick is to convert it in such a way that only the intended recipient can decode it.
The code in Listing 11.4 encodes and decodes a string. Like the previous example, it generates a key.
This example then uses an instance of the Cipher class to encode the text (taken as a byte array) into
another byte array, which is encrypted using the key. The program then decrypts the string. Of course,
you usually won't have the encryption and decryption steps for the same data executing so close
together. Usually, you'll encrypt the data and then send it or store it somewhere. Later, you'll receive
or recall the data (perhaps using a different program), and decrypt the data.
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
import java.lang.*;
if (args.length != 1)
"string");
} else
-352 -
Java 2 Core Language Little Black Book Chapter 11: Security
sourceString = args[0];
try
mode + "/" +
padding;
KeyGenerator kg = KeyGenerator.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key);
for(int i=0;i<input.length;i++)
-353 -
Java 2 Core Language Little Black Book Chapter 11: Security
System.out.print(Byte.toString(input[i] ) + flag);
System.out.println("\n");
System.out.println("Encrypted: ");
for(int i=0;i<encrypted.length;i++)
System.out.print(Byte.toString(encrypted[i]) + flag);
System.out.println("\n");
// Decrypt it
cipher.init(Cipher.DECRYPT_MODE, key);
System.out.println(new String(output));
} catch (Exception e)
e.printStackTrace();
//returns:
-354 -
Java 2 Core Language Little Black Book Chapter 11: Security
//
//Encrypted:
//97 3 28 11 -80 11 23 24 96 37
//-103 21
//
The two highlighted lines in this code are the beginning of the decrypt section. You can initialize a
Cipher object to encode or decode. The key, in this case, comes from the code just above these two
highlighted lines, in the same method. In real life, you'd probably have to supply the key in another
way (for example, by using an input file).
Encrypting a File
The previous solution demonstrated how to encrypt a string. This next solution goes a step further and
encrypts an entire file. Although this seems like it should be a similar process, there are several
pitfalls you have to avoid. Fortunately, there is a special class, the Cipher-OutputSream, that
handles most of these details for you. Listing 11.5 shows the program. The CipherOutputStream
(see the highlighted section of Listing 11.5 ) allows you to encode anything that you would normally
use as a stream. That might be a file, a network socket, or even a string if you wanted to use a
string-based stream.
-355 -
Java 2 Core Language Little Black Book Chapter 11: Security
You pass a Cipher to the CipherOutputStream constructor. Obviously, if that Cipher is set to
encrypt, the stream will encrypt. If the Cipher is set to decrypt, the stream will decrypt (see the next
Immediate Solution).
import java.security.*;
import javax.crypto.*;
import java.io.*;
class EncryptFile
if (args.length != 3)
try
-356 -
Java 2 Core Language Little Black Book Chapter 11: Security
mode + "/" +
padding;
KeyGenerator kg = KeyGenerator.getInstance(algorithm);
cipher.init(Cipher.ENCRYPT_MODE, key);
FileOutputStream fos =
new FileOutputStream(encryptedFile);
CipherOutputStream cos =
-357 -
Java 2 Core Language Little Black Book Chapter 11: Security
int ch;
cos.write(ch);
cos.flush();
fis.close();
FileOutputStream keyfile =
new FileOutputStream(keyFile);
keyfile.write(key.getEncoded());
keyfile.close();
} catch (Exception e)
-358-
Java 2 Core Language Little Black Book Chapter 11: Security
Decrypting a File
After you've encrypted a file, you use CipherOutputStream again to decode it. The difference is that
in the CipherOutputStream constructor, you provide a Cipher object initialized to do decrypting.
Listing 11.6 shows a program that will decode a file encrypted with Listing 11.5 .
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.io.*;
class DecryptFile
if (args.length != 3)
try
-359 -
Java 2 Core Language Little Black Book Chapter 11: Security
mode + "/" +
padding;
FileInputStream keyStream =
n ew FileInputStream(keyFile);
keyStream.read(keyBytes);
keyStream.close();
SecretKeyFactory keyFactory =
SecretKeyFactory.getInstance(algorithm);
cipher.init(Cipher.DECRYPT_MODE, secretKey);
-360 -
Java 2 Core Language Little Black Book Chapter 11: Security
FileInputStream fis =
new FileInputStream(encryptedFile);
FileOutputStream fos =
new FileOutputStream(decryptedFile);
CipherOutputStream cos =
Y
FL
// feeding bytes into CipherOutputStream
AM
int ch;
TE
cos.write(ch);
cos.flush();
fis.close();
cos.close();
-361 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 11: Security
} catch (Exception e)
The process of encrypting and decrypting files without the CipherInputStream and
CipherOutputStream objects is prone to error. The streams take care of padding data so that the
algorithm always works with a fixed-size block and handles other details you'd rather not worry about.
How can you use encryption to sign a message? That is, given a message, how can you be sure that
it originated from the supposed sender and wasn't modified in transit? One approach is to compute a
digest of the message and encrypt it. The recipient can then compute the same digest of the message
and decrypt the digest that was sent. If the digests don't match, something is amiss. Eithe r the sender
did not have the correct keys, or someone tampered with the message.
The Signature class encapsulates this logic. The program in Listing 11.7 demonstrates how to sign a
file digitally by using Signature.
import java.security.*;
import java.io.*;
class MakeSignature
-362 -
Java 2 Core Language Little Black Book Chapter 11: Security
if (args.l ength != 1)
} else try
SecureRandom random =
SecureRandom.getInstance("SHA1PRNG", "SUN");
byte[] byteArray;
KeyPairGenerator keyGen =
keyGen.initialize(1024, random);
Signature dsa =
Signature.getInstance("SHA1withDSA", "SUN");
-363 -
Java 2 Core Language Little Black Book Chapter 11: Security
dsa.initSign(privateKey);
byteArray = privateKey.getEncoded();
file.saveFile("privatekey", byteArray);
int len;
while (bin.available() != 0)
len = bin.read(buffer);
dsa.update(buffer, 0, len);
bin.close();
byteArray = dsa.sign();
file.saveFile("signature", byteArray);
-364 -
Java 2 Core Language Little Black Book Chapter 11: Security
byteArray = publicKey.getEncoded();
file.saveFile("publickey", byteArray);
} catch (Exception e)
//helper class
class FileSave
this.fileName = filename;
*/
try
-365 -
Java 2 Core Language Little Black Book Chapter 11: Security
this.fis.write(fileData);
this.fis.close();
} catch (Exception e)
The two highlighted lines on the previous page are the heart of this program. They are where the file's
bytes are sent to the Signature object. This object computes the digest and encrypts it with the
private key. The FileSave class is simply a helper class to store the results. This program produces
three new files— one each for the private key, the public key, and the signature itself.
Once you have a signed file, you need a way to verify the digital signature. Remember that a digitally
signed message doesn't alter the original message in any way, so it might be in plain-text form. (Of
course, you could also encrypt the entire file to keep it private; encryption and signing both use
encryption, but they use it for different reasons.)
To verify a message, you compute the digest and then use the public key to decrypt the message
digest that resides in the signature file. Finally, you'll compare the two message digests. The program
in Listing 11.8 demonstrates how to do this.
import java.security.*;
import java.security.spec.*;
import java.io.*;
class VerifySignature
-366 -
Java 2 Core Language Little Black Book Chapter 11: Security
if (args.length != 1)
} else
try
SecureRandom random =
SecureRandom.getInstance("SHA1PRNG", "SUN");
publicKeyBytes = file.getFileBytes("publickey");
X509EncodedKeySpec pubKeySpec =
new X509EncodedKeySpec(publicKeyBytes);
KeyFactory keyFactory =
KeyFactory.getInstance("DSA", "SUN");
PublicKey publicKey =
-367 -
Java 2 Core Language Little Black Book Chapter 11: Security
keyFactory.generatePublic(pubKeySpec);
/* Get signature */
signatureBytes = file.getFileBytes("signature");
Signature dsa =
Signature.getInstance("SHA1withDSA", "SUN");
dsa.initVerify(publicKey);
int len;
while (bin.available() != 0)
len = bin.read(buffer);
dsa.update(buffer, 0, len);
bin.close();
-368 -
Java 2 Core Language Little Black Book Chapter 11: Security
} catch (Exception e)
//helper class
class FileOpen
try
this.fis.read(this.fileBytes);
this.fis.close();
-369 -
Java 2 Core Language Little Black Book Chapter 11: Security
} catch (Exception e)
return this.fileBytes;
In this program, the highlighted lines on the previous page are the most important. The first line is
where the data from the file is sent to the Signature object. Remember that you have to recompute
the digest for comparison purposes. The highlighted line that calls verify actually does the
comparison operation.
-370-
Java 2 Core Language Little Black Book Chapter 12: Internationalization
In Brief
The prevalence of electronic communications has made the world seem like a smaller place. The
Internet in particular has made the world seem positively tiny. Whereas international trade was once
the province of big corporations, now even a small business can access the global marketplace. A
U.S. company might routinely import materials from Hong Kong and Bulgaria, and, in turn, it might
export electronic parts to customers on every continent. Books published in the United States might
be t ranslated into such diverse languages as Japanese, Russian, Polish, Spanish, and German.
This new international commerce often requires special care to make sure that software and Web
sites can handle non -English languages. Once a specialty, internationalization is now part of
mainstream software development. Often called I18N (because the word "internationalization" begins
with an "i," has 18 other letters, and ends with an "n"), internationalization actually encompasses
several techniques that facilitate the use of software with different languages.
Internationalization can deal only with technical issues, however, not with cultural ones. Also, it
Y
doesn't solve several common problems in user-interface design — that's up to you. What I18N can do
is to help you replace (localize) the strings you use so that your prompts, error messages, and report
FL
titles are not tied to English. I18N also provides a way for you to format dates, numbers, and currency
to conform to the user's preferences (the locale). However, I18N won't handle currency conversion;
AM
I18N does not take care of problems that aren't immediately obvious. For example, some languages
TE
are not read from left to right; some are read up and down. Even languages similar to English can
cause a problem. For example, German is superficially similar to English (at least, compared to Farsi
or Cantonese), but the German language has many extremely long words composed of other words.
This length often makes text boxes and other user-interface elements too short to contain their
messages.
I18N Strings
At the heart of Java's I18N support is Unicode. How do your programs store characters? Internally,
Java uses the Unicode format, which is a standard 16-bit character set used to represent glyphs for
nearly every known language and a number of extra symbols.
For external data (that is, data in files or other external sources), Java uses an encoding scheme
known as UTF-8. This is a particular way of storing characters in which the initial bit pattern
determines the number of bytes in the character. (Remember that a byte contains eight bits,
numbered from 0 to 7.) Having this variable bit pattern lets you store data in an efficient but versatile
manner. The UTF-8 scheme provides three types o f characters: one-byte, two-byte, and three -byte.
Here's how it works:
-371 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 12: Internationalization
§ One -byte characters — If bit number 7 of the first byte is set to 0, then the character is
made up of only one byte.
§ Two-byte characters — If the first three bits (numbers 7, 6, and 5) are set to 110
(binary), then the character consists of two bytes. In this case, the second byte must
begin with 10 (binary), which leaves 11 bits remaining to define the character.
§ Three-byte characters— If the character requires more than 11 significant bits, the
UTF-8 scheme says that Java must use three bytes to store it. In this case, the first
byte must start with 1110 (binary). The next two bytes each start with 10 (binary). This
scheme lets you store the full 16 bits.
The UTF scheme has several advantages. All pure ASCII files are already proper UTF -8 files, so you
don't have to convert any existing data. (Remember that pure ASCII characters are all less than 0x80,
so bit 7 will always be zero.) In addition, because of the bit patterns, it's easy to recognize — by looking
at the starting bits — whether a byte starts a sequence, belongs to a sequence, or is its own character.
Any byte that's part of a sequence starts with 10 (binary); any byte that does not start with 10 (binary)
either begins a sequence or is a single byte.
Thanks to Unicode, Java has no problem representing strings in practically any language or alphabet.
Unicode has characters for Cyrillic, Greek, and many other alphabets. You could create multiple
versions of your program, each having strings in a different language. Of course, it is up to you to
supply the translations.
There is a better way, however. First, extract all the display text from code, and place the text into a
repository file. When the program needs a particular string, have the program retrieve the string from
the repository. That way, you can change languages by simply replacing the repository.
For this scheme to work, you need two things. First, you need a way to store strings for later retrieval.
And second, you need a way to detect which language the user wants to use. You could handle all the
details yourself, as in the following program:
i f (args.length != 1)
"English|French");
} else
language = args[0];
-372 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
if( language.equalsIgnoreCase("English") )
message = messageInEnglish;
} else
if( language.equalsIgnoreCase("French") )
message = messageInFrench;
System.out.println(message);
//java EnglishFrench
//returns:
//
//returns:
This program uses a simple option on the command line to decide whether to display its text in
English or French. However, the obvious problem is that the text cannot change unless you recompile
the program. This is a harbinger of a nasty maintenance burden.
The better way to manage text translations is to move the text pieces from code to a repository
outside the program. The following pseudocode walks through the steps:
find textName;
-373 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
return textValue;
We can write our own helper class to perform the steps outlined by the pseudo -code. However, the
second Immediate Solution later in this chapter (see "Internationalizing Text with a MessageBundle ")
shows you how to use a class called the ResourceBundle , which takes care of the pseudo -code's
chores automatically.
The other problem with this simple approach is that it can lead to a great deal of duplication. For
example, localized versions for the United States, Canada, and the United Kingdom will all have
strings that are mostly the same but might differ in a few details, such as word spellings.
With a ResourceBundle, Java can manage a hierarchy of repositories. Java will search in the most
specific repository first (say, English, for the United Kingdom). If it can't find the requested string in
that bundle, it will search a bundle for generic English (if one exists). If that fails, Java will continue
looking in a generic bundle before giving up.
Locales
Before you can put resource bundles to use, it's important to understand locales. A locale
(represented by the java.util.Locale class) indicates a language, a country, and a dialect or variant.
For example, your user's language might be English. If you know the user's country, you can specify
American English or British English.
Great Britain uses a different currency symbol and different date formats from those used in the
United States. Besides that, some words are spelled differently ("honour" and "honor," for example).
Even words for common objects are different ("petrol" and "gasoline"; "lift" and "elevator"). To make
matters more complex, some countries have dialects, which are further subdivisions or variants of a
single language. Java's Locale class also accounts for dialects.
Beyond words, languages can be different in other seemingly innocuous, but important, ways. For
example, in Spanish, "ch" is often (depending on the country) treated as one letter when it's
alphabetized. Thai and Lao vowels have peculiar sorting rules as well. The java.text.Collation class
is sensitive to these rules. You can use this class to determine if one word is alphabetically before or
after another word (which is the essence of sorting, of course). The compare method of this class
tells you the order of two strings. You can also use other methods to set options like case sensitivity.
The documentation for this class is a wealth of information about language-sorting issues.
Most modern operating systems also support the use of locales. Your program can call the static
function java.util.Locale.getDefault to learn the default locale. You can then use member functions
of the Locale object to get the specific country and language information. If you want to change the
current locale, you can use the setDefault function.
-374 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
Immediate Solutions
The Locale object encapsulates the country and language of a location. You often need both the
country and the language to decide how to display text, currency, and dates. Usually, you'll use the
static function java.util.Locale.getDefault to obtain the system's idea of the current Locale. However,
you can also construct your own arbitrary Locale objects.
For example, the following code initializes a Locale object to rep resent the English language:
Java encodes as constants the languages and countries most often used in code. The previous line is
equivalent to this:
The previous English example is a language-specific Locale. The following is a country Locale that
includes both a location and a language:
The other language Locale constants are FRENCH, GERMAN, ITALIAN , JAPANESE, KOREAN,
CHINESE, SIMPLIFIED_CHINESE, and TRADITIONAL_CHINESE. The other country Locale
constants are FRANCE, GERMANY, ITALY, JAPAN, KOREA, CHINA, PRC, TAIWAN, UK,
CANADA, and CANADA_FRENCH.
The program in Listing 12.1 demonstrates the most important methods of the Locale object.
import java.util.*;
import java.io.*;
-375 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
int i;
boolean f;
String s;
Locale canada;
Locale.setDefault(usa);
tabloid.print(Locale.CANADA);
tabloid.print(Locale.getDefault());
//getDisplayLanguage(Locale.US);//alternate method
//getDisplayVariant(Locale.US);//alternate method
canada = (Locale)Locale.CANADA.clone();
"Locale.CANADA? ");
System.out.println( canada.equals(Locale.CANADA_FRENCH));
tabloid.print(countries, "ISOCountries");
-376 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
tabloid.print(locales, "AvailableLocales");
class LocalReport
o.println(L.getDisplayName() + ":");
o.print(L.getCountry() + "\t");
o.print(L.getISO3Country() + "\t");
o.println(L.getDisplayCountry());
o.print(L.getLanguage() + "\t");
o.print(L.getISO3Language() + "\t");
o.println(L.getDisplayLanguage());
o.print(L.toString() + "\t");
o.println(L.hashCode());
o.println();
//L.getDisplayVariant();
-377 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
//L.getVariant();
o.println("\n");
o.println();
-378 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
//returns:
//English (Canada):
//en_CA 1271
//
//en_US 1591
//
//ISOCountries: AD AE AF AG AI AL AM AN AO AQ AR AS AT AU AW AZ
//BA BB BD BE BF BG BH BI BJ BM BN BO BR BS BT BV BW BY BZ CA
//ISOLanguages: aa ab af am ar as ay az ba be bg bh bi bn bo br
//ca co cs cy da de dz el en eo es et eu fa fi fj fo fr fy ga gd
//ar_JO ar_KW ar_LB ar_LY ar_MA ar_OM ar_QA ar_SA ar_SD ar_SY
The MessageBundle class takes care of finding a string in an appropriate language. The scheme is
simple— you place your translations into files that have the same name except for the addition of
country and language identifiers.
Here are the steps you'll need to follow to use the MessageBundle:
-379 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
4. YesMessage = Yes
5. Save the file using a base name (for example, "captions") and an extension
of .properties.
6. You can create more files using the same base name, but with a particular language
and, optionally, country code (for example, captions_fr_FR.properties or
captions_en.properties). These files have the same format but provide strings in
different languages.
//English
YesMessage = Yes
NoMessage = No
//French
YesMessage = Oui
NoMessage = Non
ThankYouMessage = Merci
The codes are defined by the ISO (International Organization for Standardization, the most
authoritative international-standards body). You can find a complete list of language codes at
http://www1.ics.uci.edu/pub/ietf/http/related/iso639.txt and the list of country codes at
http://www.userpage.chemie.fu-berlin.de/diverse/doc/ISO/3166.html. The code for English is e n, and
the code for the United States is US. You can find all the codes supported by Java by looking in the
Locale class source.
The first file, captions.properties, contains the default key-value pairs. MessageBundle starts looking
at the mos t specific file that matches the requested locale. If the string doesn't exist in this bundle, the
class continues searching in the less specific bundles. The program in Listing 12.2 demonstrates how
to use the ResourceBundle to get a string in one of several languages. The static
ResourceBundle.getBundle accepts the base name of the file ("captions") and a locale and returns
a Resource Bundle object. After making this call, the program simply calls getString to retrieve the
correct string by its key.
-380 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
import java.util.*;
String language;
String country;
if (args.length != 2) {
Locale currentLocale;
ResourceBundle messages;
messages = ResourceBundle.getBundle("Captions",
currentLocale);
-381 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 12: Internationalization
messages.getString("YesMessage") + "\"";
messages.getString("NoMessage") + "\"";
messages.getString("ThankYouMessage") + "\"";
System.out.println(YesMessage);
System.out.println(NoMessage);
System.out.println(ThankYouMessage);
//java ResourceBundleTest fr FR
//returns:
The ListResourceBundle serves the same function as the ResourceBundle . The differences
between the two classes lie in where the data is stored and which data types are allowed. Because
ResourceBundle uses text files, it can handle only strings for both the keys and the values. Of
course, you can add sophistication by extending it and internally converting text into numbers and
dates in addition to converting text to strings. This is somewhat clumsy, but it is possible.
The ListResourceBundle uses class files instead of text files. Of course, this means that to update a
ListResourceBundle, you have to compile Java files to create the class files. The class files are
small, however, and are not directly related to the program's operation, so distributing them isn't any
harder than distributing new text. For the small price of a compile, you gain the ability to store any
object type— including strings in the bundle.
-382 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
Listing 12.3 shows an example ListResourceBundle. Notice that Listing 12.3 extends
ListResourceBundle and simply returns an array of Object arrays. This array contains the keys and
values contained in the bundle.
import java.util.*;
ListResourceBundle
return contents;
{ "Habitat", "Australia" },
{ "Method", "touch" },
};
This example doesn't use languages; instead, it classifies poisonous animals. However, the same
principle applies to classifying languages and countries by using the ISO codes; the
ListResourceBundle doesn't care what strings you use. For this example, there are two subdivisions
-383 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
of the PoisonousAnimal category. Notice that the first description (venomous) appended to the
base name is lowercase. Also, the second description (JELLYFISH) is uppercase. You'll get an error
if you don't follow this convention.
Listing 12.4 shows how you can use the ListResourceBundle. Notice that some of the data in th e
bundle is not a string. In particular, Size is a Double, and Potency is an Integer object.
import java.util.*;
Locale[] spookyVermin = {
new Locale("venomous","SNAKE"),
new Locale("poison","FROG"),
new Locale("venomous","JELLYFISH")
};
spookyVermin[i]);
spookyReport(spookyVermin[i]);
System.out.println();
-384 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
ResourceBundle animal =
ResourceBundle.getBundle("PoisonousAnimal",
currentLocale);
//returns:
//
-385 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
//
Numbers and currency are two types of data that need to be localized for international applications.
The program in Listing 12.5 demonstrates how to use Java's formatting objects. Java uses formatting
appropriate to the current locale or to a locale you provide, if you wish.
import java.util.*;
import java.text.*;
NumberFormat prettyNumber;
-386 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
String s;
s = prettyNumber.format(mercuryRadius);
s = prettyNumber.format(mercuryMass);
s = prettyNumber.format(venusRadius);
s = prettyNumber.format(venusMass);
s = prettyNumber.format(earthRadius);
s = prettyNumber.format(earthMass);
System.out.println();
NumberFormat money;
-387 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
String s;
money = NumberFormat.getCurrencyInstance(L);
s = money.format(debt);
NumberFormat average;
String s;
average = NumberFormat.getPercentInstance(L);
s = average.format(battingAverage);
-388 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
System.out.println();
System.out.println(locales[i].getDisplayName());
showAstronomy(locales[i]);
showDebt(locales[i]);
showBattingAverage(locales[i]);
//returns:
//
//
//Albanian (Albania)
//
//
//
//Chinese (Taiwan)
-389 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
//
The highlighted lines on the previous page show where the formatting takes place. Listing 12.5 uses
the Locale.getAvailableLocales method to get all of the locales and then loops through each one,
showing you the differences in formatting.
Formatting Dates
Dates are another data type that Java has already internationalized for you. The program in Listing
12.6 demonstrates how to display the five date styles in all the languages supported by Java.
import java.util.*;
import java.text.*;
Date today;
String s;
DateFormat d;
d = DateFormat.getDateInstance(DateFormat.DEFAULT,L);
s = d.format(today);
System.out.printl n(s);
-390 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
d = DateFormat.getDateInstance(DateFormat.SHORT,L);
s = d.format(today);
System.out.println(s);
d = DateFormat.getDateInstance(DateFormat.MEDIUM,L);
s = d.format(today);
System.out.println(s);
d = DateFormat.getDateInstance(DateFormat.LONG,L);
s = d.format(today);
System.out.println(s);
d = DateFormat.getDateInstance(DateFormat.FULL,L);
s = d.format(today);
System.out.println(s); Y
FL
}
AM
System.out.println();
System.out.println(locales[i].getDisplayName());
showDates(locales[i]);
-391 -
Team-Fly®
Java 2 Core Language Little Black Book Chapter 12: Internationalization
//returns:
Dutch
//11 -okt-0 1
//11 -10-01
//11 -okt-0 1
//
//Portuguese (Brazil)
//11/10/2001
//11/10/01
//11/10/2001
//
//Swedish (Sweden)
//2001-okt-1 1
//2001-10 -11
//2001-okt-1 1
-392 -
Java 2 Core Language Little Black Book Chapter 12: Internationalization
Comparing Characters
When handling strings, be sure to use the Character class to test a character for set membership. For
example, to test a character to see if it is a letter, you might be tempted to write:
if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')) . . .
This is incorrect for many languages, however. A better test is the following:
if (Character.isLetter(letterCandidate)) . . .
You can also use the java.text.Collation object to compare strings to determine their lexical ordering.
This class also uses locale rules.
-393 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
Overview
In this book, we've used the Sun Microsystems development tools. After all, these tools represent the
base level of Java, which is available for practically all platforms. Also, using Sun's tools allowed us to
focus on the Java code and not on the various quirks and idiosyncrasies of tools. If you start writing a
substantial amount of Java code, however, you'll probably want to use a different tool (although it's
possible to write a lot of code with nothing more than the Emacs text editor and the basic Sun tools).
Sun provides a graphical-user-interface tool called Forte. This product has a community edition you
can download for free. Be warned: This program is written in Java, so you need a fast machine with
plenty of memory in order to run it. (How fast and with how much memory depends on your operating
system and which version of Forte you are running.) You can download Forte from Sun's Web site at
http://www.java.sun.com .
Regardless of which tool you choose, you'll probably continue to use the same Java Virtual Machine
(JVM) that you've always used. Every tool has the same job: converting source code to class files.
The tools offer a graphical work environment, project management features, and enhanced
debugging; in addition, many offer automated wizards that can produce some code automatically.
This appendix concentrates on the tools that Sun bundles with the Software Development Kit (SDK),
plus a few other tools w e think you should try for your Java development.
Note The popular integrated development environments (IDEs) either run Java's
native compiler behind the scenes or come with the vendor's own compiler.
Either way, the IDEs take care of many compiling chores for you, but the
fundamental process is still the same behind the scenes.
For the purposes of this appendix, we will group development tools into three categories. The first
group is the toolset that comes with the basic SDK. The majority of this app endix covers these tools.
The second group consists of text editors that support Java syntax. They highlight keywords,
automatically indent code, and display line numbers. Some of these editors also compile and execute
code and provide rudimentary project management features. The third group consists of the
enterprise IDE (integrated development environment). This IDE provides rapid J2EE application
development, Java-to-database wizards, XML tools, and support for including JavaBeans. These
tools often have version-control features that support team development.
Forte, VisualAge, Visual Café, and JBuilder are certainly the biggest names in IDEs, but hundreds of
Java authoring tools are available. Even more tools exist that have nothing to do with authoring (for
example, profiling tools). The top list of tools to keep your eye on is maintained by Sun at
http://www.i ndustry.java.sun.com/solutions/products/by_type/0,2359,all-28-0,00.html. An honorable
-394 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
One thing you have to watch for: Many vendors' tools add libraries that are vendor-specific to perform
certain tasks. (This is especially true if you use wizards o r other tools to generate code automatically.)
Then you have to remember to distribute these libraries with your application. Of the four top guns,
only Forte doesn't include renegade classes. Another thing that is high-handed about IDEs is that
many of th em force you to use a certain coding convention or style.
One of the best features of most IDEs (and many code editors) is syntax coloring. By coloring
keywords and common structures, an editor can help you browse your code more quickly.
Another handy fea ture in many IDEs is code completion. For example, JBuilder lets you insert code
from an expanded list of user-defined templates. If you type "forb", highlight it, and press Ctrl+J,
JBuilder replaces forb with a complete for block and places the cursor at the initiation statement point.
Borland ships all the fundamental constructs and allows you to add your own. As you type, the editor
starts guessing what you want. Another keyboard shortcut displays a pop-up window that provides a
list of keywords, includi ng your own classes and methods, to complete your expression. Most IDEs
have a similar feature.
Code Editors
Many people prefer code editors to full IDEs. Although IDEs include everything but the kitchen sink,
code editors are light and fast. Dozens of editors are similar in terms of features and reliability. A few
expensive ones are very good, such as SlickEdit ( http://www.slickedit.com), but the high price for a
text editor makes us pause because a user can get 85 percent of the same functionality from free or
inexpensive editors. Our favorites? We usually use one of these three:
§ UltraEdit— http://www.idmcomp.com/products/index.html
§ NoteTab— http://www.notetab.com
§ TextPad— http://www.textpad.com
Other editors are better, but they are more difficult to learn. For example, Emacs isn't just a text editor;
it is a way of life, and probably not useful to the casual user. (People who know Emacs use it for
everything— text editing, document preparation, mail and news, compiling programs, browsing the
Web, transferring files over the network, and more. Unfortunately, however, it takes a big investment
in time to get familiar with this large, but powerful, program.)
The compiler is what translates your source code into class files. You compile at the command prompt
with the following command:
javac myProgram.java
-395 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
This command will produce a file named myProgram.class. This class file is what runs on the JVM.
You can supply several options for the javac compiler. Table A.1 lists the most common options.
Option Description
-classpath classpath Specifies the location for import classes (overrides the
CLASSPATH environment variable).
-d directory Specifies the destination directory for class files. (This option
will append package name directories, so -d c:\myclasses
for com.mypackage.MyClass produces
c:\myclasses\com \mypackage\ MyClass.class.)
-deprecation
Prints each deprecated member or class.
-encoding encoding
Sets the source file's encoding method.
-g:none
Turns off debugging information.
-g:{keyword list} Provides specific debugging information for source, lines, and
vars.
-help
Prints most of the information in this table.
-source release
When release is set to 1.4, the compiler accepts assertions.
-396 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
Option Description
-verbose
Produces additional output about each class loaded and each
source file compiled.
-Xstdout filename
Places compiler mes sages in the named file.
One nice capability of the javac compiler is that you can place the list of options and source-file paths
in files instead of retyping them each time. This is convenient when you are compiling more than one
file or when you simply want to specify several options. You can create one file named args.txt and
place the following in it:
-g
-deprecation
-verbose
Then create another file called classes.txt, and place the list of source files in it (use relative or
absolute paths):
test1 \source\Splitter.java
test1 \source\flip.java
Development Tools
You will see something like this result in the command window:
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
(java/lang/Object.class)]
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
-397 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
(java/lang/String.class)]
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
(java/lang/Exception.class)]
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
(java/util/Random.class)]
[checking Splitter]
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
(java/lang/Throwable.class)]
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
(java/util/regex/Pattern.class)]
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
(java/util/regex/Matcher.class)]
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
(java/lang/CharSequence.class)]
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
(java/io/Serializable.class)]
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
(java/lang/Comparable.class)]
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
(java/lang/System.class)]
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
(java/io/PrintStream.class)]
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
(java/io/FilterOutputStream.class)]
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
(java/io/OutputStream.class)]
[wrote test1\source\classes\Splitter.class]
[checking flip]
[loading c:\dev\java\jdk1.4\jre\lib\rt.jar
(java/lang/StringBuffer.class)]
[wrote test1\source\classes\flip.class]
[total 591ms]
-398 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
java myProgram
The myProgram file is a class file, not a source file. The full file name is myProgram.class. Table A.2
lists the options for the java launcher.
Option Description
-classpath classpath (or just –c p) Specifies the location for import classes (overrides the
CLASSPATH environment variable).
-enableassertions[:<package
Enables assertions. Assertions are disabled by default.
name> "..." | :<class name> ]
-disableassertions[:<package
Disables assertions. This setting is the default.
name> "..." | :<class> ; ]
-showversion
Displays version information.
There are also extended options that begin with — X. These represent options that are not typically
standard among different compilers. The — Xprof option is especially helpful when you are analyzing
performance. For example, the — Xprof option was used to generate the following profile report:
-399 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
86.1% 0 + 31 java.io.FileInputStream.open
2.8% 0 + 1 java.lang.Exception.<init>
2.8% 1 + 0 java.util.Locale.getDefault
2.8% 0 + 1 java.lang.StringBuffer.expandCapacity
2.8% 0 + 1 sun.misc.URLClassPath$JarLoader.getJarFile
2.8% 0 + 1 java.io.Win32FileSystem.canonicalize
The javadoc program extracts special comments from your Java source code and uses these
comments to build HTML documentation. These special comments start with /** (which the Java
compiler treats as an ordinary comment). Consider the following fictitious source file as an example:
/*
*/
/**
* <p>
* @see truck.sales
* @since JDK1.4
*/
-400 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
/**
* detail customer.
*/
public TruckSale() {
super();
/**
Y
* customer. The customer is not initialized, and may
FL
* subsequently be initialized by a call to
AM
* {@link #initCause}.
*/
super(customer);
/**
* automatically incorporated in
-401 -
Team-Fly®
Java 2 Core Language Little Black Book Appendix A: Development Tools
* retrieval by the
* @since 1.4
*/
super(customer, occasion);
/**
* occasion.toString())</tt> (which
* <tt>occasion</tt>).
* retrieval by the
* @since 1.4
*/
super(occasion);
/**
-402 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
* <p>
* SecurityException.
* <p>
* <code>checkPropertyAccess</code> method
* property.
* <code>null</code>.
* is empty.
* @see #setProperty
* @see java.lang.SecurityException
* @see java.lang.Sale#getProperties()
*/
if (key == null) {
return props.getProperty(key);
-403 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
The code is not valid, but the comments and javadoc tags are. When you run javadoc on a source file
like the one just shown, you get several new files, including overview-tree.html, index-all.html,
deprecated-list.html, allclasses-frame.html, index.html, packages.html, TruckSale.html,
package-list.html, help-doc.html, and stylesheet.css. These .html, Web pages have a nice layout, and
all the links work. These documentation pages are the same as the ones generated for the Java
libraries themselves.
The javadoc program looks for certain tags of the form @tagname . Table A.3 shows the most
common tags.
parameter
-404 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
Tip Remember that javadoc generates HTML. You can enclose HTML formatting in
the comments. Also, you should encode the HTML special characters, such as
the less-than (<), greater -than (>), and ampersand & symbols. For example, to
write a less-than sign, you should write & to prevent the Web browser from
treating your text as an HTML tag.
The jar tool combines multiple files into a single JAR archive file. Archives are files that contain other
files. These files are compressed in Zip archive format. Unlike ordinary Zip files, however, the JAR
files contain extra information understood by the JVM.
A JAR archive allows you to distribute a single file that contains all the cl asses and other files required
by your application. In addition to the class files, the JAR file can contain a manifest that specifies
additional information for the JVM. The most common use for a manifest is to specify a class in the
JAR file that contains a main method. Table A.4 lists the options for the jar command.
Option Description
c
Creates a new or empty archive.
-405 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
Option Description
t
Lists the table of contents.
x file
Extracts all files or just the named files.
v
Generates verbose output.
u
Updates an existing JAR file by adding files or changing the
manifest.
The jar tool adds all the files in a particular directory to an archive (overwri ting contents if the archive
already exists). For example, the dir command lists the following files in a given directory:
-406 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
added manifest
Now the truckSale.jar file contains all the files in that directory in a compressed format.
If you want to get a snapshot of a class's members and methods, the javap tool is a quick way to get it.
Suppose you have the following class:
import java.io.*;
import java.net.*;
-407 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
pageBuffer.append(html);
page.close();
html = pageBuffer.toString();
System.out.println(html);
System.out.println(date);
System.out.println(time);
}
Running the command javap WhatTimeIsIT will yield this:
-408 -
Java 2 Core Language Little Black Book Appendix A: Development Tools
public WhatTimeIsIT();
throws java.lang.Exception;
}
This code works for any class file— even if you don't have the source code. The javap program can
also dump out the bytecodes for a class, but this is difficult to interpret (see Appendix C).
The Sun JDK provides jdb, the Java debugger. This debugger is rather primitive and works only with
the command line. Most programmers don't like jdb and with good reason. Fortunately, Sun provides
hooks for debugging programs, and there are many others from which to choose.
If you use a large-scale IDE, it probably supports debugging right in its own environment. If you just
use the command-line tools, you might want to look at the JSwat debugger at
http://www.bluemarsh.com/java/jswat/.
-409 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Appendix B: References
Many Web sites discuss Java. The following is a collection of our favorites. We wanted to do
more than just list a bunch of URLs, so we grouped them to make it easier to find sites of interest.
Of course, links come and go, so if you find a broken link you'll just have to keep looking.
Topic Link
http://www.java.sun.com/docs/books/tutorial/applet/index.html
Applets
Classes http://www.java.sun.com/docs/books/tutorial/essential/index.html
http://www.java.sun.com/docs/books/tutorial/essential/exceptions
Exceptions
/index.html
http://www.java.sun.com/docs/books/tutorial/essential/threads/ind
Threads
ex.html
I/O http://www.java.sun.com/docs/books/tutorial/essential/io/index.ht
ml
Networking http://www.java.sun.com/docs/books/tutorial/networking/index.ht
ml
http://www.java.sun.com/docs/books/tutorial/uiswing/index.html
Swing
http://www.java.sun.com/docs/books/tutorial/collections/index.ht
Collections
ml
Internationalization http://www.java.sun.com/docs/books/tutorial/i18n/index.html
-410 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Topic Link
http://www.java.sun.com/docs/books/tutorial/2d/index.html
2D Graphics
http://www.java.sun.com/docs/books/tutorial/sound/index.html
Sound
JavaBeans http://www.java.sun.com/docs/books/tutorial/javabeans/index.htm
l
http://www.java.sun.com/docs/books/tutorial/jdbc/index.html
JDBC
http://www.java.sun.com/docs/books/tutorial/rmi/index.html
RMI
IDL http://www.java.sun.com/docs/books/tutorial/idl/index.html
Y
FL
http://www.java.sun.com/docs/books/tutorial/servlets/index.html
Ser vlets
AM
Security http://www.java.sun.com/docs/books/tutorial/security1.2/index.ht
ml
TE
JAR http://www.java.sun.com/docs/books/tutorial/jar/index.html
http://www.java.sun.com/docs/books/tutorial/ext/index.html
Extensions
Interface
http://www.java.sun.com/docs/books/tutorial/reflect/index.html
Reflection
Security http://www.java.sun.com/docs/books/tutorial/security1.1/api/index
.html
Comprehensive http://www.java.sun.com/docs/books/tutorial/together/index.html
-411 -
Team-Fly®
Java 2 Core Language Little Black Book Appendix B: R eferences
Topic Link
http://www.java.sun.com/docs/books/tutorial/getStarted/QandE/questio
Beginning
ns.html
http://www.java.sun.com/docs/books/tutorial/java/concepts/QandE/que
Basic OOP
stions.html
Variables http://www.java.sun.com/docs/books/tutorial/java/nutsandbolts/QandE/
questions_variables.html
Operators http://www.java.sun.com/docs/books/tutorial/java/nutsandbolts/QandE/
questions_operators.html
http://www.java.sun.com/docs/books/tutorial/java/data/QandE/character
Strings
s-questions.html
http://www.java.sun.com/docs/books/tutorial/java/data/QandE/numbers
Numbers
-questions.html
Arrays http://www.java.sun.com/docs/books/tutorial/java/data/QandE/arrays -q
uestions.html
http://www.java.sun.com/docs/books/tutorial/java/javaOO/QandE/creati
Creating Classes
ng-questions.html
http://www.java.sun.com/docs/books/tutorial/java/javaOO/QandE/inherit
Managing Inheritance
-questions.html
http://www.java.sun.com/docs/books/tutorial/java/javaOO/QandE/neste
Nested Classes
d-questions.html
Interfaces http://www.java.sun.com/docs/books/tutorial/java/interpack/QandE/inter
faces -questions.html
http://www.java.sun.com/docs/books/tutorial/java/interpack/QandE/pac
Packages
kages-questions.html
-412 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Topic Link
http://www.java.sun.com/docs/books/tutorial/essential/exceptions/Qand
Exceptions
E/questions.html
http://www.java.sun.com/docs/books/tutorial/essential/threads/QandE/q
Threads
uestions.html
J2EE http://www.java.sun.com/j2ee/tutorial/index.html
http://www.java.sun.com/products/java-media/3D/collateral
3D API
XML http://www.java.sun.com/xml/tutorial_intro.html
http://www.java.sun.com/products/jndi/tutorial
JNDI (Java Naming and
Directory Interface)
Connection)
http://www.java.sun.com/products/jfc/tsc
Swing
Topic Link
http://www.java.sun.com/developer/technicalArticles/ALT/cachingservices/index.
Caching
html
http://www.java.sun.com/developer/technicalArticles/Collections/Using/index.html
Collections
-413 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Topic Link
Entry akery
http://www.java.sun.com/developer/technicalArticles/ALT/Reflection/index.html
Java Reflection
http://www.java.sun.com/developer/technicalArticles/Media/Simple2D/index.html
Color
Localization http://www.developer.java.sun.com/developer/technicalArticles/Intl/IntlIntro/index.
html
http://www.java.sun.com/developer/technicalArticles/jbeans/XMLJavaBeans3/ind
XML JavaBeans
Integration ex.html
http://www.developer.java.sun.com/developer/technicalArticles/Programming/stri
Tokenization
ngtokenizer
http://www.developer.java.sun.com/developer/technicalArticles/Programming/em
Embedding Java
into Your Native bedjava/index.html
Apps
http://www.developer.java.sun.com/developer/technicalArticles/Programming/Jav
Javadoc
adoc
Parser index.html
http://www.developer.java.sun.com/developer/technicalArticles/Printing/Java2DP
2D Printing
rinting/index.html
Serialization http://www.developer.java.sun.com/developer/technicalArticles/RMI/ObjectPersis
t/index.html
Serialization and
-414 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Topic Link
RMI
http://www.developer.java.sun.com/developer/technicalArticles/Servlets/JavaSer
Servlet
verTech1/index.html
http://www.developer.java.sun.com/developer/onlineTraining/Security/Fundament
Security
als/abstract.html
Stream OSC/index.html
http://www.developer.java.sun.com/developer/technicalArticles/ThirdParty/WebCr
Writing a Web
Crawler awler /index.html
http://www.developer.java.sun.com/developer/technicalArticles/xml/api/index.html
XML and
Databases
XML http://www.developer.java.sun.com/developer/technicalArticles/xml/mapping
http://www.developer.java.sun.com/developer/technicalArticles/xml/metadata
XML and DB and
Cryptography
Bug
Topic Link
http://www.java.sun.com/jdc/Quizzes/BegJavaObjects
Objects
-415 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Topic Link
JavaMail http://www.java.sun.com/jdc/Quizzes/JavaMail
http://www.developer.java.sun.com/developer/Quizzes/advancedprogramming
Advanced
Programmin
g
Basic http://www.developer.java.sun.com/developer/Quizzes/langessentials
Language
Certification http://www.developer.java.sun.com/developer/Quizzes/certification.html
http://www.developer.java.sun.com/developer/Quizzes/gui.html
Graphical
User
Interface
(GUI)
http://www.developer.java.sun.com/developer/Quizzes/javaserverpages.html
JavaServer
Pages
Technology
http://www.developer.java.sun.com/developer/Quizzes/jdbctechnology.html
JDBC
Networking http://www.developer.java.sun.com/developer/Quizzes/networking.html
http://www.developer.java.sun.com/developer/Quizzes/performancedebugging.html
Performance
and
Debugging
http://www.developer.java.sun.com/developer/Quizzes/rmi.html
Remote
Method
Invocation
(RMI)
-416 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Topic Link
http://www.developer.java.sun.com/developer/Quizzes/security.html
Security
http://www.developer.java.sun.com/developer/Quizzes/wirelesstechnologies.html
Wireless
Technology
http://www.developer.java.sun.com/developer/Quizzes/ejbtechnology.html
Enterpris e
JavaBeans
Title Link
http://www.suned.sun.com/US/certification/java/java_progj2se.html
Sun Certified
Programmer for 2
Platform
http://www.sun ed.sun.com/US/certification/java/java_devj2se.html
Sun Certified
Developer for
Java 2 Platform
http://www.suned.sun.com/US/certification/java/java_archj2ee.html
Sun Certified
Enterprise
Architect for Java
2 Platform,
Enterprise Edition
Technology
http://www.suned.sun.com/US/certification/java/java_web.html
Sun Certified
Web Component
Developer for the
J2EE Platform
-417 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Java
Technology
Core Learning
Path
Title Link
Java http://www.suned.sun.com/US/catalog/courses/SL-110.html
Programming
Language for
Non-Programm
ers (SL-110)
http://www.suned.sun.com/US/catalog/courses/SL-210.html
Migrating to
Object-Oriented
Programming
with Java
Technology
(SL-210)
http://www.suned.sun.com/US/catalog/courses/SL-265.html
Java
Technology for
Structured
Programmers
(SL-265)
Java http://www.suned.sun.com/US/catalog/courses/SL-275.html
Programming
Language
(SL-275)
http://www.suned.sun.com/US/catalog/courses/OO-226.html
Object-Oriented
Analysis and
Design for Java
Technology
(UML)
(OO -226)
http://www.suned.sun.com/US/catalog/courses/SL-285.html
Java
-418 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Java
Technology
Core Learning
Path
Title Link
Programming
Language
Workshop
(SL-285)
Enterprise
Developer
Learning
Path
Title Link
Java http://www.suned.sun.com/US/catalog/courses/SL-285.html
Programmi
ng
Language
Workshop
(SL-285)
Developing http://www.suned.sun.com/US/catalog/courses/FJ-310.html
J2EE
Compliant
Enterprise
Java
Application
s (FJ-310)
Developing http://www.suned.sun.com/US/catalog/courses/FJ-311.html
J2EE
Compliant
Application
s (iPlanet)
-419 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Enterprise
Developer
Learning
Path
Title Link
(FJ -311)
Web http://www.suned.sun.com/US/catalog/courses/SL-314.html
Componen
t
Developme
nt Using
Java
Technolog
y (SL-314)
http://www.suned.sun.com/US/catalog/courses/SL-330.html
Database
Application
Programmi
ng with
Java
Technolog
y (SL-330)
http://www.suned.sun.com/US/catalog/courses/SL-351.html
Enterprise
JavaBeans
Programmi
ng
(SL-351)
Enterprise
Architect
Learning Path
Title Link
Java http://www.suned.sun.com/US/catalog/courses/SL-110.html
-420 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Enterprise
Architect
Learning Path
Title Link
Programming
Language for
Non-Programm
ers (SL-110)
http://www.suned.sun.com/US/catalog/courses/OO-226.html
Object-Oriented
Analysis and
Design for Java
Technology
(UML)
(OO -226)
Y
FL
http://www.suned.sun.com/US/catalog/courses/SEM-SL-345.html
Java 2,
Enterprise
AM
Edition:
Technology
Overview
TE
Seminar
(SEM-SL-345)
http://www.suned.sun.com/US/catalog/courses/FJ -310.html
Developing
J2EE
Compliant
Enterprise Java
Applications
(FJ -310)
http://www.suned.sun.com/US/catalog/courses/FJ -311.html
Developing
J2EE
Compliant
Applications
(iPlanet)
(FJ -311)
-421 -
Team-Fly®
Java 2 Core Language Little Black Book Appendix B: R eferences
Enterprise
Architect
Learning Path
Title Link
Java 2 http://www.suned.sun.com/US/catalog/courses/SL-500.html
Enterprise
Edition Patterns
(SL-500)
Architecting http://www.suned.sun.com/US/catalog/courses/SL-425.html
and Designing
J2EE
Applications
(SL-425)
http://www.suned.sun.com/US/catalog/courses/SEM-SL-425.html
Java 2
Enterprise
Edition:
Application
Programming
Model
(SEM-SL-425)
Fast
Track
Courses
Tit le Link
http://www.suned.sun.com/US/catalog/courses/JF-341.html
Java
Technolog
y Fast
Track
Program I
(inclusive)
(JF-341)
-422 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Fast
Track
Courses
Tit le Link
Java http://www.suned.sun.com/US/catalog/courses/JB-341.html
Technolog
y Fast
Track
Program I
(non-i nclus
ive)
(JB-341)
http://www.suned.sun.com/US/catalog/courses/JF-441.html
Java
Technolog
y Fast
Track
Program II
(inclusive)
(JF-441)
http://www.suned.sun.com/US/catalog/courses/JB-441.html
Java
Technolog
y Fast
Track
Program II
(non-inclus
ive)
(JB-441)
Other
Courses
Title Link
http://www.suned.sun.com/US/catalog/courses/DTJ-360.html
Developing
J2ME Mobile
-423 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Other
Courses
Title Link
Applications
with CLDC
and the MID
Profile
(DTJ-360)
Introduction to http://www.suned.sun.com/US/catalog/courses/SI-330.html
CORBA using
C++ and Java
Programming
(SI-330)
http://www.suned.sun.com/US/catalog/courses/SL-291.html
JavaBeans
Component
Development
(SL-291)
Distributed http://www.suned.sun.com/US/catalog/courses/SL-301.html
Programming
with Java
Technology
(SL-301)
http://www.suned.sun.com/US/catalog/courses/SL-303A.html
Implementing
Java Security
(SL-303A)
http://www.suned.sun.com/US/catalog/courses/SL-310.html
Beyond CGI:
Developing
Java Servlets
(SL-310)
http://www.suned.sun.com/US/catalog/courses/SL-315.html
Java Server
Pages
-424 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Other
Courses
Title Link
(SL-315)
GUI http://www.suned.sun.com/US/catalog/courses/SL-320.html
Construction
with Java
Foundation
Classes
(SL-320)
http://www.suned.sun.com/US/catalog/courses/SL-370.html
Programming
Distributed
Services with
Jini
Technology
(SL-370)
http://www.suned.sun.com/US/catalog/courses/SL-385.html
Managing
XML with the
Java Platform
(SL-385)
Programming http://www.suned.sun.com/US/catalog/courses/SL-450.html
D istributed
Management
Systems with
Jiro
Technology
(SL-450)
Title Link
-425 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Title Link
Programming
with Java
Technology,
Java 2 Platform
(JT-SL301)
http://www.suned.sun.com/US/catalog/courses/JTL-SL110.html
Java
Programming
for
Non-Programm
ers Library
(Java 2
Platform)
(JTL-SL110)
Java http://www.suned.sun.com/US/catalog/courses/JTL-SL110-05.html
Programming
for
Non-Programm
ers Library
(Java 2
Platform)— 5-U
ser
(JTL-SL110-05)
http://www.suned.sun.com/US/catalog/courses/JTL-SL275-2.html
Java
Programming
Language
Library (Java 2
Platform)
(JTL-SL275-2)
http://www.suned.sun.com/US/catalog/courses/JTL-SL275-2-05.html
Java
Programming
Language
Library (Java 2
Platform)— 5-U
ser
-426 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Title Link
(JTL-SL275-2-0
5)
http://www.suned.sun.com/US/catalog/courses/JTL-SL301.html
Distributed
Programming
Using Java JDK
1.1
Library— 1-User
(JTL-SL301)
http://www.suned.sun.com/US/catalog/courses/JTL-SL301-05.html
Distributed
Programming
Using Java JDK
1.1
Library— 5-User
(JTL-SL301-05)
http://www.suned.sun.com/US/catalog/courses/JTL-SL303.html
Implementing
Java Security
for JDK 1.2
Library— 1-User
(JTL-SL303)
Implementing http://www.suned.sun.com/US/catalog/courses/JTL-SL303-05.html
Java Security
for JDK 1.2
Library— 5-User
(JTL-SL303-05)
Core Learning
Suite
Title Link
http://www.suned.sun.com/us/catalog/courses/WJ-1101 -90.html
Introduction to
-427 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Core Learning
Suite
Title Link
the Java
Programming
Language
http://www.suned.sun.com/us/catalog/courses/WJ-1102 -90.html
Getting Started
with the Java
Programming
Language
http://www.suned.sun.com/us/catalog/courses/WJ-1103 -90.html
Basics of the
Java
Programming
Language
Functionality
and the Java
Programming
Language
http://www.suned.sun.com/us/catalog/courses/WJ-1105 -90.html
Inheritance and
Advanced Java
Technology
Concepts
Migrating to http://www.suned.sun.com/us/catalog/courses/WP-1201-90.html
Object-Oriented
Programming
Implementing http://www.suned.sun.com/us/catalog/courses/WP-1202-90.html
Object-Oriented
Programming
with Java
Technology
-428 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Core Learning
Suite
Title Link
http://www.suned.sun.com/us/catalog/courses/WP-1203-90.html
Advanced
Object-Oriented
Programming
http://www.suned.sun.com/us/catalog/courses/WJ-2501 -90.html
Getting Started
with the Java
Programming
Language
http://www.suned.sun.com/us/catalog/courses/WJ-2502 -90.html
Java
Programming
Lan guage
Basics
and Exceptions
in the Java 2
Platform
Streams, Files,
and Threads
Technology
Networking,
Distributed
Computing, and
-429 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Core Learning
Suite
Title Link
Foundation
Classes
the Java
Programming
Language
http://www.suned.sun.com/us/catalog/courses/WJ-2602 -90.html
Base Class
Design
Class Design
http://www.suned.sun.com/us/catalog/courses/WJ-2604 -90.html
Graphical User
Interface
Design
http://www.suned.sun.com/us/catalog/courses/WJ-2605 -90.html
Stream I/O,
Networking,
and Threads
http://www.suned.sun.com/us/catalog/courses/WJ-6701 -90.html
Programming
with the Java
3D API: A
Technical
Overview
Distributed
Technolog
ies
Learning
Suite
-430 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Title Link
Java
Platform
Technologi
es: JDBC,
RMI, IDL
Java Y
http://www.suned.sun.com/us/catalog/courses/WJ-3203 -90.html
FL
Platform
Server
AM
Technologi
es: JNDI,
JMS, JTS
TE
Technology
Overview
Started
With Jiro
Technology
Enterprise
Developer
Learning
Suite
Title Link
-4 31 -
Team-Fly®
Java 2 Core Language Little Black Book Appendix B: R eferences
http://www.suned.sun.com/us/catalog/courses/WJ-3301-90.html
Enterprise
JavaBeans
Overview
http://www.suned.sun.com/us/catalog/courses/WJ-3050-90.html
Understanding
Servlets
http://www.suned.sun.com/us/catalog/courses/WJ-3051-90.html
Programming
Java-Based
Servlets
Consumer
Devices
Title Link
An http://www.suned.sun.com/us/catalog/courses/WJ-4500-90.html
Introductio
n to J2ME
and the
MID Profile
http://www.suned.sun.com/us/catalog/courses/WJ-4601-90.html
What Is
Java Card
Technolog
y?
Technolog
y Bundle
What Is http://www.suned.sun.com/us/catalog/courses/WJ-5501-90.html
Jini
Technolog
y?
Getting http://www.suned.sun.com/us/catalog/courses/WJ-5502-90.html
-432 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Consumer
Devices
Title Link
Started
with Jini
Technolog
y
Table B.9: Quick links to Java SDK features.
CORE Features
Title Link
Version http://www.java.sun.com/j2se/1.4/compatibility.html
Compatibility with
Previous Releases
http://www.java.sun.com/j2se/1.4/index.html
Java 2 SDK
Download Page
http://www.java.sun.com/j2se/1.4/docs/api/index.html
Java 2 Platform
API Specification
Language
Specification
Machine
Specification
-433 -
Java 2 Core Language Little Black Book Appendix B: R eferences
CORE Features
Title Link
Signed Applets
http://www.java.sun.com/j2se/1.4/docs/guide/collections/index.html
Collections
Framework
JavaBeans http://www.java.sun.com/j2se/1.4/docs/guide/beans/index.html
Component API
Internationalization http://www.java.sun.com/j2se/1.4/docs/guide/intl/index.html
http://www.java.sun.com/j2se/1.4/docs/guide/nio/index.html
New I/O
http://www.java.sun.com/j2se/1.4/docs/guide/io/index.html
I/O
XML http://www.java.sun.com/j2se/1.4/docs/guide/xml/index.html
http://www.java.sun.com/j2se/1.4/docs/guide/net/index.html
Networking
http://www.java.sun.com/j2se/1.4/docs/guide/lang/index.html
Language and
Utility Packages
http://www.java.sun.com/j2se/1.4/docs/guide/util/logging/index.html
Logging
Invocation (RMI)
http://www.java.sun.com/j2se/1.4/docs/guide/math/index.html
Arbitrary-Precision
Math
-434 -
Java 2 Core Language Little Black Book Appendix B: R eferences
CORE Features
Title Link
Reflection http://www.java.sun.com/j2se/1.4/docs/guide/reflection/index.html
http://www.java.sun.com/j2se/1.4/docs/guide/versioning/index.html
Package Version
Identification
Sound http://www.java.sun.com/j2se/1.4/docs/guide/sound/index.html
http://www.java.sun.com/j2se/1.4/docs/guide/refobs/index.html
Reference Objects
http://www.java.sun.com/j2se/1.4/docs/guide/resources /index.html
Resources
Object http://www.java.sun.com/j2se/1.4/docs/guide/serialization/index.html
Serialization
http://www.java.sun.com/j2se/1.4/docs/guide/extensions/index.html
Extension
Mechanism
http://www.java.sun.com/j2se/1.4/docs/guide/jar/index.html
Java Archive
(JAR) Files
Interface (JNI)
http://www.java.sun.com/j2se/1.4/docs/guide/performance/index.html
Performance
Enhancements
http://www.java.sun.com/j2se/1.4/docs/guide/misc/index.html
Miscellaneous
Features (Applet
tag, Deprecation)
-435 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Java
Foundation
Classes
(JFC)
Topic Link
Abstract http://www.java.sun.com/j2se/1.4/docs/guide/awt/index.html
Window
Toolkit (AWT)
Components
2D Graphics http://www.java.sun.com/j2se/1.4/docs/guide/2d/index.html
and Imaging
http://www.java.sun.com/j2se/1.4/docs/guide/imageio/index.html
Image I/O
http://www.java.sun.com/j2se/1.4/docs/guide/imf/index.html
Input Method
Framework
Accessibility http://www.java.sun.com/j2se/1.4/docs/guide/access/index.html
http://www.java.sun.com/j2se/1.4/docs/guide/dragndrop/index.html
Drag-and-Drop
data transfer
Enterprise
Features
Topic Link
http://www.java.sun.com/j2se/1.4/docs/guide/rmi-iiop/index.html
RMI -IIOP
-436 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Enterprise
Features
Topic Link
http://www.java.sun.com/j2se/1.4/docs/guide/corba/index.html
CORBA
http://www.java.sun.com/j2se/1.4/docs/guide/jdbc/index.html
JDBCTM
(Java
Database
Connectivit
y)
Java http://www.java.sun.com/j2se/1.4/docs/guide/jndi/index.html
Naming
and
Directory
InterfaceT
M (JNDI)
Deployment
Topic Link
http://www.java.sun.com/j2se/1.4/docs/guide/plugin/index.html
Java Plug-in
Start
Tool
Suppor
t
-437 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Topic Link
http://www.java.sun.com/j2se/1.4/docs/guide/jpda/index.html
Java
Platform
Debugg
er
Architect
ure
(JPDA)
Java http://www.java.sun.com/j2se/1.4/docs/guide/jvmpi/index.html
Virtual
Machine
Profiler
Interface
(JVMPI)
Topic Link
Java 2 http://www.java.sun.com/products/jdk/faq.html
SDK
FAQ
Java 2 http://www.java.sun.com/j2se/1.4/docs/api/index.html
Platform
API
Specifica
tion
http://www.java.sun.com/products/jdk/faq/faq-sun-packages.html
Note
about
sun.*
Package
s
Languag
-438 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Topic Link
e
Specifica
tion
Virtual
Machine
Specifica
tion
Table B.11: Online Java books.
Title Link
Advanced http://www.developer.java.sun.com/developer/onlineTraining/Programming/JDCBoo
Programming for k/index.html
the Java 2
Platform
Computer http://www.g.oswego.edu/%7Eblue/java/hyperbook/org/Cover.html
Science Java
Style
Developing http://www.docs.rinet.ru:8080/Jintra/
Intranet
-439 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Title Link
Applications
Using Java
Java: An http://www.scism.sbu.ac.uk/jfl/jflcontents.html
Object-First
Approach
-440 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Topic Link
http://www.javacats.com/US/tools
Tools
Books http://www.javacats.com/US/books
http://www.javacats.com/US/reference
Reference
Table B.13: Miscellaneous resources.
Topic Link
http://www.developer.java.sun.com
Java
Developer
Connection
Y
FL
http://www.java.sun.com/docs/codeconv
Code
Conventions
AM
Guide
TE
http://www.java.about.com
About.com
Focus on Java
http://www.javaworld.com
"JavaWorld"
Magazine
(applet stuff)
http://www.sys-con.com/java
"Java
Developer's
Journal (best
Java
magazine)"
-441 -
Team-Fly®
Java 2 Core Language Little Black Book Appendix B: R eferences
Topic Link
http://www.mindspring.com/~scdrye/java/faq.html
Swing FAQs
http://www.rain.org/~da5e/macjava.html
Mac
developers
http://www.slashdot.org/search.pl?topic=java
Slashdot
Coding http://www.topcoder.com
tournament
http://www.www-106.ibm.com/developerworks/java
IBM's Java
IBM's http://www.alphaworks.ibm.com
AlphaWorks
http://www.xml.apache.org
Apache's
open source
http://www.jguru.com
Outstanding
developer site
Regular http://www.developer.java.sun.com/developer/technicalArticles/releases/1.
4regex/
Expressions
http://www.java.sun.com/jdc/JDCTechTips/2001/tt0807.html
Exact
Calculations
with
Floating-Point
Certification http://www.developer.java.sun.com/developer/technicalArticles/Interviews/
FAQs Certification2/index.html
-442 -
Java 2 Core Language Little Black Book Appendix B: R eferences
Topic Link
http://www.developer.java.sun.com/developer/qow/archive
Question of
the Week
http://www.java.sun.com/products/hotspot
HotSpot
http://www.java.sun.com/docs/glossary.print.html
Glossary of
Java and
Related
Terms
Sun http://www.sun.com/policies/trademarks
Trademark
and Logo
Usage
Requirements
http://www.jguru.com/jguru/faq
jguru
UML http://www.javareport.com/java2interactive/index.html
diagrams for
the core Java
packages
http://www.omg.org/uml
UML
Resource
Page
-443 -
Java 2 Core Language Little Black Book Appendix C: The Java Virtual Machine
Overview
You don't have to know how a car engine works in order to drive a car. Still, the best drivers do know
how their engines work, and this knowledge often helps them coax that last ounce of performance
from their cars. Understanding the Java Virtual Machine (JVM), its place in Java's architecture, and
how it works will help you write code that takes advantage of the JVM and avoids its weaknesses.
The JVM is a make-believe CPU that executes a special machine language (bytecodes) tailored for
Java. Although it is possible to make a hardware Java CPU (and some exist), most computers use a
CPU chip that doesn't understand Java bytecodes. Therefore, a machine-specific program— the
JVM— interprets the Java bytecodes. The Java compiler creates a file that is JVM -specific instead of
machine-specific. As long as your machine has the correct JVM, that machine can run any Java
program.
Many versions of the JVM are available from a variety of vendors. Some JVMs interpret each
bytecode on a case-by-case basis. Others use a justin-time strategy to compile the bytecodes to
na tive machine language instructions upon execution. This strategy takes a little longer to set up than
does the simple interpreter, but the strategy should result in faster execution over the long run.
JVM Architecture
Each vendor can build its own JVM, but it must comply with the following architectural criteria:
§ PC register— This register is a program counter used by each JVM thread; this counter
executes and indicates the current instruction that each thread is executing (unless the
thread is executing a native method). The JVM's PC register is one word wide, the width
guaranteed to hold a returnAddress or a native pointer on the specific platform.
§ Java stack— Each JVM thread has a private stack, created at the same time as the thread.
A Java stack stores JVM frames. Each frame holds local variables and plays a part in
method invocation and return. Because the stack is never manipulated directly except to
push and pop frames, the JVM might actually implement the stack as a heap, and Java
frames might be heap allocated. The memory for a Java stack does not need to be
contiguous. A JVM implementation might give the programmer or the user control over
the initial size of Java stacks, as well as, in the case of dynamically expanding or
contracting Java stacks, control over the maximum and minimum sizes of Java stacks.
§ Heap— A heap is a memory area shared among all threads. The heap is the runtime data
area from which memory for all class instances, variables, and arrays is allocated. The
Java heap is created on virtual machine startup. Heap storage for objects is reclaimed
by the garbage collector.
§ Method area— The method area is created on virtual machine startup and is shared among
all threads. It stores per-class structures such as the constant pool, field and method
data, and the code for methods and constructors.
-444 -
Java 2 Core Language Little Black Book Appendix C: The Java Virtual Machine
§ Constant pool — A constant pool is a per-class table of constants ranging from numeric
literals known at compile time to method and field references that must be resolved at
runtime. Each constant pool res ides in the method area.
§ Native method stacks— The native method stack is a conventional stack used to support
native methods — that is, methods written in conventional languages such as C or written
in assembly language.
§ Frames— Frames store local variables, partial results, return values for methods, and
exception information. A new frame is created each time a method invocation occurs.
JVM Instructions
A JVM instruction consists of a one-byte opcode specifying the operation to be performed, followed by
zero or more operands supplying arguments or data that are used by the operation. Many instructions
have no operands and consist only of an opcode. The steps taken by the typical JVM are:
1. Fetch an opcode.
2. Fetch operands (if any).
3. Execute the corresponding acti on.
4. Repeat steps 1 through 3.
For the majority of instructions that deal with data types, the data type is represented explicitly in the
opcode mnemonic by a letter: i for an int operation, l for long, s for short, b for byte, c for char, f for
float, d fo r double, and a for reference types. For example, the iload instruction loads the contents of
a local variable, which must be an int, onto the operand stack. The fload instruction does the same
with a float value. The load actions are summarized as follows:
§ Load a local variable onto the operand stack— iload, iload_<n>, lload, lload_<n>, fload,
fload_<n>, dload, dload_<n>, aload, aload_<n>
§ Store a value from the operand stack into a local variable— istore , istore_<n>, lstore,
lstore_<n>, fstore, fstore_<n>, dstore, dstore_<n>, astore, astore_<n>
§ Load a constant onto the operand stack — bipush, sipush, ldc, ldc_w , ldc2_w,
aconst_null, iconst_m1, iconst_<i>, lconst_<l> , fconst_<f>, dconst_<d>
§ Gain access to more local variables using a wider index, or to a lar ger immediate
operand— wide
-445 -
Java 2 Core Language Little Black Book Appendix C: The Java Virtual Machine
The narrowing numeric conversion instructions, for example, are i2b for converting an int to a byte,
and i2c for converting an int to a char. The others are i2s, l2i, f2i, f2l, d2i, d2l, and d2f. Many more
opcodes, such as newarray, are available to create a new array and arraylength, which returns the
length of an array. You can get the whole list of them at the JVM specification at
http://www.java.sun.com/docs/books/vmspec/html/Overview.doc.html.
Java Compilation
The compiler translates yo ur source code into bytecodes. Consider this method:
return d1 + d2
3 dreturn
void whileInt()
int i = 0;
i++;
0 iconst_0
-446 -
Java 2 Core Language Little Black Book Appendix C: The Java Virtual Machine
1 istore_1
2 goto 8
5 iinc 1 1
8 iload_1
9 bipush 100
11 if_icmplt 5
14 return
You can use the javap tool with the - c option (see Appendix A) to disassemble the bytecodes for any
class.
The compiler generates a class file. The structure of this file looks like this:
ClassFile {
u4 magic;
u2 minor_version;
u2 major_version;
u2 constant_pool_count;
cp_info constant_pool[constant_pool_count-1];
u2 access_flags;
u2 this_class;
u2 super_class;
u2 interfaces_count;
u2 interfaces[interfaces_count];
u2 fields_count;
field_info fields[fields_count];
u2 methods_count;
method_info methods[methods_count];
u2 attributes_count;
attribute_info attributes[attributes_count];
-447 -
Java 2 Core Language Little Black Book Appendix C: The Java Virtual Machine
-448 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Overview
If you need detailed information about anything on the Internet, the RFCs (Requests for Comments)
are the actual source documents that define practi cally everything about the Internet. Unfortunately,
with thousands of RFCs available, it is difficult to know which ones you need to read. To make matters
worse, many RFCs are no longer active, which can be confusing.
Some RFCs (such as RFC1000) are an index to the other RFCs. Also, online search engines, such as
the one at http://www.faqs.org/rfcs , can be very helpful. You can also find a complete list at
http://www.ietf.org/iesg/1rfc_index.txt, and retrieve documents from http://www.rfc-editor.org/rfc.html.
You can also get RFCs via email. The email address is [email protected]. You can get an index of
RFCs by sending an email with the following text in the message body:
HELP: rfc_index
Complete help is available with this command:
HELP: help
To retrieve a specific RFC, send:
Retrieve: RFC
Doc-ID: RFC1000
Keep in mind that not all RFCs are standards. Some of them are even humorous (check out RFC
1149, for example). The true standards documents (and their corresponding RFCs) appear in Table
D.1. A few of the standards are obsolete, but they appear in the table for completeness.
-449 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-450 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
ARPA
RFC2822
Internet Text
Messages
4 Was Mail
Routing and
the Domain
TE
System
-451 -
Team-Fly®
Java 2 Core Language Little Black Book Appendix D: Active RFCs
STD001 Obsolete:
8 Was Exterior
Gateway
Protocol
(RFC 904)
-452 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
STD003 Replaced by
4 STD0056
-453 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
STD003 Obsolete:
9 Was BBN
Report 1822
(IMP/ Host
Interface)
-454 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-455 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
System's Lekashm
HYPERchan an
nel: Protocol
Specification
-456 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-457 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Often, i t is easier to find the standard you need by referring to the common name of the protocol it
defines. Table D.2 shows this rela tionship.
-458 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-459 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
IP-IEEE Standard for the Transmission of IP datagrams over IEEE 802 3 1042
Networks
IP-IPX Standard for the Transmission of 802.2 Packets over IPX 49 1132
Networks
-460 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
MAIL Standard for the Format of ARPA Internet Text Messages 11 822
Y
FL
NETBIOS Protocol Standard for a NetBIOS Service on a TCP/UDP 19 100 2
Transport: Detailed Specifications
AM
-461 -
Team-Fly®
Java 2 Core Language Little Black Book Appendix D: Active RFCs
SMTP -SIZ SMTP Service Extension for Message Size Declaration 10 1870
E
-462 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Table D.3 lists the most useful or interesting (and active) RFCs as of the time this was written, along
with information about the RFCs they update or make obsolete. The RFCs that are also standards are
noted with their standard number in the Title column of the table. Notice that some standards have
multiple RFCs, and these are not reflected in the table.
-463 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-464 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Multiple Control
Messages
-465 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-466 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-467 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-468 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-469 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Tomlinson,
J.E. White
-470-
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-471 -
Team-Fly®
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-472 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-473 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
of Contents
-474 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Domains
-475 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-476 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-477 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-478 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-479 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-480 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Y
M.K. Stahl,
FL
E.J. Feinler
AM
E.J. Feinler
-481 -
Team-Fly®
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-482 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Protocol
C. Partridge
-483 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-484 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-485 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Access Protocol:
Version 2
-486 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-487 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
and Authentication
Procedures
-488 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-489 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-490 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Y
FL
1808 Relative Uniform R. Fielding June 1995 RFC1738
Resource Locators
AM
Service, Whois++
-491 -
Team-Fly®
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-492 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-493 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Acknowledgement J. Mahdavi,
Options S. Floyd,
A.
Romanow
-494 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-495 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Network Graphics)
Specification
Version 1.0
-496 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-497 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-498 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-499 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Option
-500 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Ostermann
Y
FL
2617 HTTP J. Franks, June 1999 RFC2069
Authentication: P.
AM
S.
Lawrence,
P. Leach,
A. Luotonen,
L. Stewart
-501 -
Team-Fly®
Java 2 Core Language Little Black Book Appendix D: Active RFCs
-502 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
Channel
Management
2854 The ‘
text/html’ D. Connolly, June 2000 RFC2070,
Media Type L. Masinter RFC1980,
RFC1942,
RFC1867,
RFC1866
-503 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
MIME Content
-504 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
DES3 64 -bit
Output Feedback
-505 -
Java 2 Core Language Little Black Book Appendix D: Active RFCs
S. St.
Laurent,
D. Kohn
-506 -
Java 2 Core Language Little Black Book Index
Index
Symbols
?: operator, 41
/none/ members, 84
-count expression, 51
-o switch, 279
! operator, 36
A
abstract classes, 103-104
versus interfaces, 106
abstract members, 84
abstract method, 104
accept method, 216 , 229
Access
managing with packages, 106
random file access, 162-163
Access modifiers
for fields, 92-95
for methods, 99-101
addAll(Collection c) method, 113
add(Object o) method, 113
Algorithms, security, 301
digest algorithms, 303
American Standard Code for Information Interchange. See ASCII files
AND (&&) operators, 47-4 9
AND algorithm, 39
append method, customized, 293 -294
Applets, profiling, 280-281
appletviewer, 8
Arithmetic operations
data type precedence for, 51
optimizing, 282-283
ArithmeticException class, 60
arraycopy method, 116-117 , 122
ArrayList class, 122 , 125-128
inserting and removing elements with, 126-127
operations of, 127-128
speed of, 128
ArrayList collection, 11 5
-507 -
Java 2 Core Language Little Black Book Index
B
Backward compatibility, 274
Base class
abstract method as, 103-104
for common operations, 138
methods, accessing in, 88
for multithreaded servers, 237-239
BigInteger, 307
Binary data
processing, 158-159
sending to server, 242
Binary operator, 3 4
Binary values
-508 -
Java 2 Core Language Little Black Book Index
-509 -
Java 2 Core Language Little Black Book Index
C
Calendar class, 190
CallableStatement class, 206
Calling routines, exception handling by, 61
Capacity, of hash tables, 129
case statement
default label, 7 0
matching switch statement to, 70-71
Casting, 43-44, 51-54
implicit and explicit, 52-53
catch blocks, in methods, 62
catch keyword, multiple, 5 9
Char data type, 37, 45
Character class, for set membership test, 341
Character data types , 6
Characters, 29 -30
comparing, 341
escape sequences for, 29-30
one -byte, 325
parsing individually, 254 -255
reading, 156 -158
reading more than one at a time, 295-296
sending to server, 242
three-byte, 325
two-byte, 325
characters event, 257, 261-262
CharArrayReader class, 141
C harArrayWriter class, 141
charAt method, avoiding, 294
checkError() method, 242
Cipher object, 309
encoding and decoding text with, 311 -313
CipherOutputStream object
decoding streams with, 315-317
encoding streams with, 313-315
Class constructors, 104 -105
Class definition, 1 6-17, 20 , 23, 86, 102-104
curly braces for, 5 7
ending of, 23
.class extension, 10
Class files, storage of, 107
class keyword, 103
Class names, 29, 103
-510 -
Java 2 Core Language Little Black Book Index
in packages, 22 , 9 0-91
private, 21
protected methods, access to, 87
TE
-511 -
Team-Fly®
Java 2 Core Language Little Black Book Index
placeholders in, 67
profiling, 280 -281
readability of, 6 3-65
reuse of, 82
spaces in, 65
style guidelines, 63-6 5
white space in, 63
Collection interface, 114-115
List interface, 115
Map interface, 115
Set interface, 115
Collections, 112-115
arrays as, 115
duplicate entries, 115
elements in, 114-115
elements in, order of, 115
elements in, processing, 122-123
elements in, removing, 123
elements in, retrieving, 123
iterator method, 122-123
key values, 115
list-type, 114
Map grouping, 114
methods in, 113
order of elements, 125-128
Set grouping, 114
Collections framework, 112
Collections.synchronizedList(list) class, 125
Collisions, 129
Comma (,), 27
Command-line programs, 4
Comments, 24-25
// syntax, 24
/* syntax, 24 -25
/** syntax, 25
*/ syntax, 25
markers for, 24
placement of, 2 5
commit method, 168
compareTo method, 37
Compilation, 16-17
line terminators and, 20
path setup, 17
problems with, 14
-512 -
Java 2 Core Language Little Black Book Index
-513 -
Java 2 Core Language Little Black Book Index
+count e xpression, 51
Country codes, 333
CR + LF line terminator, 2 6
CR line terminator, 26
createContentHandler method, 226
createStatement method, 192
createURLStreamHandler method, 225
crimson.jar file, 255
Curly braces, 27
alignment of, 63
for grouping statements, 23, 56 -57
Currency
conversion of, 324
internationalizing, 337-339
Custom handlers
selecting, 225
setting, 225-226
Custom protocols, handling, 223-226
D
Data integrity, 300
Data security, 300 . See also Security.
Data structures, 112
arrays, 112, 116-118 . See also Arrays.
associative, 129-130
collections, 112-115
hash tables, 129-130
lists, 125-128
maps, 133-135
stacks, 123-125
vectors, 118-123
Data transmission, efficiency of, 235
Data types, 6-7 . See also Primitive data types; Reference data types.
casting values to, 43-44 , 52
compile time, 45
default values of, 32
get methods for, 199
implicit conversion, 52
literal, 46
mixing, 50-51
narrowing conversion, 51-53
-514 -
Java 2 Core Language Little Black Book Index
precedence of, 51
reference data types, 3 3-34
widening conversion, 51-52
Database objects
closing, 199
creating, 195 -199
Database queries
creating, 192
executing, 190-192
DatabaseMetaData class, 172-183
Databases
connecting to, 166-167
date formats, 187-190
driver for, selecting, 183-186
functionality, location of, 169
interrogating, 172-183
metadata, retrieving, 168, 172
rows, inserting, 204-205
SDK support for, 9
SQL for, 169 -170
stored procedures, execution of, 206-207
table objects for, 195-199
transactions, committing, 205
updating, 199, 204-205
DatagramPacket class, 210
DatagramPacket object, 230
connect method, 230
disconnect method, 230
DatagramSocket class, 210
DataInput interface, 163
DataInputStream class, 159 , 296-297
DataInputStream object, 231
DataOutput interface, 163
DataOutputStream class, 159
DataOutputStream object, 231
Dates
database library format, 187
formatting, 339-340
DCE, 248
Debugger, 4, 8
Declaration statement, 66
Declarations, 31-3 3
Decryption. See also Encryption.
of files, 315-317
-515 -
Java 2 Core Language Little Black Book Index
of strings, 311-313
default constructors, 105
default label, 7 0
DELETE statement, 204
Development, 2
Digest algorithms
characteristics of, 303
custom, 303
MD5 algorithm, 305
SHA-1 algorithm, 304-305
Digests, 300
comparing for message validity, 317-322
Digital signatures, 300
verifying, 320-322
Directories
directory structure, 14
enumerating files in, 151-152
Distributed Computing Environment. See DCE
Divide-by-zero exception, 59
do statement
break statement in, 75-76
continue statement in, 76
Doc ument object, creating, 266 -267
Document Object Model. See DOM
Document Type Definition. See DTD
document variable, 267
Documentation
automatic generation of, 2 5
on SDK, 15
DocumentBuilder object, 256
DocumentBuilderFactory class, 256
Dollar sign ($), 27
DOM, 247
DOM parsers, 265-271
creating, 256
tree structure document representation, 265
uses of, 257
Domain names, as package names, 90 , 107
DOS mode error, 14
double data type, 45
do...while statement, 66, 73
Download -management programs, 13
Driver class, 183 -186
DriverManager class, 183 -186
-5 16 -
Java 2 Core Language Little Black Book Index
Drivers
discrepancies with database, 170-171
managing, 183 -186
ODBC, 186
types of, 171
DSAPrivateKey object, 307
DSAPublicKey object, 307
DTD, 246
Dynamic loading, 5
E
EBCDIC, 6
Editions, 3
Editors, 7 -8
Element object, creating, 267
empty() method, 123-125
Empty statements, 6 6-6 7
Empty strings, 29
Encapsulation, 82-83
encode method, 219
Encryption, 300
of files, 313-315
signing messages and files, 317-320
of strings, 311-313
End-of-line characters, 26
endDocument event, 257
endElement event, 257
Entity names, examples of, 2 9
Equality
equality expression, 36
testing for, 36-37
equals method, 3 7
equals(Object o) method, 113
Errors. See also Exceptions.
during compilation, 1 7
no interface methods
included, 90
Escape characters, 2 9-30
Exception class, 60
Exception-handler parameters, 67
Exception handling, 59
advanced techniques, 274
-517 -
Java 2 Core Language Little Black Book Index
by calling routines, 61
of multiple exceptions, 60-61
for SocketException, 236
by try statement, 77 -78
in XML, 266 , 270
Exceptions, 58
BindException, 236
causes of, 58-5 9
checked, 62
ClassNotFoundError exception, 168
ConnectException, 236
creating, 61
detecting, 59 -6 0
divide-by-zero exception, 59 , 61 -62
forcing, 79
InterruptedIOException, 233
IOException, 216, 2 22 , 234 , 236
NoRouteTo HostException, 236
ParserConfigurationException error, 270
SAXException error, 270
SocketException, 235 -236
types of, 61-62
unchecked, 61
UnknownHostException, 212
exceptions methods, 9 9
Exclusive OR (XOR) algorithm, 39
executeQuery method, 192
executeUpdate() method, 204, 206
Execution of code, 2 , 9, 18
break statement in, 75-76
conditional, 56
continuing at catch keyword, 5 9
path setup, 18
problems with, 14
sequencing, 58 -6 1
stopping, 58
tracing, 280
Expression statement, 66
Expressions, 5 6-58
E xtended Binary Coded Decimal Interchange Code. See EBCDIC
extends keyword, 88, 103
Extensible Markup Language. See XML.
-518 -
Java 2 Core Language Little Black Book Index
F
factory class, 225
creating, 256
Fields, 21 , 83. See also Variables .
access modifiers for, 92 -95
access to, 2 1
File access, random, 162-163
File class, 146-148
FileEnumerator class, 151-152
FileInputStream class, 141
FileOutputStream class, 141
FileReader class, 141
FileReader object, 145 -146
Files
data, appending to, 148-149
decrypting, 315 -317
digital signature, verifying, 320-322
encrypting, 313 -315
enumerating, 151-152
importance of, 138
naming, 17
public classes in, 21
reading, 145 -146
saving as .java, 16
signing, 317-320
writing to, 146-148
Files streams. See also Streams.
creating, 145 -152
FileSave class, 320
FileWriter class, 141
fill method, 114
Filter classes, 142-143
creating, 154 -156
FilterInputStream class, 142-143
FilterOutputStream class, 142 -143
FilterReader class, 142-143
Filters
DataInputStream class, 159
DataOutputStream class, 159
FilterWriter class, 142-143
final members, 84
for classes, 103
final method, 9 5-96, 99
-519 -
Java 2 Core Language Little Black Book Index
creating, 102
final variable, 32-33 , 8 4-8 5, 95 -96
finally blocks, 62 -63, 7 8-79, 199
Fingerprints, message, 305
FlashGet download-management program, 1 3
float data type, 45
for loops, optimizing, 294 -295
for statement, 66 , 74 -7 5
break statement in, 75-76
condition clause, 74
continue statement in, 76
initialization clause, 7 4-7 5
update clause, 74
Foreign languages. See also I18N .
determining language preference, 326-327
dialects, 327-328
language codes, 332-333
locales of, 327-332
sorting rules, 328
translating strings into, 326
Form-feed character, 25
Formatting
currency, 337-339
dates, 339-340
numbers, 337-339
percentages, 337-339
Forms, submitting, 218-219
Forte, 7
Functions, 83. See also Methods.
calling directly, 291-292
defining, 23
static, 22-23
G
Garbage collection
forcing, 281
for maps, 133
during tests, 281
get method, for data types, 199
getAddress method, 212 , 228
getAllByName method, 212 -214, 228
-520 -
Java 2 Core Language Little Black Book Index
-521 -
Team-Fly®
Java 2 Core Language Little Black Book Index
H
Hash index, 129
Hash tables, 129-130
capacity of, 129
load factor of, 129
Hash values
computation of, 131
retrieving, 134
hashcode() method, 113
HashMap class, 129 -130, 133-135
methods for, 134-135
printing contents, 133-134
HashMap collection, 115
HashSet collection, 115
creating, 131 -132
Hashtable class
key tags, tracking with, 263
methods of, 129-130
Hashtable collection, 112 , 115
hasNext method, 123
Hidden variables, accessing, 108
Hostnames, resolving, 212-213, 228
HTML, 244
generating, 263-265
quotation marks in, 245
HTTP, JAR file retrieval with, 222
HTTP Post method, 219
HttpURLConnection class, 210, 218 , 222
Hypertext Markup Language. See HTML.
I
Identifiers , 26-29
rules for, 27-28
IDEs, 7
if-else statement, 41 , 68-69
if statement, 36 , 5 6, 66-69
conditional operator ?:, replacing with, 6 9-70
forms of, 68
statements, effect on, 56
zero arguments, detecting with, 59-60
-522 -
Java 2 Core Language Little Black Book Index
-523 -
Java 2 Core Language Little Black Book Index
Interfaces, 8 8-90
versus abstract classes, 106
constants, declaring in, 105-106
declaring, 105-106
extending, 106
naming, 29
International Organi zation for Standardization. See ISO
Internationalization of software. See I18N.
Internet, downloading programs over, 5
InterruptedIOException, 233
Intersections, HashSet for, 131-132
IOException, 216, 222 , 234 , 236
IP add ress resolution, 212-213, 228
isEmpty() method, 113
ISO, 333
Iterator interface, 122-123
iterator() method, 113
J
Jar, 8
JAR files
class file storage in, 107
retrieving, 222
Jarsigner, 8
JarURLConnection class, 211
Java
editions of, 3
encryption support, 300
Internet awareness, 210
naming scheme, 3
network protocol support, 210
network support, 210-211
Unicode support, 6-7
Java API for XML-based RPC (JAX-RPC), 255
Java API for XML Messaging (JAXM), 255
Java API for XML Processing (JAXP), 255
Java API for XML Registries (JAXR), 255
Java Architecture for XML Binding (JAXB), 255
Java Authentication and Authorization Service (JAAS), 9
Java Cryptography Extensions (JCE), 9
Java Database Connectivity. See JDBC.
-524 -
Java 2 Core Language Little Black Book Index
-525 -
Java 2 Core Language Little Black Book Index
K
Keep alives, setting, 235
Kerberos, Java 2 SDK 1.4 use of, 9
Key tags
polling for, 262-263
tracking, 263
Key values, pair value retrieval, 133-134
KeyPair object, 307
Keys, 301
algorithm for, 307
Cipher object for, 309
generating, 302, 307 -310
p, q, and g numbers, 307-310
selecting, 301
values associated with, 129
Keytool, 8
Keywords, reserved, 27 -28
L
Labeled statements, 76 -7 7
-526 -
Java 2 Core Language Little Black Book Index
-527 -
Java 2 Core Language Little Black Book Index
M
main method, 22-23 , 86, 144
Map interface, 115
mark method, 152-154
markS upported method, 152
Math operators, 34-35
Mathematical operations, optimizing, 282-283
mathHelper class, 270
max method, 114
MD5 algorithm, 305
Member variables, 67, 84
scope of, 93-95
Members, 8 4-85
accessibility modifiers, 84
hiding, 108
overriding, 108
Message digests, 300-301
creating, 303 -305
duplicate, 305
MessageBundle class, 332-334
MessageDigest class, getInstance method, 304
MessageDigestTest class, 304
Messages
digital signature, verifying, 320-322
encrypting and decrypting, 311-313
-528 -
Java 2 Core Language Little Black Book Index
-529 -
Java 2 Core Language Little Black Book Index
minValue variable, 93
MTServerBase class
extending, 238-239
server creation with, 239-240
MulticastSocket class, 211
Multipurpose Internet Mail Extensions. See MIME
Multithreaded servers
automating, 237-240
creating, 236 -237
Multithreading, 236-240 , 274 , 277 -278
synchronized members, 277
N
Nagle's algorithm, 235
Namespaces, managing with packages, 106
Narrowing conversion, 51 -53
native methods, 9 9
Native2ascii, 8
Network programs, socket programming, 210-217
Networking, 217
new method, avoiding, 291
new operator, 3 3, 42 , 85
for array creation, 46
newDocumentBuilder method, 256
newInstance method, 237-239
newSaxParser method, 256
next method, 123
Node types, converting integer representation to strings, 268-270
NodeList object, element order in, 267
NodeType class, 268
Nonrepudiation, 300
NoRouteToHostException, 236
Notepad, 7-8
notify method, 278
with wait method, 291
notifyAll method, 278, 291
null, 31, 43
Number class, 104
Numbers
internationalizing, 337-339
optimization and, 282-283
-530-
Java 2 Core Language Little Black Book Index
O
Object class, 275
Object creation statement, 66
Object locks, 277 -278
releasing, 278
Object names
reserved keywords and, 28
reusing, 28-29
Object-oriented programming, 8 2
base classes and, 138
ObjectIntputStream class, 141
ObjectOutputStream class, 141, 231
objectRead method, custom, 286
Objects, 20-21, 82-83
Y
FL
converting data into, 226
creating, 24
declaring, with new operator, 3 3
AM
instantiating, 85
optimizing, 291-292
reading, 156 -158, 275
reconstituting, 159-161
saving to file, 275
serializing, 159-161, 275-277 . See also Serialization.
strings, 2 2
synchronizing on, 278
type of, identifying, 275
object.ser file, 286
objectWrite method, custom, 286
ODBC, 166, 170
ODBC drivers, 186
ODBC-to -JDBC bridge, 168, 171
Open Database Connectivity. See ODBC.
openStream method, 217
Operator, 34 -42
assignment operators, 40-41
-531-
Team-Fly®
Java 2 Core Language Little Black Book Index
P
package fields, 92-95
package keyword, 107
package methods, 99
-532 -
Java 2 Core Language Little Black Book Index
Package scope, 21
Packages, 2 2, 90 -91
creating, 90, 107
importing, 22 , 91
importing classes into, 107
naming, 29, 90 , 107
use of, 106-108
Parameters, 23
rules for use, 9 8
parameters methods, 9 9
Parentheses, 27
parse method, 256
ParserConfigurationException error, 270
Parsers, 246-247
building, 248-255
characters, parsing individually, 25 4-255
creating, 256 -257
DOM, 247, 256 -257, 265-271
SAX, 247 , 256-263
UTF encoding, acceptance of, 254
white space, handling, 254
PATH variable, 8
setting, 1 4
peek() method, 1 23-125
Performance
code in stored procedures and, 170-171
optimizing. See Optimization .
PipedInputStream class, 141
PipedOutputStream class, 141
PipedReader class, 141
PipedWriter class, 141
Placeholders, in code, 67
Platform, 3
Policytool, 8
Polymorphism, 82-83, 88
pop() method, 123-125
Port numbers, for servers, 215-216
Ports, scanning for use of, 217
PreparedStatement objects, 205
previousString variable, 276
Primitive data types, 45
casting, 5 4
initializing variables with, 3 2
literals for, 46-4 7
-533 -
Java 2 Core Language Little Black Book Index
Printing to screen, 23
println statement, 280
PrintStream class, 141 , 242
PrintWriter class, 141, 242
Private classes, 21
private constructors, 105
private fields, 9 2-95
Private keys, 301
generating, 307-310
private members, 84
private methods, 97 , 99
PrivateKey object, 307
process method, 78
processingInstruction event, 258
Professional applications
backward compatibility of, 274
exception handling, 274
execution speed, 274
installation programs, 274-275
Profiling tools, 274, 280 -281
Properties collection, 115
protected constructors, 105
protected fields, 92-95
protected members, 84
protected methods, 86 , 99
Protocol handlers, custom, 225-226
public classes, 1 0, 17, 21 , 103 , 107
naming, 23
public constructors, 105
public fields, 92-9 5
Public key cryptography, 301
Public keys, 301
generating, 307-310
public members, 84
public members, inheritance of, 87
public methods, 97, 99
publicKey object, 307
push() method, 124-125
PushbackInputStream class, 142
PushbackReader class, 142
-534 -
Java 2 Core Language Little Black Book Index
Q
Quotation marks, single and double, 29
R
Random class, 307
Random file access, 162-163
Random-number generator, 68 -69, 303 , 306
Random numbers
generating, 306-307
seeds for, 306-307
unpredictable sequence of, 307
RandomAccessFile class, 162-163
Read timeouts for sockets, 233-234
readByte method, 159
Reader class, 138
Readers, 140-142
readFloat method, 159
Reading
characters, 156-158
files, 145-146
objects, 156-158
optimizing, 295-297
with random file access, 162 -163
Reference data types, 3 3-34 , 45
Reflection functions, 237
registerOutParameter method, 207
Relational operators, 3 6
Remote Procedure Calls. See RPCs .
remove method, 123 , 126
removeAll(Collection c) method, 113
remove(Object o) method, 113
Repositories, text, 327
management of, 327
Requests
setting type, 222
submitting, 218 -219
Requests for Comments. See RFCs
Reserved keywords, 27 -2 8
reset method, 152-154
ResourceBundle class, 327
-535 -
Java 2 Core Language Little Black Book Index
S
Sandbox, 6
SAX parsers, 247 , 257-263
creating, 256
event functions, 257 -258
event functions, adding code to, 264 -265
key tags, polling for, 262
serial processing of XML document with, 256
SAXException error, 270
SaxParser object, 256
SaxParserFactory class, 256
-536 -
Java 2 Core Language Little Black Book Index
Schemas, 246
Scope, 29 , 92-93
defining, 57, 67
SDK, 2 -5
appletviewer, 8
compiler, 4, 8
components of, 8
debugger, 8
directory, 10
directory structure, 14
documentation on, 15
downloading, 11-13
features of, 9
installing, 13-14
jar, 8
jarsigner, 8
javadoc, 8
JDBC APIs, 9
keytool, 8
multiple versions, 8
native2ascii, 8
policytool, 8
redistributing, 9
runtime engine, 8
runtime system, 4
security features, 9
source code, 4-5
Unicode support, 9
versions of, 8-9
XML parser, 9
search() method, 124-125
Searching
arrays, 117-118
lists, 128
SecureRandom class, 307
Security
algorithms, 301
goals of, 300
Java 2 SDK 1.4 features for, 9
key generation, 307-310
keys, 301
message digest, 300 -301 , 303-305
random -number generation, 306-307
SELECT statement, 204
-537 -
Java 2 Core Language Little Black Book Index
Semicolon (;), 2 7
Separators, 26 -27
SequenceInputStream class, 142 , 1 49-151
Sequencing execution, 58-61
Serializable interface, 159-161, 275 -276
Serialization, 159 -161, 275-277
advanced techniques, 274
customizing, 286-287
functions of, 275
object support for, 275-276
process of, 284 -286
serialVersionUID name for classes, 276-277
serialVersionUID name, 276-277
Server accept timeouts, 234
Server sockets
client connections, 229
opening, 229
Servers
clients, maximum number of, 216
compressed files, sending to, 233
connecting to, 211 , 214-215
copies of, 216
incoming connections, listening for, 211-212, 216
multithreading, 236-237
passing data to, 219-220
port assignment, 211
port numbers for, 215-216
queue size, 216
requests, submitting, 218-219
server sockets, opening, 229
simple, 236
TCP sockets, 228-229
thread creation, 229
UDP sockets, 230
writing to, 211, 215-217 , 241 -242
ServerSocket class, 211, 215-217 , 229
ServerSocket.setSoTimeout method, 234
Set interface, 115
setAllowUserInteraction method, 220
setAutoCommit method, 168
setContentHandlerFactory method, 226
setDaemon method, 278
setDate method, 187
setDefaultAllowUserInteraction method, 220
-538 -
Java 2 Core Language Little Black Book Index
-539 -
Java 2 Core Language Little Black Book Index
-540 -
Java 2 Core Language Little Black Book Index
static methods, 9 7, 99
static variable, 96 -97
Stored procedures, 170-171, 206-207
TE
-541 -
Team-Fly®
Java 2 Core Language Little Black Book Index
-542 -
Java 2 Core Language Little Black Book Index
T
Tab character, 25
Table objects, creating, 194-199
TCP, Java socket support for, 210
TCP sockets, 211 , 215-217
opening, 228 -229
receiving data from, 231-232
sending data to, 231
Ternary operator, 34 , 4 2
Tests
garbage collection during, 281
switch statement for, 71
testVariableScope method, 93
Text
internationalizing, with ListResourceBundle, 334-336
internationalizing, with MessageBundle, 332 -334
repository for, 326
Text editor, 2
writing code with, 15-16
Text translations, 326-327
this keyword, 90
Thread class, 277
extending, 237, 277, 287-288
run method, 287-288
Threads. See also Multith reading.
beginning execution, 277
creating, 287 -288
for incoming requests, 229
object lock ownership, 277 -278
pausing, 289 -291
reads and processing, separating in, 234
releasing, 278, 291
sleeping, 289-291
wait method, calling from within, 278
wait state, 278 , 291
-543 -
Java 2 Core Language Little Black Book Index
yielding, 289-291
throw statement, 61-62 , 79, 101-102
Time
level of accuracy of system, 281
retrieving, 240
Time checker, 240 -241
Time servers, opening, 223-224
Timeouts
server accept timeouts, 234
socket read timeouts, 233-234
Timer class, finally statement in, 78-79
toArray() method, 113
Token list, refining, 26
Tokenizing, 157
Tokens, 2 0, 25-26
multiple-line comments between, 2 5
Tools
editors, 7-8
IDEs, 7
Transactions, committing, 205
transient members, 84
transient modifier, 276
Transmission Control Protocol. See TCP
TreeMap collection, 115
TreeSet collection, 115
creating, 132 -133
try blocks, 168
in methods, 62
try-catch-finally statement, 78-79
try-catch statement, 77-78
try statement
exception detection with, 5 9-60
finally blocks with, 6 2-63
U
UDP, Java socket support for, 210
UDP sockets, 211 , 230
Unary operator, 34
Underscore character (_), 27
Unicode, 6-7, 325
mapping bytes into, 138-139
-544 -
Java 2 Core Language Little Black Book Index
V
Values, keys associated with, 129
Variable scope, 6 7, 9 2-93 . See also Scope .
Variables, 21 , 31, 83 . See also Fields.
accessibility of, 57 , 67. See also Scope .
casting, 4 3-4 4
declaring, 16 -1 7, 31 , 45 -46
-545 -
Java 2 Core Language Little Black Book Index
W
wait method
calling from within thread, 278
notify method with, 291
WeakHashMap collection, 115, 133 -135
methods for, 134-135
Web browsers, building, 263 -264
Web pages
data presentation, describing
-546 -
Java 2 Core Language Little Black Book Index
X
XML, 244 -246. See also Parsers.
n element, 258
characters in, 261
<color> element, 258
DTDs, 246
elements, retrieving, 267
elements of, 258
event functions, 257 -258
event functions, adding code to, 264 -265
exception handling in, 266 , 270
helper classes, 268
<item> element, 258
Java extensions for, 255
Java parser for, 9
-547 -
Java 2 Core Language Little Black Book Index
Y
yield method, 289
-548 -
Java 2 Core Language Little Black Book List of Figures
List of Figures
Chapter 1: Getting Started with Java
Figure 1.1: The Java 2 Platform, Standard Edition home page.
Figure 1.2: Selecting the operating system.
Figure 1.3: The download page.
Figure 1.4: The recommended directory structure for the local hard drive.
Figure 1.5: Setting the PATH system variable.
-549 -
Java 2 Core Language Little Black Book List of Tables
List of Tables
Chapter 2: Essential Java Syntax
Table 2.1: Examples of entity names.
Table 2.2: The escape sequences in Java.
Table 2.3: Default values for given data types.
Table 2.4: Java operators.
Table 2.5: Operator precedence.
Table 2.6: Boolean operations.
Table 2.7: Shift operators.
Table 2.8: Assignment operators.
Table 2.9: Primitive data types.
Table 2.10: List of literal data types.
Appendix B: References
Table B.1: Sun tutorials.
Ta ble B.2: Sun questions and exercises.
Table B.3: Sun articles with sample code.
Table B.4: Sun quizzes.
-550-
Java 2 Core Language Little Black Book List of Tables
Y
FL
AM
TE
-551 -
Team-Fly®
Java 2 Core Language Little Black Book List of Tables
List of Listings
Chapter 2: Essential Java Syntax
Listing 2.1: This simple program does all of its work in the main function.
Listing 2.2: This simple program creates an object.
Listing 2.3: This program demonstrates some string comparisons.
Listing 2.4: Using the shift operators.
Listing 2.5: Getting the maximum and minimum values for Java's numerical data types.
Listing 2.6: A conditional operator demonstration program.
-552 -
Java 2 Core Language Little Black Book List of Tables
-553 -
Java 2 Core Language Little Black Book List of Tables
-554 -