A propos de ce document

Ce document a été construit automatiquement à partir de la documentation HTML disponible sur java.sun.com. Il est périodiquement remis à jour, lorsque de nouvelles versions des documentations originales deviennent disponibles. Pour télécharger librement et gratuitement ces mises à jour, mais aussi d''autres documents Java au format HTMLHelp ou WinHelp, visitez le site de Franck Allimant :

http://javadoc.allimant.org/

Bonne utilisation !

Contact

Les remarques et les suggestions sont les bienvenues. Merci de les faire parvenir à Franck Allimant.

Notes

La documentation HTML originale est disponible sur java.sun.com. Merci de la consulter si vous avez des incertitudes à propos les informations présentées dans ce document.

La version HTMLHelp de cette documentation diffère par quelques points de la version HTML, à cause de certaines limitations de HTMLHelp.

1. Applets Java

Les applets Java 1 fonctionnent correctement dans HTMLHelp, pourvu que les classes Java ne soient pas embarquées dans le fichier d'aide (chm) lui-même. Elles sont stockées dans le répertoire applets, qui se trouve au même endroit que le fichier d'aide. Ce répertoire n'est pas nécessaire au fonctionnement de l'aide : s'il est absent, les applets ne seront pas affichées.

Le plugin Java n'est pas supporté par HTMLHelp. Les applets nécessitant une machine virtuelle Java 2 ne peuvent pas être exécutées.

2. Fichiers nécessitant un plugin

Le support des plugins n'est pas complet dans HTMLHelp. En fonction de la configuration de votre machine, certains problèmes peuvent survenir lors de la visualisation de ces fichiers, en particulier les documents PDF.

3. Occurrences multiples d'un mot-clef de l'index

Si un mot clef de l'index pointe vers plusieurs documents, une page listant toutes les occurrences trouvées est affichée. Cette page fournit le titre des documents dans lequel le mot clef apparaît, et s'il s'agit d'une méthode, les paramètres de cette méthode. Ce mode d'affichage très détaillé a été préféré à la boîte de dialogue "Rubriques Trouvées" proposées en standard par HTMLHelp, pour permettre une navigation plus efficace et plus rapide dans un grand nombre de documents.

Merci à...

a.do Consulting, pour offrir gratuitement un parser HTML écrit en Java aussi compact et efficace.

Doug Kramer, de Sun, qui a autorisé la distribution des documentations Java pour WinHelp et HTMLHelp.

Distribution

Ce logiciel est gratuit. Il ne peut être diffusé sur Internet ou dupliqué que dans des buts non commerciaux, pour usage privé exclusivement. Toute distribution par CD-ROM est soumise à une autorisation préalable [contact].

Toutes les restrictions de distribution imposées par Sun à la documentation originale sont applicables au présent document. Consultez cette page (en anglais) pour en prendre connaissance.

Copyright © 1997-2004, Franck Allimant


About this document

This document is built from the HTML documentations available at java.sun.com. It is regularly updated, when new versions of original documentations become available. To download updates and many other WinHelp and HTMLHelp Java documentations for free, visit Franck Allimant's web site :

http://javadoc.allimant.org/

Contact

Comments and suggestions are welcome. Feel free to send them to Franck Allimant.

Notes

The original HTML documentation is available at java.sun.com. Please refer to this original documentation if you're not confident with the present document.

Due to some HTMLHelp limitations, there are some differences between this help file and the original HTML version of the documentation.

1. Java Applets

In most cases, Java 1 applets are running inside the HTMLHelp viewer, provided they're not embedded in the help (chm) file. They are stored in the applets directory, located at the same level as the help file. This folder is not required for browsing help, but if it is missing, applets will not be displayed.

Java 2 applets require the Java Plugin, which is not supported by the HTMLHelp viewer. These applets will not be displayed.

2. Documents that require a plugin

Plugins are not fully supported by the HTMLHelp viewer. Depending on the configuration of your machine, some problems may occur when viewing these files, for example PDF documents.

3. Multiple occurrences of an index keyword

If an index keyword points to more than one document, a page that lists all found occurrences is displayed. This page shows the title of every document in which the keyword appears, and if this keyword is a method, the parameters of this method. This detailed display has been preferred to the standard HTMLHelp "Topics Found" dialog box, to provide a faster and more efficient browsing of a large number of documents.

Thanks to...

a.do Consulting, for HtmlStreamTokenizer™, a compact, efficient and free HTML parser written in Java.

Doug Kramer at Sun, who authorized the distribution of this document.

Distribution

This software is free. Permission to use, copy, and distribute this software for non-commercial purposes via the Internet without fee is hereby granted. Permission is not granted for any distribution in the form of CD-ROM [contact].

Sun's documentation redistribution policy is applicable to this document. Please see this page for details.

Copyright © 1997-2004, Franck Allimant


The Java™ Tutorials

License Info

Tutorial Contents

Tutorial Resources

The Java Tutorials' Blog has news and updates about the Java SE tutorials.
You can download the Java Tutorials from the Sun Download Center.
The FAQ answers questions about the Tutorials.
Online Resources lists programming aids besides the Tutorials.

In Book Form

The Java Tutorial, Fourth Edition. Amazon.com.
Errata for The Java Tutorial, Fourth Edition.
The JFC Swing Tutorial, Second Edition. Amazon.com.
Other books on the Java platform are available from The Java Series Store.

Other Tutorials

The Java EE 5 Tutorial
The Java Web Services Tutorial
The J2EE Tutorial for the Sun ONE Platform
Using NetBeans™ IDE 5.5

Sun Training and Professional Certification

Java and Web Services Training
Sun Java Technology Certification

Software

The Java Development Kit (JDK) for Java SE 6.
NetBeans IDE
Java EE SDK
The Java Tutorials are practical guides for programmers who want to use the Java programming language to create applications. They include hundreds of complete, working examples, and dozens of lessons. Groups of related lessons are organized into "trails".

For the most accurate and up-to-date tutorials, please access the latest version from Sun's official website for the Java SE Tutorials (Last Updated 3/14/2008), which can be found at: http://java.sun.com/docs/books/tutorial.

The Java Tutorials describe features that are new for Java SE 6. For best results, download JDK 6.

For supporting Java Platform documentation, see the latest Java SE Platform Guides and API documentation.

Trails Covering the Basics

These trails are available in book form as The Java Tutorial, Fourth Edition. To buy this book, refer to the box to the right.
  • Getting Started — An introduction to Java technology and lessons on installing Java development software and using it to create a simple program.
  • Learning the Java Language — Lessons describing the essential concepts and features of the Java Programming Language.
  • Essential Java Classes — Lessons on exceptions, basic input/output, concurrency, regular expressions, and the platform environment.
  • Collections — Lessons on using and extending the Java Collections Framework.
  • Swing — An introduction to the Swing GUI toolkit, with an overview of features and a visual catalog of components. See below for a more comprehensive tutorial on Swing.
  • Deployment — How to package applications and applets using JAR files, and deploy them using Java Web Start and Java Plug-in.
  • Preparation for Java Programming Language Certification — List of available training and tutorial resources.

Creating Graphical User Interfaces

This trail is available in book form as The JFC Swing Tutorial. To buy this book, refer to the box to the right.

As part of the update to JDK 6, the Swing examples are now bundled to be open and run in NetBeans IDE. (Of course you can import the source files into any IDE that you wish.) For more information, see Running Tutorial Examples in NetBeans IDE. Each Swing lesson has a separate Examples Index — for an sample, check out the Using Swing Components Examples Index.
  • Creating a GUI with Swing — A comprehensive introduction to GUI creation on the Java platform.

Specialized Trails and Lessons

These trails and lessons are only available as web pages.

  • Custom Networking — An introduction to the Java platform's powerful networking features.
  • The Extension Mechanism — How to make custom APIs available to all applications running on the Java platform.
  • Full-Screen Exclusive Mode API — How to write applications that more fully utilize the user's graphics hardware.
  • Generics — An enhancement to the type system that supports operations on objects of various types while providing compile-time type safety. Note that this lesson is for advanced users. The Java Language trail contains a Generics lesson that is suitable for beginners.
  • Internationalization — An introduction to designing software so that it can be easily be adapted (localized) to various languages and regions.
  • JavaBeans — The Java platform's component technology.
  • JDBC Database Access — Introduces an API for connectivity between the Java applications and a wide range of databases and a data sources.
  • JMX— Java Management Extensions provides a standard way of managing resources such as applications, devices, and services.
  • JNDI— Java Naming and Directory Interface enables accessing the Naming and Directory Service such as DNS and LDAP.
  • RMI — The Remote Method Invocation API allows an object to invoke methods of an object running on another Java Virtual Machine.
  • Reflection — An API that represents ("reflects") the classes, interfaces, and objects in the current Java Virtual Machine.
  • Security — Java platform features that help protect applications from malicious software.
  • Sound — An API for playing sound data from applications.
  • 2D Graphics — How to display and print 2D graphics in applications.
Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 3/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.


Trail: Getting Started (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Getting Started
This trail provides everything you'll need to know about getting started with the Java programming language.

The Java Technology Phenomenon Provides an overview of Java technology as a whole. It discusses both the Java programming language and platform, providing a broad overview of what this technology can do and how it will make your life easier.

The "Hello World!" Application This hands-on approach describes what to download, what to install, and what to type, for creating a simple "Hello World!" application. It provides separate instructions for the NetBeansTM integrated development environment (NetBeans IDE), Microsoft Windows, SolarisTM Operating System (Solaris OS), Linux, and Mac users.

A Closer Look at "Hello World!" Discusses the "Hello World!" application, describing each section of code in detail. It covers source code comments, the HelloWorldApp class definition block, and the main method.

Common Problems (and Their Solutions) This is the place to go if you have trouble compiling or running the programs in this trail.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: The Java Technology Phenomenon


Lesson: The Java Technology Phenomenon (The Java™ Tutorials > Getting Started)

The Java Technology Phenomenon
About the Java Technology
What Can Java Technology Do?
How Will Java Technology Change My Life?
Trail: Getting Started
Home Page > Getting Started
« Previous • Trail • Next »
Lesson: The Java Technology Phenomenon
Talk about Java technology seems to be everywhere, but what exactly is it? The following sections explain how Java technology is both a programming language and a platform, and provide an overview of what this technology can do for you.
  • About the Java Technology
  • What Can Java Technology Do?
  • How Will Java Technology Change My Life?
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: About the Java Technology


About the Java Technology (The Java™ Tutorials > Getting Started > The Java Technology Phenomenon)

Trail: Getting Started
Lesson: The Java Technology Phenomenon
The Java Technology Phenomenon
About the Java Technology
What Can Java Technology Do?
How Will Java Technology Change My Life?
Home Page > Getting Started > The Java Technology Phenomenon
« Previous • Trail • Next »
About the Java Technology
Java technology is both a programming language and a platform.

The Java Programming Language

The Java programming language is a high-level language that can be characterized by all of the following buzzwords:

  • Simple
  • Architecture neutral
  • Object oriented
  • Portable
  • Distributed
  • High performance
  • Multithreaded
  • Robust
  • Dynamic
  • Secure

    • Each of the preceding buzzwords is explained in The Java Language Environment , a white paper written by James Gosling and Henry McGilton.

    In the Java programming language, all source code is first written in plain text files ending with the .java extension. Those source files are then compiled into .class files by the javac compiler. A .class file does not contain code that is native to your processor; it instead contains bytecodes — the machine language of the Java Virtual Machine1 (Java VM). The java launcher tool then runs your application with an instance of the Java Virtual Machine.

    Figure showing MyProgram.java, compiler, MyProgram.class, Java VM, and My Program running on a computer.

    An overview of the software development process.

    Because the Java VM is available on many different operating systems, the same .class files are capable of running on Microsoft Windows, the Solaris TM Operating System (Solaris OS), Linux, or Mac OS. Some virtual machines, such as the Java HotSpot virtual machine, perform additional steps at runtime to give your application a performance boost. This include various tasks such as finding performance bottlenecks and recompiling (to native code) frequently used sections of code.

    Figure showing source code, compiler, and Java VM's for Win32, Solaris OS/Linux, and Mac OS

    Through the Java VM, the same application is capable of running on multiple platforms.

    The Java Platform

    A platform is the hardware or software environment in which a program runs. We've already mentioned some of the most popular platforms like Microsoft Windows, Linux, Solaris OS, and Mac OS. Most platforms can be described as a combination of the operating system and underlying hardware. The Java platform differs from most other platforms in that it's a software-only platform that runs on top of other hardware-based platforms.

    The Java platform has two components:

    • The Java Virtual Machine
    • The Java Application Programming Interface (API)
    You've already been introduced to the Java Virtual Machine; it's the base for the Java platform and is ported onto various hardware-based platforms.

    The API is a large collection of ready-made software components that provide many useful capabilities. It is grouped into libraries of related classes and interfaces; these libraries are known as packages. The next section, What Can Java Technology Do? highlights some of the functionality provided by the API.

    Figure showing MyProgram.java, API, Java Virtual Machine, and Hardware-Based Platform

    The API and Java Virtual Machine insulate the program from the underlying hardware.

    As a platform-independent environment, the Java platform can be a bit slower than native code. However, advances in compiler and virtual machine technologies are bringing performance close to that of native code without threatening portability.

    The terms"Java Virtual Machine" and "JVM" mean a Virtual Machine for the Java platform.

    « Previous • Trail • Next »
    Problems with the examples? Try Compiling and Running the Examples: FAQs.
    Complaints? Compliments? Suggestions? Give us your feedback.

    Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

             About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
    Copyright 1995-2008 Sun Microsystems, Inc.
    Previous page: The Java Technology Phenomenon
    Next page: What Can Java Technology Do?


What Can Java Technology Do? (The Java™ Tutorials > Getting Started > The Java Technology Phenomenon)

Trail: Getting Started
Lesson: The Java Technology Phenomenon
The Java Technology Phenomenon
About the Java Technology
What Can Java Technology Do?
How Will Java Technology Change My Life?
Home Page > Getting Started > The Java Technology Phenomenon
« Previous • Trail • Next »
What Can Java Technology Do?

The general-purpose, high-level Java programming language is a powerful software platform. Every full implementation of the Java platform gives you the following features:

  • Development Tools: The development tools provide everything you'll need for compiling, running, monitoring, debugging, and documenting your applications. As a new developer, the main tools you'll be using are the javac compiler, the java launcher, and the javadoc documentation tool.

  • Application Programming Interface (API): The API provides the core functionality of the Java programming language. It offers a wide array of useful classes ready for use in your own applications. It spans everything from basic objects, to networking and security, to XML generation and database access, and more. The core API is very large; to get an overview of what it contains, consult the Java SE Development Kit 6 (JDKTM 6) documentation.

  • Deployment Technologies: The JDK software provides standard mechanisms such as the Java Web Start software and Java Plug-In software for deploying your applications to end users.

  • User Interface Toolkits: The Swing and Java 2D toolkits make it possible to create sophisticated Graphical User Interfaces (GUIs).

  • Integration Libraries: Integration libraries such as the Java IDL API, JDBCTM API, Java Naming and Directory InterfaceTM ("J.N.D.I.") API, Java RMI, and Java Remote Method Invocation over Internet Inter-ORB Protocol Technology (Java RMI-IIOP Technology) enable database access and manipulation of remote objects.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: About the Java Technology
Next page: How Will Java Technology Change My Life?


How Will Java Technology Change My Life? (The Java™ Tutorials > Getting Started > The Java Technology Phenomenon)

Trail: Getting Started
Lesson: The Java Technology Phenomenon
The Java Technology Phenomenon
About the Java Technology
What Can Java Technology Do?
How Will Java Technology Change My Life?
Home Page > Getting Started > The Java Technology Phenomenon
« Previous • Trail • Next »
How Will Java Technology Change My Life?
We can't promise you fame, fortune, or even a job if you learn the Java programming language. Still, it is likely to make your programs better and requires less effort than other languages. We believe that Java technology will help you do the following:
  • Get started quickly: Although the Java programming language is a powerful object-oriented language, it's easy to learn, especially for programmers already familiar with C or C++.

  • Write less code: Comparisons of program metrics (class counts, method counts, and so on) suggest that a program written in the Java programming language can be four times smaller than the same program written in C++.

  • Write better code: The Java programming language encourages good coding practices, and automatic garbage collection helps you avoid memory leaks. Its object orientation, its JavaBeansTM component architecture, and its wide-ranging, easily extendible API let you reuse existing, tested code and introduce fewer bugs.

  • Develop programs more quickly: The Java programming language is simpler than C++, and as such, your development time could be up to twice as fast when writing in it. Your programs will also require fewer lines of code.

  • Avoid platform dependencies: You can keep your program portable by avoiding the use of libraries written in other languages.

  • Write once, run anywhere: Because applications written in the Java programming language are compiled into machine-independent bytecodes, they run consistently on any Java platform.

  • Distribute software more easily: With Java Web Start software, users will be able to launch your applications with a single click of the mouse. An automatic version check at startup ensures that users are always up to date with the latest version of your software. If an update is available, the Java Web Start software will automatically update their installation.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: What Can Java Technology Do?
Next page: The "Hello World!" Application


Lesson: The "Hello World!" Application (The Java™ Tutorials > Getting Started)

The "Hello World!" Application
"Hello World!" for the NetBeans IDE
"Hello World!" for Microsoft Windows
"Hello World!" for Solaris OS and Linux
Trail: Getting Started
Home Page > Getting Started
« Previous • Trail • Next »
Lesson: The "Hello World!" Application
The sections listed below provide detailed instructions for compiling and running a simple "Hello World!" application. The first section provides information on getting started with the NetBeans IDE, an integrated development environment that greatly simplifies the software development process. The NetBeans IDE runs on all of the platforms listed below. The remaining sections provide platform-specific instructions for getting started without an integrated development environment. If you run into problems, be sure to consult the common problems section; it provides solutions for many issues encountered by new users.

"Hello World!" for the NetBeans IDE

These instructions are for users of the NetBeans IDE. The NetBeans IDE runs on the Java platform, which means that you can use it with any operating system for which there is a JDK 6 available. These operating systems include Microsoft Windows, Solaris OS, Linux, and Mac OS X. We recommend using the NetBeans IDE instead of the command line whenever possible.

"Hello World!" for Microsoft Windows

These command-line instructions are for users of Windows XP Professional, Windows XP Home, Windows Server 2003, Windows 2000 Professional, and Windows Vista.

"Hello World!" for Solaris OS and Linux

These command-line instructions are for users of Solaris OS and Linux.
Common Problems (and Their Solutions)
Consult this page if you have problems compiling or running your application.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: "Hello World!" for the NetBeans IDE


"Hello World!" for the NetBeans IDE (The Java™ Tutorials > Getting Started > The "Hello World!" Application)

Trail: Getting Started
Lesson: The "Hello World!" Application
The "Hello World!" Application
"Hello World!" for the NetBeans IDE
"Hello World!" for Microsoft Windows
"Hello World!" for Solaris OS and Linux
Home Page > Getting Started > The "Hello World!" Application
« Previous • Trail • Next »
"Hello World!" for the NetBeans IDE

It's time to write your first application! These detailed instructions are for users of the NetBeans IDE. The NetBeans IDE runs on the Java platform, which means that you can use it with any operating system for which there is a JDK 6 available. These operating systems include Microsoft Windows, Solaris OS, Linux, and Mac OS X.

  • A Checklist
  • Creating Your First Application
    • Create an IDE Project
    • Add JDK 6 to the Platform List (if necessary)
    • Add Code to the Generated Source File
    • Compile the Source File
    • Run the Program
  • Continuing the Tutorial with the NetBeans IDE

A Checklist

To write your first program, you'll need:
  1. The Java SE Development Kit 6 (JDK 6)

    • For Microsoft Windows, Solaris OS, and Linux: http://java.sun.com/javase/6/download.jsp
    • For Mac OS X: http://connect.apple.com

  2. The NetBeans IDE

    • For all platforms: http://www.netbeans.info/downloads/index.php

Creating Your First Application

Your first application, HelloWorldApp, will simply display the greeting "Hello World!". To create this program, you will:

  • Create an IDE project

    When you create an IDE project, you create an environment in which to build and run your applications. Using IDE projects eliminates configuration issues normally associated with developing on the command line. You can build or run your application by choosing a single menu item within the IDE.

  • Add code to the generated source file

    A source file contains code, written in the Java programming language, that you and other programmers can understand. As part of creating an IDE project, a skeleton source file will be automatically generated. You will then modify the source file to add the "Hello World!" message.

  • Compile the source file into a .class file

    The IDE invokes the Java programming language compiler (javac), which takes your source file and translates its text into instructions that the Java virtual machine can understand. The instructions contained within this file are known as bytecodes.

  • Run the program

    The IDE invokes the Java application launcher tool (java), which uses the Java virtual machine to run your application.

top

Create an IDE Project

To create an IDE project:

  1. Launch the NetBeans IDE.
    • On Microsoft Windows systems, you can use the NetBeans IDE item in the Start menu.
    • On Solaris OS and Linux systems, you execute the IDE launcher script by navigating to the IDE's bin directory and typing ./netbeans.
    • On Mac OS X systems, click the NetBeans IDE application icon.

  2. In the NetBeans IDE, choose File | New Project.

    3. NetBeans IDE with the File | New Project menu item selected.

    NetBeans IDE with the File | New Project menu item selected.

  3. In the New Project wizard, expand the General category and select Java Application as shown in the following figure:

    4. NetBeans IDE, New Project wizard, Choose Project page.

    NetBeans IDE, New Project wizard, Choose Project page.

  4. In the Name and Location page of the wizard, do the following (as shown in the figure below):
    • In the Project Name field, type Hello World App.
    • In the Create Main Class field, type helloworldapp.HelloWorldApp.
    • Leave the Set as Main Project checkbox selected.

    NetBeans IDE, New Project wizard, Name and Location page.

    NetBeans IDE, New Project wizard, Name and Location page.

  5. Click Finish.

The project is created and opened in the IDE. You should see the following components:

  • The Projects window, which contains a tree view of the components of the project, including source files, libraries that your code depends on, and so on.
  • The Source Editor window with a file called HelloWorldApp open.
  • The Navigator window, which you can use to quickly navigate between elements within the selected class.

      • NetBeans IDE with the HelloWorldApp project open.

      NetBeans IDE with the HelloWorldApp project open.

      top

Add JDK 6 to the Platform List (if necessary)

It may be necessary to add JDK 6 to the IDE's list of available platforms. To do this, choose Tools | Java Platform Manager as shown in the following figure:

Selecting the Java Platform Manager from the Tools Menu

Selecting the Java Platform Manager from the Tools Menu

If you don't see JDK 6 (which might appear as 1.6 or 1.6.0) in the list of installed platforms, click "Add Platform", navigate to your JDK 6 install directory, and click "Finish". You should now see this newly added platform:

The Java Platform Manager from the Tools Menu

The Java Platform Manager

To set this JDK as the default for all projects, you can run the IDE with the --jdkhome switch on the command line, or by entering the path to the JDK in the netbeans_j2sdkhome property of your INSTALLATION_DIRECTORY/etc/netbeans.conf file.

To specify this JDK for the current project only, select Hello World App in the Projects pane, choose File | "Hello World App" Properties, click on Libraries, then select JDK 6 under the Java Platform pulldown menu. You should see a screen similar to the following:

The IDE is now configured for JDK 6.

top

Add Code to the Generated Source File

When you created this project, you left the Create Main Class checkbox selected in the New Project wizard. The IDE has therefore created a skeleton class for you. You can add the "Hello World!" message to the skeleton code by replacing the line:

// TODO code application logic here
with the line:
System.out.println("Hello World!"); // Display the string.
Optionally, you can replace these four lines of generated code:
/**
 *
 * @author
 */
with these lines:
/**
 * The HelloWorldApp class implements an application that
 * simply prints "Hello World!" to standard output.
 */
These four lines are a code comment and do not affect how the program runs. Later sections of this tutorial explain the use and format of code comments.
Be Careful When You Type

Type all code, commands, and file names exactly as shown. Both the compiler (javac) and launcher (java) are case-sensitive, so you must capitalize consistently.

HelloWorldApp helloworldapp

Save your changes by choosing File | Save.

The file should look something like the following:

/*
 * HelloWorldApp.java
 *
 * Created on February 5, 2006, 6:43 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package helloworldapp;

/**
 * The HelloWorldApp class implements an application that
 * simply prints "Hello World!" to standard output.
 */
public class HelloWorldApp {

    /** Creates a new instance of HelloWorldApp */
    public HelloWorldApp() {
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        System.out.println("Hello World!"); // Display the string.
    }

}

top

Compile the Source File into a .class File

To compile your source file, choose Build | Build Main Project from the IDE's main menu.

The Output window opens and displays output similar to what you see in the following figure:

Output window showing results of building the HelloWorld project.

Output window showing results of building the HelloWorld project.

If the build output concludes with the statement BUILD SUCCESSFUL, congratulations! You have successfully compiled your program!

If the build output concludes with the statement BUILD FAILED, you probably have a syntax error in your code. Errors are reported in the Output window as hyper-linked text. You double-click such a hyper-link to navigate to the source of an error. You can then fix the error and once again choose Build | Build Main Project.

When you build the project, the bytecode file HelloWorldApp.class is generated. You can see where the new file is generated by opening the Files window and expanding the Hello World App/build/classes/helloworldapp node as shown in the following figure.

Files window, showing the generated .class file.

Files window, showing the generated .class file.

Now that you have built the project, you can run your program.

top

Run the Program

From the IDE's menu bar, choose Run | Run Main Project.

The next figure shows what you should now see.

The program prints

The program prints "Hello World!" to the Output window (along with other output from the build script).

Congratulations! Your program works!

top

Continuing the Tutorial with the NetBeans IDE

The next few pages of the tutorial will explain the code in this simple application. After that, the lessons go deeper into core language features and provide many more examples. Although the rest of the tutorial does not give specific instructions about using the NetBeans IDE, you can easily use the IDE to write and run the sample code. The following are some tips on using the IDE and explanations of some IDE behavior that you are likely to see:

  • Once you have created a project in the IDE, you can add files to the project using the New File wizard. Choose File | New File, and then select a template in the wizard, such as the Empty Java File template.

  • You can compile and run an individual file (as opposed to a whole project) using the IDE's Compile File (F9) and Run File (Shift-F6) commands. If you use the Run Main Project command, the IDE will run the file that the IDE associates as the main class of the main project. Therefore, if you create an additional class in your HelloWorldApp project and then try to run that file with the Run Main Project command, the IDE will run the HelloWorldApp file instead.

  • You might want to create separate IDE projects for sample applications that include more than one source file.

  • As you are typing in the IDE, a code completion box might periodically appear. You can either ignore the code completion box and keep typing, or you can select one of the suggested expressions. If you would prefer not to have the code completion box automatically appear, you can turn off the feature. Choose Tools | Options, click the Editor tab, and clear the Auto Popup Completion Window checkbox.

  • If you try to rename the node for a source file in the Projects window, the IDE prompts you with the Rename dialog box to lead you through the options of renaming the class and the updating of code that refers to that class. Click Next to display the Refactoring window, which contains a tree view of changes to be made. Then click Do Refactoring to apply the changes. This sequence of clicks might seem unnecessary if you have just a single class in your project, but it is very useful when your changes affect other parts of your code in larger projects.

  • For a more thorough guide to the features of the NetBeans IDE, see the NetBeans IDE Docs and Support page or explore the documentation available from the IDE's Help menu.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The "Hello World!" Application
Next page: "Hello World!" for Microsoft Windows


"Hello World!" for Microsoft Windows (The Java™ Tutorials > Getting Started > The "Hello World!" Application)

Trail: Getting Started
Lesson: The "Hello World!" Application
The "Hello World!" Application
"Hello World!" for the NetBeans IDE
"Hello World!" for Microsoft Windows
"Hello World!" for Solaris OS and Linux
Home Page > Getting Started > The "Hello World!" Application
« Previous • Trail • Next »
"Hello World!" for Microsoft Windows

It's time to write your first application! The following instructions are for users of Windows XP Professional, Windows XP Home, Windows Server 2003, Windows 2000 Professional, and Windows Vista. Instructions for other platforms are in "Hello World!" for Solaris OS and Linux and "Hello World!" for the NetBeans IDE.

If you encounter problems with the instructions on this page, consult the Common Problems (and Their Solutions).

  • A Checklist
  • Creating Your First Application
    • Create a Source File
    • Compile the Source File into a .class File
    • Run the Program

A Checklist

To write your first program, you'll need:
  1. The Java SE Development Kit 6 (JDK 6)

    You can download the Windows version now. (Make sure you download the JDK, not the JRE.) Consult the installation instructions.

  2. A text editor

    In this example, we'll use Notepad, a simple editor included with the Windows platforms. You can easily adapt these instructions if you use a different text editor.

These two items are all you'll need to write your first application.

Creating Your First Application

Your first application, HelloWorldApp, will simply display the greeting "Hello world!". To create this program, you will:

  • Create a source file

    A source file contains code, written in the Java programming language, that you and other programmers can understand. You can use any text editor to create and edit source files.

  • Compile the source file into a .class file

    The Java programming language compiler (javac) takes your source file and translates its text into instructions that the Java virtual machine can understand. The instructions contained within this file are known as bytecodes.

  • Run the program

    The Java application launcher tool (java) uses the Java virtual machine to run your application.

top

Create a Source File

To create a source file, you have two options:

  • You can save the file HelloWorldApp.java on your computer and avoid a lot of typing. Then, you can go straight to Compile the Source File into a .class File.

  • Or, you can use the following (longer) instructions.

First, start your editor. You can launch the Notepad editor from the Start menu by selecting Programs > Accessories > Notepad. In a new document, type in the following code:

/**
 * The HelloWorldApp class implements an application that
 * simply prints "Hello World!" to standard output.
 */
class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!"); // Display the string.
    }
}
Be Careful When You Type

Type all code, commands, and file names exactly as shown. Both the compiler (javac) and launcher tool (java) are case-sensitive, so you must capitalize consistently.

HelloWorldApp helloworldapp

Save the code in a file with the name HelloWorldApp.java. To do this in Notepad, first choose the File > Save As menu item. Then, in the Save As dialog box:

  1. Using the Save in combo box, specify the folder (directory) where you'll save your file. In this example, the directory is java on the C drive.
  2. In the File name text field, type "HelloWorldApp.java", including the quotation marks.
  3. From the Save as type combo box, choose Text Documents (*.txt).
  4. In the Encoding combo box, leave the encoding as ANSI.
When you're finished, the dialog box should look like this.

TEXT The Save As dialog, as described in the text.

The Save As dialog just before you click Save.

Now click Save, and exit Notepad.

top

Compile the Source File into a .class File

Bring up a shell, or "command," window. You can do this from the Start menu by choosing Command Prompt (Windows XP), or by choosing Run... and then entering cmd. The shell window should look similar to the following figure.

a window where you can enter DOS commands

A shell window.

The prompt shows your current directory. When you bring up the prompt, your current directory is usually your home directory for Windows XP (as shown in the preceding figure).

To compile your source file, change your current directory to the directory where your file is located. For example, if your source directory is java on the C drive, type the following command at the prompt and press Enter:

cd C:\java

Now the prompt should change to C:\java>.

Note: To change to a directory on a different drive, you must type an extra command: the name of the drive. For example, to change to the java directory on the D drive, you must enter D:, as shown in the following figure.

Changing directory on an alternate drive

Changing directory on an alternate drive.

If you enter dir at the prompt, you should see your source file, as the following figure shows.

Directory listing showing the .java source file.

Directory listing showing the .java source file.

Now you are ready to compile. At the prompt, type the following command and press Enter.

javac HelloWorldApp.java

The compiler has generated a bytecode file, HelloWorldApp.class. At the prompt, type dir to see the new file that was generated, as shown in the following figure.

Directory listing, showing the generated .class file

Directory listing, showing the generated .class file

Now that you have a .class file, you can run your program.

If you encounter problems with the instructions in this step, consult the Common Problems (and Their Solutions).

top

Run the Program

In the same directory, enter the following command at the prompt:
java HelloWorldApp

The next figure shows what you should now see:

The program prints

The program prints "Hello World!" to the screen.

Congratulations! Your program works!

If you encounter problems with the instructions in this step, consult the Common Problems (and Their Solutions).

top

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: "Hello World!" for the NetBeans IDE
Next page: "Hello World!" for Solaris OS and Linux


"Hello World!" for Solaris OS and Linux (The Java™ Tutorials > Getting Started > The "Hello World!" Application)

Trail: Getting Started
Lesson: The "Hello World!" Application
The "Hello World!" Application
"Hello World!" for the NetBeans IDE
"Hello World!" for Microsoft Windows
"Hello World!" for Solaris OS and Linux
Home Page > Getting Started > The "Hello World!" Application
« Previous • Trail • Next »
"Hello World!" for Solaris OS and Linux

It's time to write your first application! These detailed instructions are for users of Solaris OS and Linux. Instructions for other platforms are in "Hello World!" for Microsoft Windows and "Hello World!" for the NetBeans IDE.

If you encounter problems with the instructions on this page, consult the Common Problems (and Their Solutions).

  • A Checklist
  • Creating Your First Application
    • Create a Source File
    • Compile the Source File into a .class File
    • Run the Program

A Checklist

To write your first program, you'll need:
  1. The Java SE Development Kit 6 (JDK 6)

    You can download the Solaris OS or Linux version now. (Make sure you download the JDK, not the JRE.) Consult the installation instructions .

  2. A text editor

    In this example, we'll use Pico, an editor available for many UNIX-based platforms. You can easily adapt these instructions if you use a different text editor, such as vi or emacs.

These two items are all you'll need to write your first application.

Creating Your First Application

Your first application, HelloWorldApp, will simply display the greeting "Hello world!". To create this program, you will:

  • Create a source file

    A source file contains code, written in the Java programming language, that you and other programmers can understand. You can use any text editor to create and edit source files.

  • Compile the source file into a .class file

    The Java programming language compiler (javac) takes your source file and translates its text into instructions that the Java virtual machine can understand. The instructions contained within this .class file are known as bytecodes.

  • Run the program

    The Java application launcher tool (java) uses the Java virtual machine to run your application.

top

Create a Source File

To create a source file, you have two options:

  • You can save the file HelloWorldApp.java on your computer and avoid a lot of typing. Then, you can go straight to Compile the Source File.

  • Or, you can use the following (longer) instructions.

First, open a shell, or "terminal," window.

A new terminal window.

A new terminal window.

When you first bring up the prompt, your current directory will usually be your home directory. You can change your current directory to your home directory at any time by typing cd at the prompt and then pressing Return.

The source files you create should be kept in a separate directory. You can create a directory by using the command mkdir. For example, to create the directory java in your home directory, use the following commands:

cd
mkdir java

To change your current directory to this new directory, you then enter:

cd java

Now you can start creating your source file.

Start the Pico editor by typing pico at the prompt and pressing Return. If the system responds with the message pico: command not found, then Pico is most likely unavailable. Consult your system administrator for more information, or use another editor.

When you start Pico, it'll display a new, blank buffer. This is the area in which you will type your code.

Type the following code into the new buffer:

/**
 * The HelloWorldApp class implements an application that
 * simply prints "Hello World!" to standard output.
 */
class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!"); // Display the string.
    }
}
Be Careful When You Type

Type all code, commands, and file names exactly as shown. Both the compiler (javac) and launcher tool (java) are case-sensitive, so you must capitalize consistently.

HelloWorldApp helloworldapp

Save the code in a file with the name HelloWorldApp.java. In the Pico editor, you do this by typing Ctrl-O and then, at the bottom where you see the prompt File Name to write:, entering the directory in which you wish to create the file, followed by HelloWorldApp.java. For example, if you wish to save HelloWorldApp.java in the directory /home/jdoe/java, then you type /home/jdoe/java/HelloWorldApp.java and press Return.

You can type Ctrl-X to exit Pico.

top

Compile the Source File into a .class File

Bring up another shell window. To compile your source file, change your current directory to the directory where your file is located. For example, if your source directory is /home/jdoe/java, type the following command at the prompt and press Return:

cd /home/jdoe/java

If you enter pwd at the prompt, you should see the current directory, which in this example has been changed to /home/jdoe/java.

If you enter ls at the prompt, you should see your file.

Results of the ls command, showing the .java source file.

Results of the ls command, showing the .java source file.

Now are ready to compile the source file. At the prompt, type the following command and press Return.

javac HelloWorldApp.java

The compiler has generated a bytecode file, HelloWorldApp.class. At the prompt, type ls to see the new file that was generated: the following figure.

Results of the ls command, showing the generated .class file.

Results of the ls command, showing the generated .class file.

Now that you have a .class file, you can run your program.

If you encounter problems with the instructions in this step, consult the Common Problems (and Their Solutions).

top

Run the Program

In the same directory, enter at the prompt:
java HelloWorldApp

The next figure shows what you should now see.

The output prints

The output prints "Hello World!" to the screen.

Congratulations! Your program works!

If you encounter problems with the instructions in this step, consult the Common Problems (and Their Solutions).

top

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: "Hello World!" for Microsoft Windows
Next page: A Closer Look at the "Hello World!" Application


Lesson: A Closer Look at the "Hello World!" Application (The Java™ Tutorials > Getting Started)

A Closer Look at the "Hello World!" Application
Trail: Getting Started
Home Page > Getting Started
« Previous • Trail • Next »
Lesson: A Closer Look at the "Hello World!" Application
Now that you've seen the "Hello World!" application (and perhaps even compiled and run it), you might be wondering how it works. Here again is its code:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * The HelloWorldApp class implements an application that
 * simply prints "Hello World!" to standard output.
 */
class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!"); // Display the string.
    }
}
The "Hello World!" application consists of three primary components: source code comments, the HelloWorldApp class definition, and the main method. The following explanation will provide you with a basic understanding of the code, but the deeper implications will only become apparent after you've finished reading the rest of the tutorial.

Source Code Comments

The following bold text defines the comments of the "Hello World!" application:
/**
 * The HelloWorldApp class implements an application that
 * simply prints "Hello World!" to standard output.
 */
class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!"); // Display the string.
    }
}

Comments are ignored by the compiler but are useful to other programmers. The Java programming language supports three kinds of comments:

/* text */
The compiler ignores everything from /* to */.

/** documentation */
This indicates a documentation comment (doc comment, for short). The compiler ignores this kind of comment, just like it ignores comments that use /* and */. The javadoc tool uses doc comments when preparing automatically generated documentation. For more information on javadoc, see the JavadocTM tool documentation .

// text
The compiler ignores everything from // to the end of the line.

The HelloWorldApp Class Definition

The following bold text begins the class definition block for the "Hello World!" application:
/**
 * The HelloWorldApp class implements an application that
 * simply displays "Hello World!" to the standard output.
 */
class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!"); // Display the string.
    }
}

As shown above, the most basic form of a class definition is:

class name {
    . . .
}

The keyword class begins the class definition for a class named name, and the code for each class appears between the opening and closing curly braces marked in bold above. Chapter 2 provides an overview of classes in general, and Chapter 4 discusses classes in detail. For now it is enough to know that every application begins with a class definition.

The main Method

The following bold text begins the definition of the main method:
/**
 * The HelloWorldApp class implements an application that
 * simply displays "Hello World!" to the standard output.
 */
class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!"); //Display the string.
    }
}

In the Java programming language, every application must contain a main method whose signature is:

public static void main(String[] args)
The modifiers public and static can be written in either order (public static or static public), but the convention is to use public static as shown above. You can name the argument anything you want, but most programmers choose "args" or "argv".

The main method is similar to the main function in C and C++; it's the entry point for your application and will subsequently invoke all the other methods required by your program.

The main method accepts a single argument: an array of elements of type String.

public static void main(String[] args)
This array is the mechanism through which the runtime system passes information to your application. Each string in the array is called a command-line argument. Command-line arguments let users affect the operation of the application without recompiling it. For example, a sorting program might allow the user to specify that the data be sorted in descending order with this command-line argument:
-descending

The "Hello World!" application ignores its command-line arguments, but you should be aware of the fact that such arguments do exist.

Finally, the line:

System.out.println("Hello World!");
uses the System class from the core library to print the "Hello World!" message to standard output. Portions of this library (also known as the "Application Programming Interface", or "API") will be discussed throughout the remainder of the tutorial.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Questions and Exercises: Getting Started


Questions and Exercises: Getting Started (The Java™ Tutorials > Getting Started)

Trail: Getting Started
Home Page > Getting Started
« Previous • Trail • Next »
Questions and Exercises: Getting Started

Questions

1. When you compile a program written in the Java programming language, the compiler converts the human-readable source file into platform-independent code that a Java Virtual Machine can understand. What is this platform-independent code called?

2. Which of the following is not a valid comment:

a. /** comment */
b. /* comment */
c. /* comment
d. // comment
3. What's the first thing you should check if you see the following error at runtime:
Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorldApp.java.

4. What is the correct signature of the main method?

5. When declaring the main method, which modifier must come first, public or static?

6. What parameters does the main method define?

Exercises

1. Change the HelloWorldApp.java program so that it displays Hola Mundo! instead of Hello World!.

2. You can find a slightly modified version of HelloWorldApp here: HelloWorldApp2.java
The program has an error. Fix the error so that the program successfully compiles and runs. What was the error?

Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: A Closer Look at the "Hello World!" Application
Next page: Common Problems (and Their Solutions)


Lesson: Common Problems (and Their Solutions) (The Java™ Tutorials > Getting Started)

Trail: Getting Started
Home Page > Getting Started
« Previous • Trail • Next »
Lesson: Common Problems (and Their Solutions)

Compiler Problems
Common Error Messages on Microsoft Windows Systems

'javac' is not recognized as an internal or external command, operable program or batch file

If you receive this error, Windows cannot find the compiler (javac).

Here's one way to tell Windows where to find javac. Suppose you installed the JDK in C:\jdk6. At the prompt you would type the following command and press Enter:

C:\jdk6\bin\javac HelloWorldApp.java
If you choose this option, you'll have to precede your javac and java commands with C:\jdk6\bin\ each time you compile or run a program. To avoid this extra typing, consult the section Update the PATH variable in the JDK 6 installation instructions.

Class names, 'HelloWorldApp', are only accepted if annotation processing is explicitly requested

If you receive this error, you forgot to include the .java suffix when compiling the program. Remember, the command is javac HelloWorldApp.java not javac HelloWorldApp.

Common Error Messages on UNIX Systems

javac: Command not found

If you receive this error, UNIX cannot find the compiler, javac.

Here's one way to tell UNIX where to find javac. Suppose you installed the JDK in /usr/local/jdk6. At the prompt you would type the following command and press Return:

/usr/local/jdk6/javac HelloWorldApp.java
Note: If you choose this option, each time you compile or run a program, you'll have to precede your javac and java commands with /usr/local/jdk6/. To avoid this extra typing, you could add this information to your PATH variable. The steps for doing so will vary depending on which shell you are currently running.

Class names, 'HelloWorldApp', are only accepted if annotation processing is explicitly requested

If you receive this error, you forgot to include the .java suffix when compiling the program. Remember, the command is javac HelloWorldApp.java not javac HelloWorldApp.

Syntax Errors (All Platforms)

If you mistype part of a program, the compiler may issue a syntax error. The message usually displays the type of the error, the line number where the error was detected, the code on that line, and the position of the error within the code. Here's an error caused by omitting a semicolon (;) at the end of a statement:
testing.java:14: `;' expected.
System.out.println("Input has " + count + " chars.")
                                                     ^
1 error
Sometimes the compiler can't guess your intent and prints a confusing error message or multiple error messages if the error cascades over several lines. For example, the following code snippet omits a semicolon (;) from the bold line:
while (System.in.read() != -1)
    count++
System.out.println("Input has " + count + " chars.");
When processing this code, the compiler issues two error messages:
testing.java:13: Invalid type expression.
        count++
                 ^
testing.java:14: Invalid declaration.
    System.out.println("Input has " + count + " chars.");
                      ^
2 errors
The compiler issues two error messages because after it processes count++, the compiler's state indicates that it's in the middle of an expression. Without the semicolon, the compiler has no way of knowing that the statement is complete.

If you see any compiler errors, then your program did not successfully compile, and the compiler did not create a .class file. Carefully verify the program, fix any errors that you detect, and try again.

Semantic Errors

In addition to verifying that your program is syntactically correct, the compiler checks for other basic correctness. For example, the compiler warns you each time you use a variable that has not been initialized:
testing.java:13: Variable count may not have been initialized.
        count++
        ^
testing.java:14: Variable count may not have been initialized.
    System.out.println("Input has " + count + " chars.");
                                       ^
2 errors
Again, your program did not successfully compile, and the compiler did not create a .class file. Fix the error and try again.

Runtime Problems

Error Messages on Microsoft Windows Systems

Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorldApp

If you receive this error, java cannot find your bytecode file, HelloWorldApp.class.

One of the places java tries to find your .class file is your current directory. So if your .class file is in C:\java, you should change your current directory to that. To change your directory, type the following command at the prompt and press Enter:

cd c:\java

The prompt should change to C:\java>. If you enter dir at the prompt, you should see your .java and .class files. Now enter java HelloWorldApp again.

If you still have problems, you might have to change your CLASSPATH variable. To see if this is necessary, try clobbering the classpath with the following command.

set CLASSPATH=

Now enter java HelloWorldApp again. If the program works now, you'll have to change your CLASSPATH variable. To set this variable, consult the Update the PATH variable section in the JDK 6 installation instructions. The CLASSPATH variable is set in the same manner.

Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorldApp/class

A common mistake made by beginner programmers is to try and run the java launcher on the .class file that was created by the compiler. For example, you'll get this error if you try to run your program with java HelloWorldApp.class instead of java HelloWorldApp. Remember, the argument is the name of the class that you want to use, not the filename.

Exception in thread "main" java.lang.NoSuchMethodError: main

The Java VM requires that the class you execute with it have a main method at which to begin execution of your application. A Closer Look at the "Hello World!" Application discusses the main method in detail.

Error Messages on UNIX Systems

Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorldApp

If you receive this error, java cannot find your bytecode file, HelloWorldApp.class.

One of the places java tries to find your bytecode file is your current directory. So, for example, if your bytecode file is in /home/jdoe/java, you should change your current directory to that. To change your directory, type the following command at the prompt and press Return:

cd /home/jdoe/java

If you enter pwd at the prompt, you should see /home/jdoe/java. If you enter ls at the prompt, you should see your .java and .class files. Now enter java HelloWorldApp again.

If you still have problems, you might have to change your CLASSPATH environment variable. To see if this is necessary, try clobbering the classpath with the following command.

unset CLASSPATH

Now enter java HelloWorldApp again. If the program works now, you'll have to change your CLASSPATH variable in the same manner as the PATH variable above.

Exception in thread "main" java.lang.NoClassDefFoundError: HelloWorldApp/class

A common mistake made by beginner programmers is to try and run the java launcher on the .class file that was created by the compiler. For example, you'll get this error if you try to run your program with java HelloWorldApp.class instead of java HelloWorldApp. Remember, the argument is the name of the class that you want to use, not the filename.

Exception in thread "main" java.lang.NoSuchMethodError: main

The Java VM requires that the class you execute with it have a main method at which to begin execution of your application. A Closer Look at the "Hello World!" Application discusses the main method in detail.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: End of Trail


Trail: Learning the Java Language (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Learning the Java Language
This trail covers the fundamentals of programming in the Java programming language.

Object-Oriented Programming Concepts teaches you the core concepts behind object-oriented programming: objects, messages, classes, and inheritance. This lesson ends by showing you how these concepts translate into code. Feel free to skip this lesson if you are already familiar with object-oriented programming.

Language Basics describes the traditional features of the language, including variables, arrays, data types, operators, and control flow.

Classes and Objects describes how to write the classes from which objects are created, and how to create and use the objects.

Interfaces and Inheritance describes interfaces—what they are, why you would want to write one, and how to write one. This section also describes the way in which you can derive one class from another. That is, how a subclass can inherit fields and methods from a superclass. You will learn that all classes are derived from the Object class, and how to modify the methods that a subclass inherits from superclasses.

Numbers and Strings This lesson describes how to use Number and String objects The lesson also shows you how to format data for output.

Generics are a powerful feature of the Java programming language. They improve the type safety of your code, making more of your bugs detectable at compile time.

Packages are a feature of the Java programming language that help you to organize and structure your classes and their relationships to one another.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Object-Oriented Programming Concepts


Lesson: Object-Oriented Programming Concepts (The Java™ Tutorials > Learning the Java Language)

Object-Oriented Programming Concepts
What Is an Object?
What Is a Class?
What Is Inheritance?
What Is an Interface?
What Is a Package?
Questions and Exercises
Trail: Learning the Java Language
Home Page > Learning the Java Language
« Previous • Trail • Next »
Lesson: Object-Oriented Programming Concepts
If you've never used an object-oriented programming language before, you'll need to learn a few basic concepts before you can begin writing any code. This lesson will introduce you to objects, classes, inheritance, interfaces, and packages. Each discussion focuses on how these concepts relate to the real world, while simultaneously providing an introduction to the syntax of the Java programming language.

What Is an Object?

An object is a software bundle of related state and behavior. Software objects are often used to model the real-world objects that you find in everyday life. This lesson explains how state and behavior are represented within an object, introduces the concept of data encapsulation, and explains the benefits of designing your software in this manner.

What Is a Class?

A class is a blueprint or prototype from which objects are created. This section defines a class that models the state and behavior of a real-world object. It intentionally focuses on the basics, showing how even a simple class can cleanly model state and behavior.

What Is Inheritance?

Inheritance provides a powerful and natural mechanism for organizing and structuring your software. This section explains how classes inherit state and behavior from their superclasses, and explains how to derive one class from another using the simple syntax provided by the Java programming language.

What Is an Interface?

An interface is a contract between a class and the outside world. When a class implements an interface, it promises to provide the behavior published by that interface. This section defines a simple interface and explains the necessary changes for any class that implements it.

What Is a Package?

A package is a namespace for organizing classes and interfaces in a logical manner. Placing your code into packages makes large software projects easier to manage. This section explains why this is useful, and introduces you to the Application Programming Interface (API) provided by the Java platform.

Questions and Exercises: Object-Oriented Programming Concepts

Use the questions and exercises presented in this section to test your understanding of objects, classes, inheritance, interfaces, and packages.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: What Is an Object?


What Is an Object? (The Java™ Tutorials > Learning the Java Language > Object-Oriented Programming Concepts)

Trail: Learning the Java Language
Lesson: Object-Oriented Programming Concepts
Object-Oriented Programming Concepts
What Is an Object?
What Is a Class?
What Is Inheritance?
What Is an Interface?
What Is a Package?
Questions and Exercises
Home Page > Learning the Java Language > Object-Oriented Programming Concepts
« Previous • Trail • Next »
What Is an Object?
Objects are key to understanding object-oriented technology. Look around right now and you'll find many examples of real-world objects: your dog, your desk, your television set, your bicycle.

Real-world objects share two characteristics: They all have state and behavior. Dogs have state (name, color, breed, hungry) and behavior (barking, fetching, wagging tail). Bicycles also have state (current gear, current pedal cadence, current speed) and behavior (changing gear, changing pedal cadence, applying brakes). Identifying the state and behavior for real-world objects is a great way to begin thinking in terms of object-oriented programming.

Take a minute right now to observe the real-world objects that are in your immediate area. For each object that you see, ask yourself two questions: "What possible states can this object be in?" and "What possible behavior can this object perform?". Make sure to write down your observations. As you do, you'll notice that real-world objects vary in complexity; your desktop lamp may have only two possible states (on and off) and two possible behaviors (turn on, turn off), but your desktop radio might have additional states (on, off, current volume, current station) and behavior (turn on, turn off, increase volume, decrease volume, seek, scan, and tune). You may also notice that some objects, in turn, will also contain other objects. These real-world observations all translate into the world of object-oriented programming.

A circle with an inner circle filled with items, surrounded by gray wedges representing methods that allow access to the inner circle.

A software object.

Software objects are conceptually similar to real-world objects: they too consist of state and related behavior. An object stores its state in fields (variables in some programming languages) and exposes its behavior through methods (functions in some programming languages). Methods operate on an object's internal state and serve as the primary mechanism for object-to-object communication. Hiding internal state and requiring all interaction to be performed through an object's methods is known as data encapsulation — a fundamental principle of object-oriented programming.

Consider a bicycle, for example:

A picture of an object, with bibycle methods and instance variables.

A bicycle modeled as a software object.

By attributing state (current speed, current pedal cadence, and current gear) and providing methods for changing that state, the object remains in control of how the outside world is allowed to use it. For example, if the bicycle only has 6 gears, a method to change gears could reject any value that is less than 1 or greater than 6.

Bundling code into individual software objects provides a number of benefits, including:

  1. Modularity: The source code for an object can be written and maintained independently of the source code for other objects. Once created, an object can be easily passed around inside the system.

  2. Information-hiding: By interacting only with an object's methods, the details of its internal implementation remain hidden from the outside world.

  3. Code re-use: If an object already exists (perhaps written by another software developer), you can use that object in your program. This allows specialists to implement/test/debug complex, task-specific objects, which you can then trust to run in your own code.

  4. Pluggability and debugging ease: If a particular object turns out to be problematic, you can simply remove it from your application and plug in a different object as its replacement. This is analogous to fixing mechanical problems in the real world. If a bolt breaks, you replace it, not the entire machine.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Object-Oriented Programming Concepts
Next page: What Is a Class?


What Is a Class? (The Java™ Tutorials > Learning the Java Language > Object-Oriented Programming Concepts)

Trail: Learning the Java Language
Lesson: Object-Oriented Programming Concepts
Object-Oriented Programming Concepts
What Is an Object?
What Is a Class?
What Is Inheritance?
What Is an Interface?
What Is a Package?
Questions and Exercises
Home Page > Learning the Java Language > Object-Oriented Programming Concepts
« Previous • Trail • Next »
What Is a Class?
In the real world, you'll often find many individual objects all of the same kind. There may be thousands of other bicycles in existence, all of the same make and model. Each bicycle was built from the same set of blueprints and therefore contains the same components. In object-oriented terms, we say that your bicycle is an instance of the class of objects known as bicycles. A class is the blueprint from which individual objects are created.

The following Bicycle class is one possible implementation of a bicycle:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class Bicycle {

       int cadence = 0;
       int speed = 0;
       int gear = 1;

       void changeCadence(int newValue) {
            cadence = newValue;
       }

       void changeGear(int newValue) {
            gear = newValue;
       }

       void speedUp(int increment) {
            speed = speed + increment;
       }

       void applyBrakes(int decrement) {
            speed = speed - decrement;
       }

       void printStates() {
            System.out.println("cadence:"+cadence+" speed:"+speed+" gear:"+gear);
       }
}
The syntax of the Java programming language will look new to you, but the design of this class is based on the previous discussion of bicycle objects. The fields cadence, speed, and gear represent the object's state, and the methods (changeCadence, changeGear, speedUp etc.) define its interaction with the outside world.

You may have noticed that the Bicycle class does not contain a main method. That's because it's not a complete application; it's just the blueprint for bicycles that might be used in an application. The responsibility of creating and using new Bicycle objects belongs to some other class in your application.

Here's a BicycleDemo class that creates two separate Bicycle objects and invokes their methods:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class BicycleDemo {
     public static void main(String[] args) {

          // Create two different Bicycle objects
          Bicycle bike1 = new Bicycle();
          Bicycle bike2 = new Bicycle();

          // Invoke methods on those objects
          bike1.changeCadence(50);
          bike1.speedUp(10);
          bike1.changeGear(2);
          bike1.printStates();

          bike2.changeCadence(50);
          bike2.speedUp(10);
          bike2.changeGear(2);
          bike2.changeCadence(40);
          bike2.speedUp(10);
          bike2.changeGear(3);
          bike2.printStates();
     }
}
The output of this test prints the ending pedal cadence, speed, and gear for the two bicycles:
cadence:50 speed:10 gear:2
cadence:40 speed:20 gear:3
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: What Is an Object?
Next page: What Is Inheritance?


What Is Inheritance? (The Java™ Tutorials > Learning the Java Language > Object-Oriented Programming Concepts)

Trail: Learning the Java Language
Lesson: Object-Oriented Programming Concepts
Object-Oriented Programming Concepts
What Is an Object?
What Is a Class?
What Is Inheritance?
What Is an Interface?
What Is a Package?
Questions and Exercises
Home Page > Learning the Java Language > Object-Oriented Programming Concepts
« Previous • Trail • Next »
What Is Inheritance?
Different kinds of objects often have a certain amount in common with each other. Mountain bikes, road bikes, and tandem bikes, for example, all share the characteristics of bicycles (current speed, current pedal cadence, current gear). Yet each also defines additional features that make them different: tandem bicycles have two seats and two sets of handlebars; road bikes have drop handlebars; some mountain bikes have an additional chain ring, giving them a lower gear ratio.

Object-oriented programming allows classes to inherit commonly used state and behavior from other classes. In this example, Bicycle now becomes the superclass of MountainBike, RoadBike, and TandemBike. In the Java programming language, each class is allowed to have one direct superclass, and each superclass has the potential for an unlimited number of subclasses:

A diagram of classes in a hierarchy.

A hierarchy of bicycle classes.

The syntax for creating a subclass is simple. At the beginning of your class declaration, use the extends keyword, followed by the name of the class to inherit from:

class MountainBike extends Bicycle {

     // new fields and methods defining a mountain bike would go here

}
This gives MountainBike all the same fields and methods as Bicycle, yet allows its code to focus exclusively on the features that make it unique. This makes code for your subclasses easy to read. However, you must take care to properly document the state and behavior that each superclass defines, since that code will not appear in the source file of each subclass.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: What Is a Class?
Next page: What Is an Interface?


What Is an Interface? (The Java™ Tutorials > Learning the Java Language > Object-Oriented Programming Concepts)

Trail: Learning the Java Language
Lesson: Object-Oriented Programming Concepts
Object-Oriented Programming Concepts
What Is an Object?
What Is a Class?
What Is Inheritance?
What Is an Interface?
What Is a Package?
Questions and Exercises
Home Page > Learning the Java Language > Object-Oriented Programming Concepts
« Previous • Trail • Next »
What Is an Interface?
As you've already learned, objects define their interaction with the outside world through the methods that they expose. Methods form the object's interface with the outside world; the buttons on the front of your television set, for example, are the interface between you and the electrical wiring on the other side of its plastic casing. You press the "power" button to turn the television on and off.

In its most common form, an interface is a group of related methods with empty bodies. A bicycle's behavior, if specified as an interface, might appear as follows:

interface Bicycle {

       void changeCadence(int newValue);

       void changeGear(int newValue);

       void speedUp(int increment);

       void applyBrakes(int decrement);
}
To implement this interface, the name of your class would change (to ACMEBicycle, for example), and you'd use the implements keyword in the class declaration:
class ACMEBicycle implements Bicycle {

   // remainder of this class implemented as before

}
Implementing an interface allows a class to become more formal about the behavior it promises to provide. Interfaces form a contract between the class and the outside world, and this contract is enforced at build time by the compiler. If your class claims to implement an interface, all methods defined by that interface must appear in its source code before the class will successfully compile.
Note: To actually compile the ACMEBicycle class, you'll need to add the public keyword to the beginning of the implemented interface methods. You'll learn the reasons for this later in the lessons on Classes and Objects and Interfaces and Inheritance.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: What Is Inheritance?
Next page: What Is a Package?


What Is a Package? (The Java™ Tutorials > Learning the Java Language > Object-Oriented Programming Concepts)

Trail: Learning the Java Language
Lesson: Object-Oriented Programming Concepts
Object-Oriented Programming Concepts
What Is an Object?
What Is a Class?
What Is Inheritance?
What Is an Interface?
What Is a Package?
Questions and Exercises
Home Page > Learning the Java Language > Object-Oriented Programming Concepts
« Previous • Trail • Next »
What Is a Package?
A package is a namespace that organizes a set of related classes and interfaces. Conceptually you can think of packages as being similar to different folders on your computer. You might keep HTML pages in one folder, images in another, and scripts or applications in yet another. Because software written in the Java programming language can be composed of hundreds or thousands of individual classes, it makes sense to keep things organized by placing related classes and interfaces into packages.

The Java platform provides an enormous class library (a set of packages) suitable for use in your own applications. This library is known as the "Application Programming Interface", or "API" for short. Its packages represent the tasks most commonly associated with general-purpose programming. For example, a String object contains state and behavior for character strings; a File object allows a programmer to easily create, delete, inspect, compare, or modify a file on the filesystem; a Socket object allows for the creation and use of network sockets; various GUI objects control buttons and checkboxes and anything else related to graphical user interfaces. There are literally thousands of classes to choose from. This allows you, the programmer, to focus on the design of your particular application, rather than the infrastructure required to make it work.

The Java Platform API Specification contains the complete listing for all packages, interfaces, classes, fields, and methods supplied by the Java Platform 6, Standard Edition. Load the page in your browser and bookmark it. As a programmer, it will become your single most important piece of reference documentation.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: What Is an Interface?
Next page: Questions and Exercises: Object-Oriented Programming Concepts


Questions and Exercises: Object-Oriented Programming Concepts (The Java™ Tutorials > Learning the Java Language > Object-Oriented Programming Concepts)

Trail: Learning the Java Language
Lesson: Object-Oriented Programming Concepts
Object-Oriented Programming Concepts
What Is an Object?
What Is a Class?
What Is Inheritance?
What Is an Interface?
What Is a Package?
Questions and Exercises
Home Page > Learning the Java Language > Object-Oriented Programming Concepts
« Previous • Trail • Next »
Questions and Exercises: Object-Oriented Programming Concepts

Questions

  1. Real-world objects contain ___ and ___.

  2. A software object's state is stored in ___.

  3. A software object's behavior is exposed through ___.

  4. Hiding internal data from the outside world, and accessing it only through publicly exposed methods is known as data ___.

  5. A blueprint for a software object is called a ___.

  6. Common behavior can be defined in a ___ and inherited into a ___ using the ___ keyword.

  7. A collection of methods with no implementation is called an ___.

  8. A namespace that organizes classes and interfaces by functionality is called a ___.

  9. The term API stands for ___?

Exercises

  1. Create new classes for each real-world object that you observed at the beginning of this trail. Refer to the Bicycle class if you forget the required syntax.

  2. For each new class that you've created above, create an interface that defines its behavior, then require your class to implement it. Omit one or two methods and try compiling. What does the error look like?
Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: What Is a Package?
Next page: Language Basics


Lesson: Language Basics (The Java™ Tutorials > Learning the Java Language)

Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Trail: Learning the Java Language
Home Page > Learning the Java Language
« Previous • Trail • Next »
Lesson: Language Basics

Variables

You've already learned that objects store their state in fields. However, the Java programming language also uses the term "variable" as well. This section discusses this relationship, plus variable naming rules and conventions, basic data types (primitive types, character strings, and arrays), default values, and literals.

Operators

This section describes the operators of the Java programming language. It presents the most commonly-used operators first, and the less commonly-used operators last. Each discussion includes code samples that you can compile and run.

Expressions, Statements, and Blocks

Operators may be used in building expressions, which compute values; expressions are the core components of statements; statements may be grouped into blocks. This section discusses expressions, statements, and blocks using example code that you've already seen.

Control Flow Statements

This section describes the control flow statements supported by the Java programming language. It covers the decisions-making, looping, and branching statements that enable your programs to conditionally execute particular blocks of code.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Variables


Variables (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Variables
As you learned in the previous lesson, an object stores its state in fields.
int cadence = 0;
int speed = 0;
int gear = 1;

The What Is an Object? discussion introduced you to fields, but you probably have still a few questions, such as: What are the rules and conventions for naming a field? Besides int, what other data types are there? Do fields have to be initialized when they are declared? Are fields assigned a default value if they are not explicitly initialized? We'll explore the answers to such questions in this lesson, but before we do, there are a few technical distinctions you must first become aware of. In the Java programming language, the terms "field" and "variable" are both used; this is a common source of confusion among new developers, since both often seem to refer to the same thing.

The Java programming language defines the following kinds of variables:

  • Instance Variables (Non-Static Fields) Technically speaking, objects store their individual states in "non-static fields", that is, fields declared without the static keyword. Non-static fields are also known as instance variables because their values are unique to each instance of a class (to each object, in other words); the currentSpeed of one bicycle is independent from the currentSpeed of another.

  • Class Variables (Static Fields) A class variable is any field declared with the static modifier; this tells the compiler that there is exactly one copy of this variable in existence, regardless of how many times the class has been instantiated. A field defining the number of gears for a particular kind of bicycle could be marked as static since conceptually the same number of gears will apply to all instances. The code static int numGears = 6; would create such a static field. Additionally, the keyword final could be added to indicate that the number of gears will never change.

  • Local Variables Similar to how an object stores its state in fields, a method will often store its temporary state in local variables. The syntax for declaring a local variable is similar to declaring a field (for example, int count = 0;). There is no special keyword designating a variable as local; that determination comes entirely from the location in which the variable is declared — which is between the opening and closing braces of a method. As such, local variables are only visible to the methods in which they are declared; they are not accessible from the rest of the class.

  • Parameters You've already seen examples of parameters, both in the Bicycle class and in the main method of the "Hello World!" application. Recall that the signature for the main method is public static void main(String[] args). Here, the args variable is the parameter to this method. The important thing to remember is that parameters are always classified as "variables" not "fields". This applies to other parameter-accepting constructs as well (such as constructors and exception handlers) that you'll learn about later in the tutorial.
Having said that, the remainder of this tutorial uses the following general guidelines when discussing fields and variables. If we are talking about "fields in general" (excluding local variables and parameters), we may simply say "fields". If the discussion applies to "all of the above", we may simply say "variables". If the context calls for a distinction, we will use specific terms (static field, local variables, etc.) as appropriate. You may also occasionally see the term "member" used as well. A type's fields, methods, and nested types are collectively called its members.

Naming

Every programming language has its own set of rules and conventions for the kinds of names that you're allowed to use, and the Java programming language is no different. The rules and conventions for naming your variables can be summarized as follows:

  • Variable names are case-sensitive. A variable's name can be any legal identifier — an unlimited-length sequence of Unicode letters and digits, beginning with a letter, the dollar sign "$", or the underscore character "_". The convention, however, is to always begin your variable names with a letter, not "$" or "_". Additionally, the dollar sign character, by convention, is never used at all. You may find some situations where auto-generated names will contain the dollar sign, but your variable names should always avoid using it. A similar convention exists for the underscore character; while it's technically legal to begin your variable's name with "_", this practice is discouraged. White space is not permitted.

  • Subsequent characters may be letters, digits, dollar signs, or underscore characters. Conventions (and common sense) apply to this rule as well. When choosing a name for your variables, use full words instead of cryptic abbreviations. Doing so will make your code easier to read and understand. In many cases it will also make your code self-documenting; fields named cadence, speed, and gear, for example, are much more intuitive than abbreviated versions, such as s, c, and g. Also keep in mind that the name you choose must not be a keyword or reserved word.

  • If the name you choose consists of only one word, spell that word in all lowercase letters. If it consists of more than one word, capitalize the first letter of each subsequent word. The names gearRatio and currentGear are prime examples of this convention. If your variable stores a constant value, such as static final int NUM_GEARS = 6, the convention changes slightly, capitalizing every letter and separating subsequent words with the underscore character. By convention, the underscore character is never used elsewhere.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Language Basics
Next page: Primitive Data Types


Primitive Data Types (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Section: Variables
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Primitive Data Types
The Java programming language is strongly-typed, which means that all variables must first be declared before they can be used. This involves stating the variable's type and name, as you've already seen:

int gear = 1;
Doing so tells your program that a field named "gear" exists, holds numerical data, and has an initial value of "1". A variable's data type determines the values it may contain, plus the operations that may be performed on it. In addition to int, the Java programming language supports seven other primitive data types. A primitive type is predefined by the language and is named by a reserved keyword. Primitive values do not share state with other primitive values. The eight primitive data types supported by the Java programming language are:
  • byte: The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.

  • short: The short data type is a 16-bit signed two's complement integer. It has a minimum value of -32,768 and a maximum value of 32,767 (inclusive). As with byte, the same guidelines apply: you can use a short to save memory in large arrays, in situations where the memory savings actually matters.

  • int: The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive). For integral values, this data type is generally the default choice unless there is a reason (like the above) to choose something else. This data type will most likely be large enough for the numbers your program will use, but if you need a wider range of values, use long instead.

  • long: The long data type is a 64-bit signed two's complement integer. It has a minimum value of -9,223,372,036,854,775,808 and a maximum value of 9,223,372,036,854,775,807 (inclusive). Use this data type when you need a range of values wider than those provided by int.

  • float: The float data type is a single-precision 32-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in section 4.2.3 of the Java Language Specification. As with the recommendations for byte and short, use a float (instead of double) if you need to save memory in large arrays of floating point numbers. This data type should never be used for precise values, such as currency. For that, you will need to use the java.math.BigDecimal class instead. Numbers and Strings covers BigDecimal and other useful classes provided by the Java platform.

  • double: The double data type is a double-precision 64-bit IEEE 754 floating point. Its range of values is beyond the scope of this discussion, but is specified in section 4.2.3 of the Java Language Specification. For decimal values, this data type is generally the default choice. As mentioned above, this data type should never be used for precise values, such as currency.

  • boolean: The boolean data type has only two possible values: true and false. Use this data type for simple flags that track true/false conditions. This data type represents one bit of information, but its "size" isn't something that's precisely defined.

  • char: The char data type is a single 16-bit Unicode character. It has a minimum value of '\u0000' (or 0) and a maximum value of '\uffff' (or 65,535 inclusive).
In addition to the eight primitive data types listed above, the Java programming language also provides special support for character strings via the java.lang.String class. Enclosing your character string within double quotes will automatically create a new String object; for example, String s = "this is a string";. String objects are immutable, which means that once created, their values cannot be changed. The String class is not technically a primitive data type, but considering the special support given to it by the language, you'll probably tend to think of it as such. You'll learn more about the String class in Simple Data Objects

Default Values

It's not always necessary to assign a value when a field is declared. Fields that are declared but not initialized will be set to a reasonable default by the compiler. Generally speaking, this default will be zero or null, depending on the data type. Relying on such default values, however, is generally considered bad programming style.

The following chart summarizes the default values for the above data types.

Data Type | Default Value (for fields)
byte | 0
short | 0
int | 0
long | 0L
float | 0.0f
double | 0.0d
char | '\u0000'
String (or any object) | null
boolean | false

Local variables are slightly different; the compiler never assigns a default value to an uninitialized local variable. If you cannot initialize your local variable where it is declared, make sure to assign it a value before you attempt to use it. Accessing an uninitialized local variable will result in a compile-time error.

Literals

You may have noticed that the new keyword isn't used when initializing a variable of a primitive type. Primitive types are special data types built into the language; they are not objects created from a class. A literal is the source code representation of a fixed value; literals are represented directly in your code without requiring computation. As shown below, it's possible to assign a literal to a variable of a primitive type:

     boolean result = true;
     char capitalC = 'C';
     byte b = 100;
     short s = 10000;
     int i = 100000;
The integral types (byte, short, int, and long) can be expressed using decimal, octal, or hexadecimal number systems. Decimal is the number system you already use every day; it's based on 10 digits, numbered 0 through 9. The octal number system is base 8, consisting of the digits 0 through 7. The hexadecimal system is base 16, whose digits are the numbers 0 through 9 and the letters A through F. For general-purpose programming, the decimal system is likely to be the only number system you'll ever use. However, if you need octal or hexadecimal, the following example shows the correct syntax. The prefix 0 indicates octal, whereas 0x indicates hexadecimal.

     int decVal = 26; 	// The number 26, in decimal
     int octVal = 032; 	// The number 26, in octal
     int hexVal = 0x1a;	// The number 26, in hexadecimal

The floating point types (float and double) can also be expressed using E or e (for scientific notation), F or f (32-bit float literal) and D or d (64-bit double literal; this is the default and by convention is omitted).

     double d1 = 123.4;
     double d2 = 1.234e2; // same value as d1, but in scientific notation
     float f1  = 123.4f;

Literals of types char and String may contain any Unicode (UTF-16) characters. If your editor and file system allow it, you can use such characters directly in your code. If not, you can use a "Unicode escape" such as '\u0108' (capital C with circumflex), or "S\u00ED se\u00F1or" (Sí Señor in Spanish). Always use 'single quotes' for char literals and "double quotes" for String literals. Unicode escape sequences may be used elsewhere in a program (such as in field names, for example), not just in char or String literals.

The Java programming language also supports a few special escape sequences for char and String literals: \b (backspace), \t (tab), \n (line feed), \f (form feed), \r (carriage return), \" (double quote), \' (single quote), and \\ (backslash).

There's also a special null literal that can be used as a value for any reference type. null may be assigned to any variable, except variables of primitive types. There's little you can do with a null value beyond testing for its presence. Therefore, null is often used in programs as a marker to indicate that some object is unavailable.

Finally, there's also a special kind of literal called a class literal, formed by taking a type name and appending ".class"; for example, String.class. This refers to the object (of type Class) that represents the type itself.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Variables
Next page: Arrays


Arrays (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Section: Variables
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Arrays
An array is a container object that holds a fixed number of values of a single type. The length of an array is established when the array is created. After creation, its length is fixed. You've seen an example of arrays already, in the main method of the "Hello World!" application. This section discusses arrays in greater detail.

Illustration of an array as 10 boxes numbered 0 through 9; an index of 0 indicates the first element in the array

An array of ten elements

Each item in an array is called an element, and each element is accessed by its numerical index. As shown in the above illustration, numbering begins with 0. The 9th element, for example, would therefore be accessed at index 8.

The following program, ArrayDemo, creates an array of integers, puts some values in it, and prints each value to standard output.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class ArrayDemo {
     public static void main(String[] args) {
          int[] anArray;              // declares an array of integers

          anArray = new int[10];      // allocates memory for 10 integers

          anArray[0] = 100; // initialize first element
          anArray[1] = 200; // initialize second element
          anArray[2] = 300; // etc.
          anArray[3] = 400;
          anArray[4] = 500;
          anArray[5] = 600;
          anArray[6] = 700;
          anArray[7] = 800;
          anArray[8] = 900;
          anArray[9] = 1000;

          System.out.println("Element at index 0: " + anArray[0]);
          System.out.println("Element at index 1: " + anArray[1]);
          System.out.println("Element at index 2: " + anArray[2]);
          System.out.println("Element at index 3: " + anArray[3]);
          System.out.println("Element at index 4: " + anArray[4]);
          System.out.println("Element at index 5: " + anArray[5]);
          System.out.println("Element at index 6: " + anArray[6]);
          System.out.println("Element at index 7: " + anArray[7]);
          System.out.println("Element at index 8: " + anArray[8]);
          System.out.println("Element at index 9: " + anArray[9]);
     }
}
The output from this program is:
Element at index 0: 100
Element at index 1: 200
Element at index 2: 300
Element at index 3: 400
Element at index 4: 500
Element at index 5: 600
Element at index 6: 700
Element at index 7: 800
Element at index 8: 900
Element at index 9: 1000

In a real-world programming situation, you'd probably use one of the supported looping constructs to iterate through each element of the array, rather than write each line individually as shown above. However, this example clearly illustrates the array syntax. You'll learn about the various looping constructs (for, while, and do-while) in the Control Flow section.

Declaring a Variable to Refer to an Array

The above program declares anArray with the following line of code:
int[] anArray;          // declares an array of integers

Like declarations for variables of other types, an array declaration has two components: the array's type and the array's name. An array's type is written as type[], where type is the data type of the contained elements; the square brackets are special symbols indicating that this variable holds an array. The size of the array is not part of its type (which is why the brackets are empty). An array's name can be anything you want, provided that it follows the rules and conventions as previously discussed in the naming section. As with variables of other types, the declaration does not actually create an array — it simply tells the compiler that this variable will hold an array of the specified type.

Similarly, you can declare arrays of other types:

byte[] anArrayOfBytes;
short[] anArrayOfShorts;
long[] anArrayOfLongs;
float[] anArrayOfFloats;
double[] anArrayOfDoubles;
boolean[] anArrayOfBooleans;
char[] anArrayOfChars;
String[] anArrayOfStrings;

You can also place the square brackets after the array's name:

float anArrayOfFloats[]; // this form is discouraged
However, convention discourages this form; the brackets identify the array type and should appear with the type designation.

Creating, Initializing, and Accessing an Array

One way to create an array is with the new operator. The next statement in the ArrayDemo program allocates an array with enough memory for ten integer elements and assigns the array to the anArray variable.
anArray = new int[10];  // create an array of integers
If this statement were missing, the compiler would print an error like the following, and compilation would fail:
ArrayDemo.java:4: Variable anArray may not have been initialized.
The next few lines assign values to each element of the array:
anArray[0] = 100; // initialize first element
anArray[1] = 200; // initialize second element
anArray[2] = 300; // etc.
Each array element is accessed by its numerical index:
System.out.println("Element 1 at index 0: " + anArray[0]);
System.out.println("Element 2 at index 1: " + anArray[1]);
System.out.println("Element 3 at index 2: " + anArray[2]);
Alternatively, you can use the shortcut syntax to create and initialize an array:
int[] anArray = {100, 200, 300, 400, 500, 600, 700, 800, 900, 1000};
Here the length of the array is determined by the number of values provided between { and }.

You can also declare an array of arrays (also known as a multidimensional array) by using two or more sets of square brackets, such as String[][] names. Each element, therefore, must be accessed by a corresponding number of index values.

In the Java programming language, a multidimensional array is simply an array whose components are themselves arrays. This is unlike arrays in C or Fortran. A consequence of this is that the rows are allowed to vary in length, as shown in the following MultiDimArrayDemo program:

class MultiDimArrayDemo {
    public static void main(String[] args) {
        String[][] names = {{"Mr. ", "Mrs. ", "Ms. "},
                            {"Smith", "Jones"}};
        System.out.println(names[0][0] + names[1][0]); //Mr. Smith
        System.out.println(names[0][2] + names[1][1]); //Ms. Jones
    }
}
The output from this program is:
    Mr. Smith
    Ms. Jones

Finally, you can use the built-in length property to determine the size of any array. The code

 System.out.println(anArray.length);
will print the array's size to standard output.

Copying Arrays

The System class has an arraycopy method that you can use to efficiently copy data from one array into another:
public static void arraycopy(Object src,
                             int srcPos,
                             Object dest,
                             int destPos,
                             int length)
The two Object arguments specify the array to copy from and the array to copy to. The three int arguments specify the starting position in the source array, the starting position in the destination array, and the number of array elements to copy.

The following program, ArrayCopyDemo, declares an array of char elements, spelling the word "decaffeinated". It uses arraycopy to copy a subsequence of array components into a second array:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class ArrayCopyDemo {
    public static void main(String[] args) {
        char[] copyFrom = { 'd', 'e', 'c', 'a', 'f', 'f', 'e',
                'i', 'n', 'a', 't', 'e', 'd' };
        char[] copyTo = new char[7];

        System.arraycopy(copyFrom, 2, copyTo, 0, 7);
        System.out.println(new String(copyTo));
    }
}

The output from this program is:

caffein
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Primitive Data Types
Next page: Summary of Variables


Summary of Variables (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Section: Variables
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Summary of Variables
The Java programming language uses both "fields" and "variables" as part of its terminology. Instance variables (non-static fields) are unique to each instance of a class. Class variables (static fields) are fields declared with the static modifier; there is exactly one copy of a class variable, regardless of how many times the class has been instantiated. Local variables store temporary state inside a method. Parameters are variables that provide extra information to a method; both local variables and parameters are always classified as "variables" (not "fields"). When naming your fields or variables, there are rules and conventions that you should (or must) follow.

The eight primitive data types are: byte, short, int, long, float, double, boolean, and char. The java.lang.String class represents character strings. The compiler will assign a reasonable default value for fields of the above types; for local variables, a default value is never assigned. A literal is the source code representation of a fixed value. An array is a container object that holds a fixed number of values of a single type. The length of an array is established when the array is created. After creation, its length is fixed.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Arrays
Next page: Questions and Exercises: Variables


Questions and Exercises: Variables (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Questions and Exercises: Variables

Questions

  1. The term "instance variable" is another name for ___.

  2. The term "class variable" is another name for ___.

  3. A local variable stores temporary state; it is declared inside a ___.

  4. A variable declared within the opening and closing parenthesis of a method signature called a ____.

  5. What are the eight primitive data types supported by the Java programming language?

  6. Character strings are represented by the class ___.

  7. An ___ is a container object that holds a fixed number of values of a single type.

Exercises

  1. Create a small program that defines some fields. Try creating some illegal field names and see what kind of error the compiler produces. Use the naming rules and conventions as a guide.

  2. In the program you created in Exercise 1, try leaving the fields uninitialized and print out their values. Try the same with a local variable and see what kind of compiler errors you can produce. Becoming familiar with common compiler errors will make it easier to recognize bugs in your code.
Check your answers

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary of Variables
Next page: Operators


Operators (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Operators
Now that you've learned how to declare and initialize variables, you probably want to know how to do something with them. Learning the operators of the Java programming language is a good place to start. Operators are special symbols that perform specific operations on one, two, or three operands, and then return a result.

As we explore the operators of the Java programming language, it may be helpful for you to know ahead of time which operators have the highest precedence. The operators in the following table are listed according to precedence order. The closer to the top of the table an operator appears, the higher its precedence. Operators with higher precedence are evaluated before operators with relatively lower precedence. Operators on the same line have equal precedence. When operators of equal precedence appear in the same expression, a rule must govern which is evaluated first. All binary operators except for the assignment operators are evaluated from left to right; assignment operators are evaluated right to left.

Operator Precedence
Operators | Precedence
postfix | expr++ expr--
unary | ++expr --expr +expr -expr ~ !
multiplicative * / %
additive + -
shift << >> >>>
relational | < > <= >= instanceof
equality == !=
bitwise AND &
bitwise exclusive OR ^
bitwise inclusive OR |
logical AND &&
logical OR ||
ternary ? :
assignment = += -= *= /= %= &= ^= |= <<= >>= >>>=

In general-purpose programming, certain operators tend to appear more frequently than others; for example, the assignment operator "=" is far more common than the unsigned right shift operator ">>>". With that in mind, the following discussion focuses first on the operators that you're most likely to use on a regular basis, and ends focusing on those that are less common. Each discussion is accompanied by sample code that you can compile and run. Studying its output will help reinforce what you've just learned.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Variables
Next page: Assignment, Arithmetic, and Unary Operators


Assignment, Arithmetic, and Unary Operators (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Section: Operators
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Assignment, Arithmetic, and Unary Operators
The Simple Assignment Operator

One of the most common operators that you'll encounter is the simple assignment operator "=". You saw this operator in the Bicycle class; it assigns the value on its right to the operand on its left:

 int cadence = 0;
 int speed = 0;
 int gear = 1;

This operator can also be used on objects to assign object references, as discussed in Creating Objects.

The Arithmetic Operators

The Java programming language provides operators that perform addition, subtraction, multiplication, and division. There's a good chance you'll recognize them by their counterparts in basic mathematics. The only symbol that might look new to you is "%", which divides one operand by another and returns the remainder as its result.

+ 	additive operator (also used for String concatenation)
- 	subtraction operator
*	multiplication operator
/ 	division operator
%	remainder operator
The following program, ArithmeticDemo, tests the arithmetic operators.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class ArithmeticDemo {

     public static void main (String[] args){

          int result = 1 + 2; // result is now 3
          System.out.println(result);

          result = result - 1; // result is now 2
          System.out.println(result);

          result = result * 2; // result is now 4
          System.out.println(result);

          result = result / 2; // result is now 2
          System.out.println(result);

          result = result + 8; // result is now 10
          result = result % 7; // result is now 3
          System.out.println(result);

     }
}
You can also combine the arithmetic operators with the simple assignment operator to create compound assignments. For example, x+=1; and x=x+1; both increment the value of x by 1.

The + operator can also be used for concatenating (joining) two strings together, as shown in the following ConcatDemo program:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class ConcatDemo {
     public static void main(String[] args){
          String firstString = "This is";
          String secondString = " a concatenated string.";
          String thirdString = firstString+secondString;
          System.out.println(thirdString);
     }
}
By the end of this program, the variable thirdString contains "This is a concatenated string.", which gets printed to standard output.

The Unary Operators

The unary operators require only one operand; they perform various operations such as incrementing/decrementing a value by one, negating an expression, or inverting the value of a boolean.

+ 	Unary plus operator; indicates positive value (numbers are positive without this, however)
- 	Unary minus operator; negates an expression
++  	Increment operator; increments a value by 1
--    	Decrement operator; decrements a value by 1
!     	Logical complement operator; inverts the value of a boolean

The following program, UnaryDemo, tests the unary operators:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class UnaryDemo {

     public static void main(String[] args){
          int result = +1; // result is now 1
          System.out.println(result);
          result--;  // result is now 0
          System.out.println(result);
          result++; // result is now 1
          System.out.println(result);
          result = -result; // result is now -1
          System.out.println(result);
          boolean success = false;
          System.out.println(success); // false
          System.out.println(!success); // true
     }
}
The increment/decrement operators can be applied before (prefix) or after (postfix) the operand. The code result++; and ++result; will both end in result being incremented by one. The only difference is that the prefix version (++result) evaluates to the incremented value, whereas the postfix version (result++) evaluates to the original value. If you are just performing a simple increment/decrement, it doesn't really matter which version you choose. But if you use this operator in part of a larger expression, the one that you choose may make a significant difference.

The following program, PrePostDemo, illustrates the prefix/postfix unary increment operator:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class PrePostDemo {
     public static void main(String[] args){
          int i = 3;
      i++;
      System.out.println(i);	// "4"
      ++i;
      System.out.println(i);	// "5"
      System.out.println(++i);	// "6"
      System.out.println(i++);	// "6"
      System.out.println(i);	// "7"
     }
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Operators
Next page: Equality, Relational, and Conditional Operators


Equality, Relational, and Conditional Operators (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Section: Operators
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Equality, Relational, and Conditional Operators
The Equality and Relational Operators

The equality and relational operators determine if one operand is greater than, less than, equal to, or not equal to another operand. The majority of these operators will probably look familiar to you as well. Keep in mind that you must use "==", not "=", when testing if two primitive values are equal.

==	equal to
!=	not equal to
>	greater than
>=	greater than or equal to
The following program, ComparisonDemo, tests the comparison operators:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class ComparisonDemo {

     public static void main(String[] args){
          int value1 = 1;
          int value2 = 2;
          if(value1 == value2) System.out.println("value1 == value2");
          if(value1 != value2) System.out.println("value1 != value2");
          if(value1 > value2) System.out.println("value1 > value2");
          if(value1 < value2) System.out.println("value1 < value2");
          if(value1 <= value2) System.out.println("value1 <= value2");
     }
}
Output:
value1 != value2
value1 < value2
value1 <= value2="value2"

The Conditional Operators

The && and || operators perform Conditional-AND and Conditional-OR operations on two boolean expressions. These operators exhibit "short-circuiting" behavior, which means that the second operand is evaluated only if needed.

&& Conditional-AND
|| Conditional-OR

The following program, ConditionalDemo1, tests these operators:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class ConditionalDemo1 {

     public static void main(String[] args){
          int value1 = 1;
          int value2 = 2;
          if((value1 == 1) && (value2 == 2)) System.out.println("value1 is 1 AND value2 is 2");
          if((value1 == 1) || (value2 == 1)) System.out.println("value1 is 1 OR value2 is 1");

     }
}

Another conditional operator is ?:, which can be thought of as shorthand for an if-then-else statement (discussed in the Control Flow Statements section of this lesson). This operator is also known as the ternary operator because it uses three operands. In the following example, this operator should be read as: "If someCondition is true, assign the value of value1 to result. Otherwise, assign the value of value2 to result."

The following program, ConditionalDemo2, tests the ?: operator:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class ConditionalDemo2 {

     public static void main(String[] args){
          int value1 = 1;
          int value2 = 2;
          int result;
          boolean someCondition = true;
          result = someCondition ? value1 : value2;

          System.out.println(result);

     }
}

Because someCondition is true, this program prints "1" to the screen. Use the ?: operator instead of an if-then-else statement if it makes your code more readable; for example, when the expressions are compact and without side-effects (such as assignments).

The Type Comparison Operator instanceof

The instanceof operator compares an object to a specified type. You can use it to test if an object is an instance of a class, an instance of a subclass, or an instance of a class that implements a particular interface.

The following program, InstanceofDemo, defines a parent class (named Parent), a simple interface (named MyInterface), and a child class (named Child) that inherits from the parent and implements the interface.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class InstanceofDemo {
  public static void main(String[] args) {

    Parent obj1 = new Parent();
    Parent obj2 = new Child();

    System.out.println("obj1 instanceof Parent: " + (obj1 instanceof Parent));
    System.out.println("obj1 instanceof Child: " + (obj1 instanceof Child));
    System.out.println("obj1 instanceof MyInterface: " + (obj1 instanceof MyInterface));
    System.out.println("obj2 instanceof Parent: " + (obj2 instanceof Parent));
    System.out.println("obj2 instanceof Child: " + (obj2 instanceof Child));
    System.out.println("obj2 instanceof MyInterface: " + (obj2 instanceof MyInterface));
  }
}

class Parent{}
class Child extends Parent implements MyInterface{}
interface MyInterface{}
Output:
obj1 instanceof Parent: true
obj1 instanceof Child: false
obj1 instanceof MyInterface: false
obj2 instanceof Parent: true
obj2 instanceof Child: true
obj2 instanceof MyInterface: true
When using the instanceof operator, keep in mind that null is not an instance of anything.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Assignment, Arithmetic, and Unary Operators
Next page: Bitwise and Bit Shift Operators


Bitwise and Bit Shift Operators (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Section: Operators
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Bitwise and Bit Shift Operators
The Java programming language also provides operators that perform bitwise and bit shift operations on integral types. The operators discussed in this section are less commonly used. Therefore, their coverage is brief; the intent is to simply make you aware that these operators exist.

The unary bitwise complement operator "~" inverts a bit pattern; it can be applied to any of the integral types, making every "0" a "1" and every "1" a "0". For example, a byte contains 8 bits; applying this operator to a value whose bit pattern is "00000000" would change its pattern to "11111111".

The signed left shift operator "<<" shifts a bit pattern to the left, and the signed right shift operator ">>" shifts a bit pattern to the right. The bit pattern is given by the left-hand operand, and the number of positions to shift by the right-hand operand. The unsigned right shift operator ">>>" shifts a zero into the leftmost position, while the leftmost position after ">>" depends on sign extension.

The bitwise & operator performs a bitwise AND operation.

The bitwise ^ operator performs a bitwise exclusive OR operation.

The bitwise | operator performs a bitwise inclusive OR operation.

The following program, BitDemo, uses the bitwise AND operator to print the number "2" to standard output.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class BitDemo {
     public static void main(String[] args) {
          int bitmask = 0x000F;
      int val = 0x2222;
      System.out.println(val & bitmask);  // prints "2"
     }
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Equality, Relational, and Conditional Operators
Next page: Summary of Operators


Summary of Operators (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Section: Operators
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Summary of Operators
The following quick reference summarizes the operators supported by the Java programming language.

Simple Assignment Operator

=	Simple assignment operator

Arithmetic Operators

+ 	Additive operator (also used for String concatenation)
- 	Subtraction operator
*	Multiplication operator
/ 	Division operator
%	Remainder operator

Unary Operators

+ 	Unary plus operator; indicates positive value (numbers are positive without this, however)
- 	Unary minus operator; negates an expression
++  	Increment operator; increments a value by 1
--    	Decrement operator; decrements a value by 1
!     	Logical compliment operator; inverts the value of a boolean

Equality and Relational Operators

==	Equal to
!=	Not equal to
>	Greater than
>=	Greater than or equal to

Conditional Operators

&& 	Conditional-AND
|| 	Conditional-OR
?:      Ternary (shorthand for if-then-else statement)

Type Comparison Operator

instanceof	Compares an object to a specified type

Bitwise and Bit Shift Operators

~	Unary bitwise complement
<<	Signed left shift
>>	Signed right shift
>>>	Unsigned right shift
&	Bitwise AND
^	Bitwise exclusive OR
|	Bitwise inclusive OR
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Bitwise and Bit Shift Operators
Next page: Questions and Exercises: Operators


Questions and Exercises: Operators (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Questions and Exercises: Operators

Questions

  1. Consider the following code snippet.
    arrayOfInts[j] > arrayOfInts[j+1]
    Which operators does the code contain?

  2. Consider the following code snippet.
    int i = 10;
int n = i++%5;
    1. What are the values of i and n after the code is executed?

    2. What are the final values of i and n if instead of using the postfix increment operator (i++), you use the prefix version (++i))?

  3. To invert the value of a boolean, which operator would you use?

  4. Which operator is used to compare two values, = or == ?

  5. Explain the following code sample: result = someCondition ? value1 : value2;

Exercises

  1. Change the following program to use compound assignments:
    class ArithmeticDemo {

     public static void main (String[] args){

          int result = 1 + 2; // result is now 3
          System.out.println(result);

          result = result - 1; // result is now 2
          System.out.println(result);

          result = result * 2; // result is now 4
          System.out.println(result);

          result = result / 2; // result is now 2
          System.out.println(result);

          result = result + 8; // result is now 10
          result = result % 7; // result is now 3
          System.out.println(result);

     }
}
  2. In the following program, explain why the value "6" is printed twice in a row:
    class PrePostDemo {
     public static void main(String[] args){
          int i = 3;
      i++;
      System.out.println(i);	// "4"
      ++i;
      System.out.println(i);	// "5"
      System.out.println(++i);	// "6"
      System.out.println(i++);	// "6"
      System.out.println(i);	// "7"
     }
}
Check your answers

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary of Operators
Next page: Expressions, Statements, and Blocks


Expressions, Statements, and Blocks (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Expressions, Statements, and Blocks
Now that you understand variables and operators, it's time to learn about expressions, statements, and blocks. Operators may be used in building expressions, which compute values; expressions are the core components of statements; statements may be grouped into blocks.

Expressions

An expression is a construct made up of variables, operators, and method invocations, which are constructed according to the syntax of the language, that evaluates to a single value. You've already seen examples of expressions, illustrated in bold below:
     int cadence = 0;
     anArray[0] = 100;
     System.out.println("Element 1 at index 0: " + anArray[0]);

     int result = 1 + 2; // result is now 3
     if(value1 == value2) System.out.println("value1 == value2");
The data type of the value returned by an expression depends on the elements used in the expression. The expression cadence = 0 returns an int because the assignment operator returns a value of the same data type as its left-hand operand; in this case, cadence is an int. As you can see from the other expressions, an expression can return other types of values as well, such as boolean or String.

The Java programming language allows you to construct compound expressions from various smaller expressions as long as the data type required by one part of the expression matches the data type of the other. Here's an example of a compound expression:

1 * 2 * 3

In this particular example, the order in which the expression is evaluated is unimportant because the result of multiplication is independent of order; the outcome is always the same, no matter in which order you apply the multiplications. However, this is not true of all expressions. For example, the following expression gives different results, depending on whether you perform the addition or the division operation first:

x + y / 100     // ambiguous

You can specify exactly how an expression will be evaluated using balanced parenthesis: ( and ). For example, to make the previous expression unambiguous, you could write the following:

(x + y) / 100    // unambiguous, recommended

If you don't explicitly indicate the order for the operations to be performed, the order is determined by the precedence assigned to the operators in use within the expression. Operators that have a higher precedence get evaluated first. For example, the division operator has a higher precedence than does the addition operator. Therefore, the following two statements are equivalent:

x + y / 100

x + (y / 100) // unambiguous, recommended

When writing compound expressions, be explicit and indicate with parentheses which operators should be evaluated first. This practice makes code easier to read and to maintain.

Statements

Statements are roughly equivalent to sentences in natural languages. A statement forms a complete unit of execution. The following types of expressions can be made into a statement by terminating the expression with a semicolon (;).
  • Assignment expressions
  • Any use of ++ or --
  • Method invocations
  • Object creation expressions
Such statements are called expression statements. Here are some examples of expression statements.
aValue = 8933.234;                      // assignment statement
aValue++;                               // increment statement
System.out.println("Hello World!");     // method invocation statement
Bicycle myBike = new Bicycle(); // object creation statement
In addition to expression statements, there are two other kinds of statements: declaration statements and control flow statements. A declaration statement declares a variable. You've seen many examples of declaration statements already:
double aValue = 8933.234; //declaration statement
Finally, control flow statements regulate the order in which statements get executed. You'll learn about control flow statements in the next section, Control Flow Statements

Blocks

A block is a group of zero or more statements between balanced braces and can be used anywhere a single statement is allowed. The following example, BlockDemo, illustrates the use of blocks:
class BlockDemo {
     public static void main(String[] args) {
          boolean condition = true;
          if (condition) { // begin block 1
               System.out.println("Condition is true.");
          } // end block one
          else { // begin block 2
               System.out.println("Condition is false.");
          } // end block 2
     }
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Operators
Next page: Questions and Exercises: Expressions, Statements, and Blocks


Questions and Exercises: Expressions, Statements, and Blocks (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Questions and Exercises: Expressions, Statements, and Blocks

Questions

  1. Operators may be used in building ___, which compute values.

  2. Expressions are the core components of ___.

  3. Statements may be grouped into ___.

  4. The following code snippet is an example of a ___ expression.

     1 * 2 * 3
  5. Statements are roughly equivalent to sentences in natural languages, but instead of ending with a period, a statement ends with a ___.

  6. A block is a group of zero or more statements between balanced ___ and can be used anywhere a single statement is allowed.

Exercises

Identify the following kinds of expression statements:
  • aValue = 8933.234;
  • aValue++;
  • System.out.println("Hello World!");
  • Bicycle myBike = new Bicycle();

Check your answers

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Expressions, Statements, and Blocks
Next page: Control Flow Statements


Control Flow Statements (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Control Flow Statements

The statements inside your source files are generally executed from top to bottom, in the order that they appear. Control flow statements, however, break up the flow of execution by employing decision making, looping, and branching, enabling your program to conditionally execute particular blocks of code. This section describes the decision-making statements (if-then, if-then-else, switch), the looping statements (for, while, do-while), and the branching statements (break, continue, return) supported by the Java programming language.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Expressions, Statements, and Blocks
Next page: The if-then and if-then-else Statements


The if-then and if-then-else Statements (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Section: Control Flow Statements
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
The if-then and if-then-else Statements

The if-then Statement

The if-then statement is the most basic of all the control flow statements. It tells your program to execute a certain section of code only if a particular test evaluates to true. For example, the Bicycle class could allow the brakes to decrease the bicycle's speed only if the bicycle is already in motion. One possible implementation of the applyBrakes method could be as follows:
void applyBrakes(){
     if (isMoving){  // the "if" clause: bicycle must moving
          currentSpeed--; // the "then" clause: decrease current speed
     }
}

If this test evaluates to false (meaning that the bicycle is not in motion), control jumps to the end of the if-then statement.

In addition, the opening and closing braces are optional, provided that the "then" clause contains only one statement:

void applyBrakes(){
     if (isMoving) currentSpeed--; // same as above, but without braces
}
Deciding when to omit the braces is a matter of personal taste. Omitting them can make the code more brittle. If a second statement is later added to the "then" clause, a common mistake would be forgetting to add the newly required braces. The compiler cannot catch this sort of error; you'll just get the wrong results.

The if-then-else Statement

The if-then-else statement provides a secondary path of execution when an "if" clause evaluates to false. You could use an if-then-else statement in the applyBrakes method to take some action if the brakes are applied when the bicycle is not in motion. In this case, the action is to simply print an error message stating that the bicycle has already stopped.
void applyBrakes(){
     if (isMoving) {
          currentSpeed--;
     } else {
          System.err.println("The bicycle has already stopped!");
     }
}

The following program, IfElseDemo, assigns a grade based on the value of a test score: an A for a score of 90% or above, a B for a score of 80% or above, and so on.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class IfElseDemo {
    public static void main(String[] args) {

        int testscore = 76;
        char grade;

        if (testscore >= 90) {
            grade = 'A';
        } else if (testscore >= 80) {
            grade = 'B';
        } else if (testscore >= 70) {
            grade = 'C';
        } else if (testscore >= 60) {
            grade = 'D';
        } else {
            grade = 'F';
        }
        System.out.println("Grade = " + grade);
    }
}
The output from the program is:
    Grade = C
You may have noticed that the value of testscore can satisfy more than one expression in the compound statement: 76 >= 70 and 76 >= 60. However, once a condition is satisfied, the appropriate statements are executed (grade = 'C';) and the remaining conditions are not evaluated.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Control Flow Statements
Next page: The switch Statement


The switch Statement (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Section: Control Flow Statements
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
The switch Statement
Unlike if-then and if-then-else, the switch statement allows for any number of possible execution paths. A switch works with the byte, short, char, and int primitive data types. It also works with enumerated types (discussed in Classes and Inheritance) and a few special classes that "wrap" certain primitive types: Character, Byte, Short, and Integer (discussed in Simple Data Objects ).

The following program, SwitchDemo, declares an int named month whose value represents a month out of the year. The program displays the name of the month, based on the value of month, using the switch statement.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class SwitchDemo {
    public static void main(String[] args) {

        int month = 8;
        switch (month) {
            case 1:  System.out.println("January"); break;
            case 2:  System.out.println("February"); break;
            case 3:  System.out.println("March"); break;
            case 4:  System.out.println("April"); break;
            case 5:  System.out.println("May"); break;
            case 6:  System.out.println("June"); break;
            case 7:  System.out.println("July"); break;
            case 8:  System.out.println("August"); break;
            case 9:  System.out.println("September"); break;
            case 10: System.out.println("October"); break;
            case 11: System.out.println("November"); break;
            case 12: System.out.println("December"); break;
            default: System.out.println("Invalid month.");break;
        }
    }
}

In this case, "August" is printed to standard output.

The body of a switch statement is known as a switch block. Any statement immediately contained by the switch block may be labeled with one or more case or default labels. The switch statement evaluates its expression and executes the appropriate case.

Of course, you could also implement the same thing with if-then-else statements:

int month = 8;
if (month == 1) {
    System.out.println("January");
} else if (month == 2) {
    System.out.println("February");
}
. . . // and so on
Deciding whether to use if-then-else statements or a switch statement is sometimes a judgment call. You can decide which one to use based on readability and other factors. An if-then-else statement can be used to make decisions based on ranges of values or conditions, whereas a switch statement can make decisions based only on a single integer or enumerated value.

Another point of interest is the break statement after each case. Each break statement terminates the enclosing switch statement. Control flow continues with the first statement following the switch block. The break statements are necessary because without them, case statements fall through; that is, without an explicit break, control will flow sequentially through subsequent case statements. The following program, SwitchDemo2, illustrates why it might be useful to have case statements fall through:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class SwitchDemo2 {
    public static void main(String[] args) {

        int month = 2;
        int year = 2000;
        int numDays = 0;

        switch (month) {
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                numDays = 31;
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                numDays = 30;
                break;
            case 2:
                if ( ((year % 4 == 0) && !(year % 100 == 0))
                     || (year % 400 == 0) )
                    numDays = 29;
                else
                    numDays = 28;
                break;
            default:
                System.out.println("Invalid month.");
                break;
        }
        System.out.println("Number of Days = " + numDays);
    }
}

This is the output from the program.

    Number of Days = 29

Technically, the final break is not required because flow would fall out of the switch statement anyway. However, we recommend using a break so that modifying the code is easier and less error-prone. The default section handles all values that aren't explicitly handled by one of the case sections.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The if-then and if-then-else Statements
Next page: The while and do-while Statements


The while and do-while Statements (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Section: Control Flow Statements
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
The while and do-while Statements
The while statement continually executes a block of statements while a particular condition is true. Its syntax can be expressed as:
while (expression) {
     statement(s)
}
The while statement evaluates expression, which must return a boolean value. If the expression evaluates to true, the while statement executes the statement(s) in the while block. The while statement continues testing the expression and executing its block until the expression evaluates to false. Using the while statement to print the values from 1 through 10 can be accomplished as in the following WhileDemo program:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class WhileDemo {
     public static void main(String[] args){
          int count = 1;
          while (count < 11) {
               System.out.println("Count is: " + count);
               count++;
          }
     }
}

You can implement an infinite loop using the while statement as follows:

while (true){
    // your code goes here
}

The Java programming language also provides a do-while statement, which can be expressed as follows:

do {
     statement(s)
} while (expression);
The difference between do-while and while is that do-while evaluates its expression at the bottom of the loop instead of the top. Therefore, the statements within the do block are always executed at least once, as shown in the following DoWhileDemo program:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class DoWhileDemo {
     public static void main(String[] args){
          int count = 1;
          do {
               System.out.println("Count is: " + count);
               count++;
          } while (count <= 11);
     }
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The switch Statement
Next page: The for Statement


The for Statement (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Section: Control Flow Statements
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
The for Statement
The for statement provides a compact way to iterate over a range of values. Programmers often refer to it as the "for loop" because of the way in which it repeatedly loops until a particular condition is satisfied. The general form of the for statement can be expressed as follows:
for (initialization; termination; increment) {
    statement(s)
}
When using this version of the for statement, keep in mind that:
  • The initialization expression initializes the loop; it's executed once, as the loop begins.
  • When the termination expression evaluates to false, the loop terminates.
  • The increment expression is invoked after each iteration through the loop; it is perfectly acceptable for this expression to increment or decrement a value.

The following program, ForDemo, uses the general form of the for statement to print the numbers 1 through 10 to standard output:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class ForDemo {
     public static void main(String[] args){
          for(int i=1; i<11; i++){
               System.out.println("Count is: " + i);
          }
     }
}
The output of this program is:
Count is: 1
Count is: 2
Count is: 3
Count is: 4
Count is: 5
Count is: 6
Count is: 7
Count is: 8
Count is: 9
Count is: 10
Notice how the code declares a variable within the initialization expression. The scope of this variable extends from its declaration to the end of the block governed by the for statement, so it can be used in the termination and increment expressions as well. If the variable that controls a for statement is not needed outside of the loop, it's best to declare the variable in the initialization expression. The names i, j, and k are often used to control for loops; declaring them within the initialization expression limits their life span and reduces errors.

The three expressions of the for loop are optional; an infinite loop can be created as follows:

for ( ; ; ) {    // infinite loop

     // your code goes here
}

The for statement also has another form designed for iteration through Collections and arrays This form is sometimes referred to as the enhanced for statement, and can be used to make your loops more compact and easy to read. To demonstrate, consider the following array, which holds the numbers 1 through 10:

int[] numbers = {1,2,3,4,5,6,7,8,9,10};

The following program, EnhancedForDemo, uses the enhanced for to loop through the array:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class EnhancedForDemo {
     public static void main(String[] args){
          int[] numbers = {1,2,3,4,5,6,7,8,9,10};
          for (int item : numbers) {
            System.out.println("Count is: " + item);
          }
     }
}
In this example, the variable item holds the current value from the numbers array. The output from this program is the same as before:
Count is: 1
Count is: 2
Count is: 3
Count is: 4
Count is: 5
Count is: 6
Count is: 7
Count is: 8
Count is: 9
Count is: 10
We recommend using this form of the for statement instead of the general form whenever possible.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The while and do-while Statements
Next page: Branching Statements


Branching Statements (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Section: Control Flow Statements
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Branching Statements

The break Statement

The break statement has two forms: labeled and unlabeled. You saw the unlabeled form in the previous discussion of the switch statement. You can also use an unlabeled break to terminate a for, while, or do-while loop, as shown in the following BreakDemo program:
class BreakDemo {
    public static void main(String[] args) {

        int[] arrayOfInts = { 32, 87, 3, 589, 12, 1076,
                              2000, 8, 622, 127 };
        int searchfor = 12;

        int i;
        boolean foundIt = false;

        for (i = 0; i < arrayOfInts.length; i++) {
            if (arrayOfInts[i] == searchfor) {
                foundIt = true;
                break;
            }
        }

        if (foundIt) {
            System.out.println("Found " + searchfor
                               + " at index " + i);
        } else {
            System.out.println(searchfor
                               + " not in the array");
        }
    }
}
This program searches for the number 12 in an array. The break statement, shown in boldface, terminates the for loop when that value is found. Control flow then transfers to the print statement at the end of the program. This program's output is:
Found 12 at index 4
An unlabeled break statement terminates the innermost switch, for, while, or do-while statement, but a labeled break terminates an outer statement. The following program, BreakWithLabelDemo, is similar to the previous program, but uses nested for loops to search for a value in a two-dimensional array. When the value is found, a labeled break terminates the outer for loop (labeled "search"):
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class BreakWithLabelDemo {
    public static void main(String[] args) {

        int[][] arrayOfInts = { { 32, 87, 3, 589 },
                                { 12, 1076, 2000, 8 },
                                { 622, 127, 77, 955 }
                              };
        int searchfor = 12;

        int i;
        int j = 0;
        boolean foundIt = false;

    search:
        for (i = 0; i < arrayOfInts.length; i++) {
            for (j = 0; j < arrayOfInts[i].length; j++) {
                if (arrayOfInts[i][j] == searchfor) {
                    foundIt = true;
                    break search;
                }
            }
        }

        if (foundIt) {
            System.out.println("Found " + searchfor +
                               " at " + i + ", " + j);
        } else {
            System.out.println(searchfor
                               + " not in the array");
        }
    }
}

This is the output of the program.

     Found 12 at 1, 0
The break statement terminates the labeled statement; it does not transfer the flow of control to the label. Control flow is transferred to the statement immediately following the labeled (terminated) statement.

The continue Statement

The continue statement skips the current iteration of a for, while , or do-while loop. The unlabeled form skips to the end of the innermost loop's body and evaluates the boolean expression that controls the loop. The following program, ContinueDemo , steps through a String, counting the occurences of the letter "p". If the current character is not a p, the continue statement skips the rest of the loop and proceeds to the next character. If it is a "p", the program increments the letter count.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class ContinueDemo {
    public static void main(String[] args) {

        String searchMe = "peter piper picked a peck of pickled peppers";
        int max = searchMe.length();
        int numPs = 0;

        for (int i = 0; i < max; i++) {
            //interested only in p's
            if (searchMe.charAt(i) != 'p')
                continue;

            //process p's
            numPs++;
        }
        System.out.println("Found " + numPs + " p's in the string.");
    }
}
Here is the output of this program:
Found 9 p's in the string.
To see this effect more clearly, try removing the continue statement and recompiling. When you run the program again, the count will be wrong, saying that it found 35 p's instead of 9.

A labeled continue statement skips the current iteration of an outer loop marked with the given label. The following example program, ContinueWithLabelDemo, uses nested loops to search for a substring within another string. Two nested loops are required: one to iterate over the substring and one to iterate over the string being searched. The following program, ContinueWithLabelDemo, uses the labeled form of continue to skip an iteration in the outer loop.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class ContinueWithLabelDemo {
    public static void main(String[] args) {

        String searchMe = "Look for a substring in me";
        String substring = "sub";
        boolean foundIt = false;

        int max = searchMe.length() - substring.length();

    test:
        for (int i = 0; i <= max; i++) {
            int n = substring.length();
            int j = i;
            int k = 0;
            while (n-- != 0) {
                if (searchMe.charAt(j++)
                        != substring.charAt(k++)) {
                    continue test;
                }
            }
            foundIt = true;
                 break test;
        }
        System.out.println(foundIt ? "Found it" :
                                     "Didn't find it");
    }
}

Here is the output from this program.

     Found it

The return Statement

The last of the branching statements is the return statement. The return statement exits from the current method, and control flow returns to where the method was invoked. The return statement has two forms: one that returns a value, and one that doesn't. To return a value, simply put the value (or an expression that calculates the value) after the return keyword.
     return ++count;
The data type of the returned value must match the type of the method's declared return value. When a method is declared void, use the form of return that doesn't return a value.
     return;
The Classes and Objects lesson will cover everything you need to know about writing methods.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The for Statement
Next page: Summary of Control Flow Statements


Summary of Control Flow Statements (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Section: Control Flow Statements
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Summary of Control Flow Statements
The if-then statement is the most basic of all the control flow statements. It tells your program to execute a certain section of code only if a particular test evaluates to true. The if-then-else statement provides a secondary path of execution when an "if" clause evaluates to false. Unlike if-then and if-then-else, the switch statement allows for any number of possible execution paths. The while and do-while statements continually execute a block of statements while a particular condition is true. The difference between do-while and while is that do-while evaluates its expression at the bottom of the loop instead of the top. Therefore, the statements within the do block are always executed at least once. The for statement provides a compact way to iterate over a range of values. It has two forms, one of which was designed for looping through collections and arrays.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Branching Statements
Next page: Questions and Exercises: Control Flow Statements


Questions and Exercises: Control Flow Statements (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises
Expressions, Statements, and Blocks
Questions and Exercises
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises
Home Page > Learning the Java Language > Language Basics
« Previous • Trail • Next »
Questions and Exercises: Control Flow Statements

Questions

  1. The most basic control flow statement supported by the Java programming language is the ___ statement.

  2. The ___ statement allows for any number of possible execution paths.

  3. The ___ statement is similar to the while statement, but evaluates its expression at the ___ of the loop.

  4. How do you write an infinite loop using the for statement?

  5. How do you write an infinite loop using the while statement?

Exercises

  1. Consider the following code snippet.
    if (aNumber >= 0)
    if (aNumber == 0) System.out.println("first string");
else System.out.println("second string");
System.out.println("third string");

    1. What output do you think the code will produce if aNumber is 3?

    2. Write a test program containing the previous code snippet; make aNumber 3. What is the output of the program? Is it what you predicted? Explain why the output is what it is; in other words, what is the control flow for the code snippet?

    3. Using only spaces and line breaks, reformat the code snippet to make the control flow easier to understand.

    4. Use braces, { and }, to further clarify the code.

Check your answers

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary of Control Flow Statements
Next page: Classes and Objects


Lesson: Classes and Objects (The Java™ Tutorials > Learning the Java Language)

Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Trail: Learning the Java Language
Home Page > Learning the Java Language
« Previous • Trail • Next »
Lesson: Classes and Objects
With the knowledge you now have of the basics of the Java programming language, you can learn to write your own classes. In this lesson, you will find information about defining your own classes, including declaring member variables, methods, and constructors.

You will learn to use your classes to create objects, and how to use the objects you create.

This lesson also covers nesting classes within other classes, enumerations, and annotations.

Classes

This section shows you the anatomy of a class, and how to declare fields, methods, and constructors.

Objects

This section covers creating and using objects. You will learn how to instantiate an object, and, once instantiated, how to use the dot operator to access the object's instance variables and methods.

More on Classes

This section covers more aspects of classes that depend on using object references and the dot operator that you learned about in the preceding section: returning values from methods, the this keyword, class vs. instance members, and access control.

Nested Classes

Static nested classes, inner classes, anonymous inner classes, and local classes are covered.

Enum Types

This section covers enumerations, specialized classes that allow you to define and use sets of constants.

Annotations

Annotations allow you to add information to your program that is not actually part of the program. This section describes three built-in annotations that you should know about.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Classes


Classes (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Classes
The introduction to object-oriented concepts in the lesson titled Object-oriented Programming Concepts used a bicycle class as an example, with racing bikes, mountain bikes, and tandem bikes as subclasses. Here is sample code for a possible implementation of a Bicycle class, to give you an overview of a class declaration. Subsequent sections of this lesson will back up and explain class declarations step by step. For the moment, don't concern yourself with the details.
public class Bicycle {

    // the Bicycle class has three fields
    public int cadence;
    public int gear;
    public int speed;

    // the Bicycle class has one constructor
    public Bicycle(int startCadence, int startSpeed, int startGear) {
        gear = startGear;
        cadence = startCadence;
        speed = startSpeed;
    }

    // the Bicycle class has four methods
    public void setCadence(int newValue) {
        cadence = newValue;
    }

    public void setGear(int newValue) {
        gear = newValue;
    }

    public void applyBrake(int decrement) {
        speed -= decrement;
    }

    public void speedUp(int increment) {
        speed += increment;
    }

}

A class declaration for a MountainBike class that is a subclass of Bicycle might look like this:

public class MountainBike extends Bicycle {

    // the MountainBike subclass has one field
    public int seatHeight;

    // the MountainBike subclass has one constructor
    public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear) {
        super(startCadence, startSpeed, startGear);
        seatHeight = startHeight;
    }

    // the MountainBike subclass has one method
    public void setHeight(int newValue) {
        seatHeight = newValue;
    }

}
MountainBike inherits all the fields and methods of Bicycle and adds the field seatHeight and a method to set it (mountain bikes have seats that can be moved up and down as the terrain demands).
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Classes and Objects
Next page: Declaring Classes


Declaring Classes (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: Classes
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Declaring Classes
You've seen classes defined in the following way:
class MyClass {
    //field, constructor, and method declarations
}
This is a class declaration. The class body (the area between the braces) contains all the code that provides for the life cycle of the objects created from the class: constructors for initializing new objects, declarations for the fields that provide the state of the class and its objects, and methods to implement the behavior of the class and its objects.

The preceding class declaration is a minimal one—it contains only those components of a class declaration that are required. You can provide more information about the class, such as the name of its superclass, whether it implements any interfaces, and so on, at the start of the class declaration. For example,

class MyClass extends MySuperClass implements YourInterface {
    //field, constructor, and method declarations
}

means that MyClass is a subclass of MySuperClass and that it implements the YourInterface interface.

You can also add modifiers like public or private at the very beginning—so you can see that the opening line of a class declaration can become quite complicated. The modifiers public and private, which determine what other classes can access MyClass, are discussed later in this lesson. The lesson on interfaces and inheritance will explain how and why you would use the extends and implements keywords in a class declaration. For the moment you do not need to worry about these extra complications.

In general, class declarations can include these components, in order:

  1. Modifiers such as public, private, and a number of others that you will encounter later.
  2. The class name, with the initial letter capitalized by convention.
  3. The name of the class's parent (superclass), if any, preceded by the keyword extends. A class can only extend (subclass) one parent.
  4. A comma-separated list of interfaces implemented by the class, if any, preceded by the keyword implements. A class can implement more than one interface.
  5. The class body, surrounded by braces, {}.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Classes
Next page: Declaring Member Variables


Declaring Member Variables (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: Classes
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Declaring Member Variables
There are several kinds of variables:
  • Member variables in a class—these are called fields.
  • Variables in a method or block of code—these are called local variables.
  • Variables in method declarations—these are called parameters.
The Bicycle class uses the following lines of code to define its fields:
public int cadence;
public int gear;
public int speed;
Field declarations are composed of three components, in order:
  1. Zero or more modifiers, such as public or private.
  2. The field's type.
  3. The field's name.
The fields of Bicycle are named cadence, gear, and speed and are all of data type integer (int). The public keyword identifies these fields as public members, accessible by any object that can access the class.

Access Modifiers

The first (left-most) modifier used lets you control what other classes have access to a member field. For the moment, consider only public and private. Other access modifiers will be discussed later.
  • public modifier—the field is accessible from all classes.
  • private modifier—the field is accessible only within its own class.

In the spirit of encapsulation, it is common to make fields private. This means that they can only be directly accessed from the Bicycle class. We still need access to these values, however. This can be done indirectly by adding public methods that obtain the field values for us:

public class Bicycle {

    private int cadence;
    private int gear;
    private int speed;

    public Bicycle(int startCadence, int startSpeed, int startGear) {
        gear = startGear;
        cadence = startCadence;
        speed = startSpeed;
    }

    public int getCadence() {
        return cadence;
    }

    public void setCadence(int newValue) {
        cadence = newValue;
    }

    public int getGear() {
        return gear;
    }

    public void setGear(int newValue) {
        gear = newValue;
    }

    public int getSpeed() {
        return speed;
    }

    public void applyBrake(int decrement) {
        speed -= decrement;
    }

    public void speedUp(int increment) {
        speed += increment;
    }

}

Types

All variables must have a type. You can use primitive types such as int, float, boolean, etc. Or you can use reference types, such as strings, arrays, or objects.

Variable Names

All variables, whether they are fields, local variables, or parameters, follow the same naming rules and conventions that were covered in the Language Basics lesson, Variables—Naming .

In this lesson, be aware that the same naming rules and conventions are used for method and class names, except that

  • the first letter of a class name should be capitalized, and
  • the first (or only) word in a method name should be a verb.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Declaring Classes
Next page: Defining Methods


Defining Methods (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: Classes
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Defining Methods
Here is an example of a typical method declaration:
public double calculateAnswer(double wingSpan, int numberOfEngines, double length, double grossTons) {
    //do the calculation here
}
The only required elements of a method declaration are the method's return type, name, a pair of parentheses, (), and a body between braces, {}.

More generally, method declarations have six components, in order:

  1. Modifiers—such as public, private, and others you will learn about later.
  2. The return type—the data type of the value returned by the method, or void if the method does not return a value.
  3. The method name—the rules for field names apply to method names as well, but the convention is a little different.
  4. The parameter list in parenthesis—a comma-delimited list of input parameters, preceded by their data types, enclosed by parentheses, (). If there are no parameters, you must use empty parentheses.
  5. An exception list—to be discussed later.
  6. The method body, enclosed between braces—the method's code, including the declaration of local variables, goes here.
Modifiers, return types, and parameters will be discussed later in this lesson. Exceptions are discussed in a later lesson.

Definition: Two of the components of a method declaration comprise the method signature—the method's name and the parameter types.
The signature of the method declared above is:
calculateAnswer(double, int, double, double)

Naming a Method

Although a method name can be any legal identifier, code conventions restrict method names. By convention, method names should be a verb in lowercase or a multi-word name that begins with a verb in lowercase, followed by adjectives, nouns, etc. In multi-word names, the first letter of each of the second and following words should be capitalized. Here are some examples:
run
runFast
getBackground
getFinalData
compareTo
setX
isEmpty
Typically, a method has a unique name within its class. However, a method might have the same name as other methods due to method overloading.

Overloading Methods

The Java programming language supports overloading methods, and Java can distinguish between methods with different method signatures. This means that methods within a class can have the same name if they have different parameter lists (there are some qualifications to this that will be discussed in the lesson titled "Interfaces and Inheritance").

Suppose that you have a class that can use calligraphy to draw various types of data (strings, integers, and so on) and that contains a method for drawing each data type. It is cumbersome to use a new name for each method—for example, drawString, drawInteger, drawFloat, and so on. In the Java programming language, you can use the same name for all the drawing methods but pass a different argument list to each method. Thus, the data drawing class might declare four methods named draw, each of which has a different parameter list.

public class DataArtist {
    ...
    public void draw(String s) {
        ...
    }
    public void draw(int i) {
        ...
    }
    public void draw(double f) {
        ...
    }
    public void draw(int i, double f) {
        ...
    }
}
Overloaded methods are differentiated by the number and the type of the arguments passed into the method. In the code sample, draw(String s) and draw(int i) are distinct and unique methods because they require different argument types.

You cannot declare more than one method with the same name and the same number and type of arguments, because the compiler cannot tell them apart.

The compiler does not consider return type when differentiating methods, so you cannot declare two methods with the same signature even if they have a different return type.

Note: Overloaded methods should be used sparingly, as they can make code much less readable.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Declaring Member Variables
Next page: Providing Constructors for Your Classes


Providing Constructors for Your Classes (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: Classes
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Providing Constructors for Your Classes
A class contains constructors that are invoked to create objects from the class blueprint. Constructor declarations look like method declarations—except that they use the name of the class and have no return type. For example, Bicycle has one constructor:
public Bicycle(int startCadence, int startSpeed, int startGear) {
    gear = startGear;
    cadence = startCadence;
    speed = startSpeed;
}
To create a new Bicycle object called myBike, a constructor is called by the new operator:
Bicycle myBike = new Bicycle(30, 0, 8);
new Bicycle(30, 0, 8) creates space in memory for the object and initializes its fields.

Although Bicycle only has one constructor, it could have others, including a no-argument constructor:

public Bicycle() {
    gear = 1;
    cadence = 10;
    speed = 0;
}

Bicycle yourBike = new Bicycle(); invokes the no-argument constructor to create a new Bicycle object called yourBike.

Both constructors could have been declared in Bicycle because they have different argument lists. As with methods, the Java platform differentiates constructors on the basis of the number of arguments in the list and their types. You cannot write two constructors that have the same number and type of arguments for the same class, because the platform would not be able to tell them apart. Doing so causes a compile-time error.

You don't have to provide any constructors for your class, but you must be careful when doing this. The compiler automatically provides a no-argument, default constructor for any class without constructors. This default constructor will call the no-argument constructor of the superclass. In this situation, the compiler will complain if the superclass doesn't have a no-argument constructor so you must verify that it does. If your class has no explicit superclass, then it has an implicit superclass of Object, which does have a no-argument constructor.

You can use a superclass constructor yourself. The MountainBike class at the beginning of this lesson did just that. This will be discussed later, in the lesson on interfaces and inheritance.

You can use access modifiers in a constructor's declaration to control which other classes can call the constructor.

Note : If another class cannot call a MyClass constructor, it cannot directly create MyClass objects.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Defining Methods
Next page: Passing Information to a Method or a Constructor


Passing Information to a Method or a Constructor (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: Classes
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Passing Information to a Method or a Constructor
The declaration for a method or a constructor declares the number and the type of the arguments for that method or constructor. For example, the following is a method that computes the monthly payments for a home loan, based on the amount of the loan, the interest rate, the length of the loan (the number of periods), and the future value of the loan:
public double computePayment(double loanAmt,
                             double rate,
                             double futureValue,
                             int numPeriods) {
    double interest = rate / 100.0;
    double partial1 = Math.pow((1 + interest), -numPeriods);
    double denominator = (1 - partial1) / interest;
    double answer = (-loanAmt / denominator)
                    - ((futureValue * partial1) / denominator);
    return answer;
}
This method has four parameters: the loan amount, the interest rate, the future value and the number of periods. The first three are double-precision floating point numbers, and the fourth is an integer. The parameters are used in the method body and at runtime will take on the values of the arguments that are passed in.

Note : Parameters refers to the list of variables in a method declaration. Arguments are the actual values that are passed in when the method is invoked. When you invoke a method, the arguments used must match the declaration's parameters in type and order.

Parameter Types

You can use any data type for a parameter of a method or a constructor. This includes primitive data types, such as doubles, floats, and integers, as you saw in the computePayment method, and reference data types, such as objects and arrays.

Here's an example of a method that accepts an array as an argument. In this example, the method creates a new Polygon object and initializes it from an array of Point objects (assume that Point is a class that represents an x, y coordinate):

public Polygon polygonFrom(Point[] corners) {
    // method body goes here
}

Note : The Java programming language doesn't let you pass methods into methods. But you can pass an object into a method and then invoke the object's methods.

Arbitrary Number of Arguments

You can use a construct called varargs to pass an arbitrary number of values to a method. You use varargs when you don't know how many of a particular type of argument will be passed to the method. It's a shortcut to creating an array manually (the previous method could have used varargs rather than an array).

To use varargs, you follow the type of the last parameter by an ellipsis (three dots, ...), then a space, and the parameter name. The method can then be called with any number of that parameter, including none.

public Polygon polygonFrom(Point... corners) {
    int numberOfSides = corners.length;
    double squareOfSide1, lengthOfSide1;
    squareOfSide1 = (corners[1].x - corners[0].x)*(corners[1].x - corners[0].x)
            + (corners[1].y - corners[0].y)*(corners[1].y - corners[0].y) ;
    lengthOfSide1 = Math.sqrt(squareOfSide1);
    // more method body code follows that creates
    // and returns a polygon connecting the Points
}
You can see that, inside the method, corners is treated like an array. The method can be called either with an array or with a sequence of arguments. The code in the method body will treat the parameter as an array in either case.

You will most commonly see varargs with the printing methods; for example, this printf method:

public PrintStream printf(String format, Object... args)
allows you to print an arbitrary number of objects. It can be called like this:
System.out.printf("%s: %d, %s%n", name, idnum, address);
or like this
System.out.printf("%s: %d, %s, %s, %s%n", name, idnum, address, phone, email);
or with yet a different number of arguments.

Parameter Names

When you declare a parameter to a method or a constructor, you provide a name for that parameter. This name is used within the method body to refer to the passed-in argument.

The name of a parameter must be unique in its scope. It cannot be the same as the name of another parameter for the same method or constructor, and it cannot be the name of a local variable within the method or constructor.

A parameter can have the same name as one of the class's fields. If this is the case, the parameter is said to shadow the field. Shadowing fields can make your code difficult to read and is conventionally used only within constructors and methods that set a particular field. For example, consider the following Circle class and its setOrigin method:

public class Circle {
    private int x, y, radius;
    public void setOrigin(int x, int y) {
        ...
    }
}
The Circle class has three fields: x, y, and radius. The setOrigin method has two parameters, each of which has the same name as one of the fields. Each method parameter shadows the field that shares its name. So using the simple names x or y within the body of the method refers to the parameter, not to the field. To access the field, you must use a qualified name. This will be discussed later in this lesson in the section titled "Using the this Keyword."

Passing Primitive Data Type Arguments

Primitive arguments, such as an int or a double, are passed into methods by value. This means that any changes to the values of the parameters exist only within the scope of the method. When the method returns, the parameters are gone and any changes to them are lost. Here is an example:
public class PassPrimitiveByValue {

    public static void main(String[] args) {

        int x = 3;

        //invoke passMethod() with x as argument
        passMethod(x);

        // print x to see if its value has changed
        System.out.println("After invoking passMethod, x = " + x);

    }

    // change parameter in passMethod()
    public static void passMethod(int p) {
        p = 10;
    }
}
When you run this program, the output is:
After invoking passMethod, x = 3

Passing Reference Data Type Arguments

Reference data type parameters, such as objects, are also passed into methods by value. This means that when the method returns, the passed-in reference still references the same object as before. However, the values of the object's fields can be changed in the method, if they have the proper access level.

For example, consider a method in an arbitrary class that moves Circle objects:

public void moveCircle(Circle circle, int deltaX, int deltaY) {
    // code to move origin of circle to x+deltaX, y+deltaY
    circle.setX(circle.getX() + deltaX);
    circle.setY(circle.getY() + deltaY);

    //code to assign a new reference to circle
    circle = new Circle(0, 0);
}
Let the method be invoked with these arguments:
moveCircle(myCircle, 23, 56)
Inside the method, circle initially refers to myCircle. The method changes the x and y coordinates of the object that circle references (i.e., myCircle) by 23 and 56, respectively. These changes will persist when the method returns. Then circle is assigned a reference to a new Circle object with x = y = 0. This reassignment has no permanence, however, because the reference was passed in by value and cannot change. Within the method, the object pointed to by circle has changed, but, when the method returns, myCircle still references the same Circle object as before the method was called.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Providing Constructors for Your Classes
Next page: Objects


Objects (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Objects
A typical Java program creates many objects, which as you know, interact by invoking methods Through these object interactions, a program can carry out various tasks, such as implementing a GUI, running an animation, or sending and receiving information over a network. Once an object has completed the work for which it was created, its resources are recycled for use by other objects.

Here's a small program, called CreateObjectDemo, that creates three objects: one Point object and two Rectangle objects. You will need all three source files to compile this program.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class CreateObjectDemo {

    public static void main(String[] args) {

        //Declare and create a point object
        //and two rectangle objects.
        Point originOne = new Point(23, 94);
        Rectangle rectOne = new Rectangle(originOne, 100, 200);
        Rectangle rectTwo = new Rectangle(50, 100);

        //display rectOne's width, height, and area
        System.out.println("Width of rectOne: " +
                rectOne.width);
        System.out.println("Height of rectOne: " +
                rectOne.height);
        System.out.println("Area of rectOne: " + rectOne.getArea());

        //set rectTwo's position
        rectTwo.origin = originOne;

        //display rectTwo's position
        System.out.println("X Position of rectTwo: "
                + rectTwo.origin.x);
        System.out.println("Y Position of rectTwo: "
                + rectTwo.origin.y);

        //move rectTwo and display its new position
        rectTwo.move(40, 72);
        System.out.println("X Position of rectTwo: "
                + rectTwo.origin.x);
        System.out.println("Y Position of rectTwo: "
                + rectTwo.origin.y);
    }
}
This program creates, manipulates, and displays information about various objects. Here's the output:
Width of rectOne: 100
Height of rectOne: 200
Area of rectOne: 20000
X Position of rectTwo: 23
Y Position of rectTwo: 94
X Position of rectTwo: 40
Y Position of rectTwo: 72

The following three sections use the above example to describe the life cycle of an object within a program. From them, you will learn how to write code that creates and uses objects in your own programs. You will also learn how the system cleans up after an object when its life has ended.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Passing Information to a Method or a Constructor
Next page: Creating Objects


Creating Objects (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: Objects
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Creating Objects
As you know, a class provides the blueprint for objects; you create an object from a class. Each of the following statements taken from the CreateObjectDemo program creates an object and assigns it to a variable:
Point originOne = new Point(23, 94);
Rectangle rectOne = new Rectangle(originOne, 100, 200);
Rectangle rectTwo = new Rectangle(50, 100);
The first line creates an object of the Point class, and the second and third lines each create an object of the Rectangle class.

Each of these statements has three parts (discussed in detail below):

  1. Declaration: The code set in bold are all variable declarations that associate a variable name with an object type.
  2. Instantiation: The new keyword is a Java operator that creates the object.
  3. Initialization: The new operator is followed by a call to a constructor, which initializes the new object.

Declaring a Variable to Refer to an Object

 Previously, you learned that to declare a variable, you write:
type name;
This notifies the compiler that you will use name to refer to data whose type is type. With a primitive variable, this declaration also reserves the proper amount of memory for the variable.

You can also declare a reference variable on its own line. For example:

Point originOne;
If you declare originOne like this, its value will be undetermined until an object is actually created and assigned to it. Simply declaring a reference variable does not create an object. For that, you need to use the new operator, as described in the next section. You must assign an object to originOne before you use it in your code. Otherwise, you will get a compiler error.

A variable in this state, which currently references no object, can be illustrated as follows (the variable name, originOne, plus a reference pointing to nothing):

originOne is null.

Instantiating a Class

 The new operator instantiates a class by allocating memory for a new object and returning a reference to that memory. The new operator also invokes the object constructor.

Note: The phrase "instantiating a class" means the same thing as "creating an object." When you create an object, you are creating an "instance" of a class, therefore "instantiating" a class.

The new operator requires a single, postfix argument: a call to a constructor. The name of the constructor provides the name of the class to instantiate.

The new operator returns a reference to the object it created. This reference is usually assigned to a variable of the appropriate type, like:

Point originOne = new Point(23, 94);
The reference returned by the new operator does not have to be assigned to a variable. It can also be used directly in an expression. For example:
int height = new Rectangle().height;
This statement will be discussed in the next section.

Initializing an Object

Here's the code for the Point class:
public class Point {
    public int x = 0;
    public int y = 0;
    //constructor
    public Point(int a, int b) {
    x = a;
    y = b;
    }
}
This class contains a single constructor. You can recognize a constructor because its declaration uses the same name as the class and it has no return type. The constructor in the Point class takes two integer arguments, as declared by the code (int a, int b). The following statement provides 23 and 94 as values for those arguments:
Point originOne = new Point(23, 94);
The result of executing this statement can be illustrated in the next figure:

originOne now points to a Point object.

Here's the code for the Rectangle class, which contains four constructors:
public class Rectangle {
    public int width = 0;
    public int height = 0;
    public Point origin;

    // four constructors
    public Rectangle() {
    origin = new Point(0, 0);
    }
    public Rectangle(Point p) {
    origin = p;
    }
    public Rectangle(int w, int h) {
    origin = new Point(0, 0);
    width = w;
    height = h;
    }
    public Rectangle(Point p, int w, int h) {
    origin = p;
    width = w;
    height = h;
    }

    // a method for moving the rectangle
    public void move(int x, int y) {
    origin.x = x;
    origin.y = y;
    }

    // a method for computing the area of the rectangle
    public int getArea() {
    return width * height;
    }
}
Each constructor lets you provide initial values for the rectangle's size and width, using both primitive and reference types. If a class has multiple constructors, they must have different signatures. The Java compiler differentiates the constructors based on the number and the type of the arguments. When the Java compiler encounters the following code, it knows to call the constructor in the Rectangle class that requires a Point argument followed by two integer arguments:

Rectangle rectOne = new Rectangle(originOne, 100, 200);
This calls one of Rectangle's constructors that initializes origin to originOne. Also, the constructor sets width to 100 and height to 200. Now there are two references to the same Point object— an object can have multiple references to it, as shown in the next figure:

Now the rectangle's origin variable also points to the Point.

The following line of code calls the Rectangle constructor that requires two integer arguments, which provide the initial values for width and height. If you inspect the code within the constructor, you will see that it creates a new Point object whose x and y values are initialized to 0:
Rectangle rectTwo = new Rectangle(50, 100);
The Rectangle constructor used in the following statement doesn't take any arguments, so it's called a no-argument constructor:
Rectangle rect = new Rectangle();
All classes have at least one constructor. If a class does not explicitly declare any, the Java compiler automatically provides a no-argument constructor, called the default constructor. This default constructor calls the class parent's no-argument constructor, or the Object constructor if the class has no other parent. If the parent has no constructor (Object does have one), the compiler will reject the program.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Objects
Next page: Using Objects


Using Objects (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: Objects
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Using Objects
Once you've created an object, you probably want to use it for something. You may need to use the value of one of its fields, change one of its fields, or call one of its methods to perform an action.

Referencing an Object's Fields

Object fields are accessed by their name. You must use a name that is unambiguous.

You may use a simple name for a field within its own class. For example, we can add a statement within the Rectangle class that prints the width and height:

System.out.println("Width and height are: " + width + ", " + height);
In this case, width and height are simple names.

Code that is outside the object's class must use an object reference or expression, followed by the dot (.) operator, followed by a simple field name, as in:

objectReference.fieldName

For example, the code in the CreateObjectDemo class is outside the code for the Rectangle class. So to refer to the origin, width, and height fields within the Rectangle object named rectOne, the CreateObjectDemo class must use the names rectOne.origin, rectOne.width, and rectOne.height, respectively. The program uses two of these names to display the width and the height of rectOne:

System.out.println("Width of rectOne: " + rectOne.width);
System.out.println("Height of rectOne: " + rectOne.height);
Attempting to use the simple names width and height from the code in the CreateObjectDemo class doesn't make sense — those fields exist only within an object — and results in a compiler error.

Later, the program uses similar code to display information about rectTwo. Objects of the same type have their own copy of the same instance fields. Thus, each Rectangle object has fields named origin, width, and height. When you access an instance field through an object reference, you reference that particular object's field. The two objects rectOne and rectTwo in the CreateObjectDemo program have different origin, width, and height fields.

To access a field, you can use a named reference to an object, as in the previous examples, or you can use any expression that returns an object reference. Recall that the new operator returns a reference to an object. So you could use the value returned from new to access a new object's fields:

int height = new Rectangle().height;
This statement creates a new Rectangle object and immediately gets its height. In essence, the statement calculates the default height of a Rectangle. Note that after this statement has been executed, the program no longer has a reference to the created Rectangle, because the program never stored the reference anywhere. The object is unreferenced, and its resources are free to be recycled by the Java Virtual Machine.

Calling an Object's Methods

 You also use an object reference to invoke an object's method. You append the method's simple name to the object reference, with an intervening dot operator (.). Also, you provide, within enclosing parentheses, any arguments to the method. If the method does not require any arguments, use empty parentheses.
objectReference.methodName(argumentList);
   or
objectReference.methodName();
The Rectangle class has two methods: getArea() to compute the rectangle's area and move() to change the rectangle's origin. Here's the CreateObjectDemo code that invokes these two methods:
System.out.println("Area of rectOne: " + rectOne.getArea());
...
rectTwo.move(40, 72);
The first statement invokes rectOne's getArea() method and displays the results. The second line moves rectTwo because the move() method assigns new values to the object's origin.x and origin.y.

As with instance fields, objectReference must be a reference to an object. You can use a variable name, but you also can use any expression that returns an object reference. The new operator returns an object reference, so you can use the value returned from new to invoke a new object's methods:

new Rectangle(100, 50).getArea()
The expression new Rectangle(100, 50) returns an object reference that refers to a Rectangle object. As shown, you can use the dot notation to invoke the new Rectangle's getArea() method to compute the area of the new rectangle.

Some methods, such as getArea(), return a value. For methods that return a value, you can use the method invocation in expressions. You can assign the return value to a variable, use it to make decisions, or control a loop. This code assigns the value returned by getArea() to the variable areaOfRectangle:

int areaOfRectangle = new Rectangle(100, 50).getArea();
Remember, invoking a method on a particular object is the same as sending a message to that object. In this case, the object that getArea() is invoked on is the rectangle returned by the constructor.

The Garbage Collector

Some object-oriented languages require that you keep track of all the objects you create and that you explicitly destroy them when they are no longer needed. Managing memory explicitly is tedious and error-prone. The Java platform allows you to create as many objects as you want (limited, of course, by what your system can handle), and you don't have to worry about destroying them. The Java runtime environment deletes objects when it determines that they are no longer being used. This process is called garbage collection.

An object is eligible for garbage collection when there are no more references to that object. References that are held in a variable are usually dropped when the variable goes out of scope. Or, you can explicitly drop an object reference by setting the variable to the special value null. Remember that a program can have multiple references to the same object; all references to an object must be dropped before the object is eligible for garbage collection.

The Java runtime environment has a garbage collector that periodically frees the memory used by objects that are no longer referenced. The garbage collector does its job automatically when it determines that the time is right.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating Objects
Next page: More on Classes


More on Classes (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
More on Classes
This section covers more aspects of classes that depend on using object references and the dot operator that you learned about in the preceding sections on objects:
  • Returning values from methods.
  • The this keyword.
  • Class vs. instance members.
  • Access control.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Objects
Next page: Returning a Value from a Method


Returning a Value from a Method (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: More on Classes
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Returning a Value from a Method
A method returns to the code that invoked it when it
  • completes all the statements in the method,
  • reaches a return statement, or
  • throws an exception (covered later),
whichever occurs first.

You declare a method's return type in its method declaration. Within the body of the method, you use the return statement to return the value.

Any method declared void doesn't return a value. It does not need to contain a return statement, but it may do so. In such a case, a return statement can be used to branch out of a control flow block and exit the method and is simply used like this:

 return;
If you try to return a value from a method that is declared void, you will get a compiler error.

Any method that is not declared void must contain a return statement with a corresponding return value, like this:

 return returnValue;
The data type of the return value must match the method's declared return type; you can't return an integer value from a method declared to return a boolean.

The getArea() method in the Rectangle Rectangle class that was discussed in the sections on objects returns an integer:

    // a method for computing the area of the rectangle
    public int getArea() {
    return width * height;
    }
This method returns the integer that the expression width*height evaluates to.

The area method returns a primitive type. A method can also return a reference type. For example, in a program to manipulate Bicycle objects, we might have a method like this:

public Bicycle seeWhosFastest(Bicycle myBike, Bicycle yourBike, Environment env) {
  Bicycle fastest;
  // code to calculate which bike is faster, given
  // each bike's gear and cadence and given
  // the environment (terrain and wind)
  return fastest;
}

Returning a Class or Interface

If this section confuses you, skip it and return to it after you have finished the lesson on interfaces and inheritance.

When a method uses a class name as its return type, such as whosFastest does, the class of the type of the returned object must be either a subclass of, or the exact class of, the return type. Suppose that you have a class hierarchy in which ImaginaryNumber is a subclass of java.lang.Number, which is in turn a subclass of Object, as illustrated in the following figure.

The class hierarchy for ImaginaryNumber

The class hierarchy for ImaginaryNumber

Now suppose that you have a method declared to return a Number:
public Number returnANumber() {
    ...
}
The returnANumber method can return an ImaginaryNumber but not an Object. ImaginaryNumber is a Number because it's a subclass of Number. However, an Object is not necessarily a Number — it could be a String or another type.

You can override a method and define it to return a subclass of the original method, like this:

public ImaginaryNumber returnANumber() {
    ...
}
This technique, called covariant return type, means that the return type is allowed to vary in the same direction as the subclass.
Note: You also can use interface names as return types. In this case, the object returned must implement the specified interface.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: More on Classes
Next page: Using the this Keyword


Using the this Keyword (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: More on Classes
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Using the this Keyword
Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called. You can refer to any member of the current object from within an instance method or a constructor by using this.

Using this with a Field

The most common reason for using the this keyword is because a field is shadowed by a method or constructor parameter.

For example, the Point class was written like this

public class Point {
    public int x = 0;
    public int y = 0;

    //constructor
    public Point(int a, int b) {
    x = a;
    y = b;
    }
}
but it could have been written like this:
public class Point {
    public int x = 0;
    public int y = 0;

    //constructor
    public Point(int x, int y) {
    this.x = x;
    this.y = y;
    }
}
Each argument to the second constructor shadows one of the object's fields—inside the constructor x is a local copy of the constructor's first argument. To refer to the Point field x, the constructor must use this.x.

Using this with a Constructor

From within a constructor, you can also use the this keyword to call another constructor in the same class. Doing so is called an explicit constructor invocation. Here's another Rectangle class, with a different implementation from the one in the Objects section.
public class Rectangle {
    private int x, y;
    private int width, height;

    public Rectangle() {
        this(0, 0, 0, 0);
    }
    public Rectangle(int width, int height) {
        this(0, 0, width, height);
    }
    public Rectangle(int x, int y, int width, int height) {
        this.x = x;
        this.y = y;
        this.width = width;
        this.height = height;
    }
    ...
}
This class contains a set of constructors. Each constructor initializes some or all of the rectangle's member variables. The constructors provide a default value for any member variable whose initial value is not provided by an argument. For example, the no-argument constructor calls the four-argument constructor with four 0 values and the two-argument constructor calls the four-argument constructor with two 0 values. As before, the compiler determines which constructor to call, based on the number and the type of arguments.

If present, the invocation of another constructor must be the first line in the constructor.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Returning a Value from a Method
Next page: Controlling Access to Members of a Class


Controlling Access to Members of a Class (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: More on Classes
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Controlling Access to Members of a Class
Access level modifiers determine whether other classes can use a particular field or invoke a particular method. There are two levels of access control:
  • At the top level—public, or package-private (no explicit modifier).
  • At the member level—public, private, protected, or package-private (no explicit modifier).

A class may be declared with the modifier public, in which case that class is visible to all classes everywhere. If a class has no modifier (the default, also known as package-private), it is visible only within its own package (packages are named groups of related classes—you will learn about them in a later lesson.)

At the member level, you can also use the public modifier or no modifier (package-private) just as with top-level classes, and with the same meaning. For members, there are two additional access modifiers: private and protected. The private modifier specifies that the member can only be accessed in its own class. The protected modifier specifies that the member can only be accessed within its own package (as with package-private) and, in addition, by a subclass of its class in another package.

The following table shows the access to members permitted by each modifier.

Access Levels
Modifier | Class | Package | Subclass | World
public | Y | Y | Y | Y
protected | Y | Y | Y | N
no modifier | Y | Y | N | N
private | Y | N | N | N
The first data column indicates whether the class itself has access to the member defined by the access level. As you can see, a class always has access to its own members. The second column indicates whether classes in the same package as the class (regardless of their parentage) have access to the member. The third column indicates whether subclasses of the class — declared outside this package — have access to the member. The fourth column indicates whether all classes have access to the member.

Access levels affect you in two ways. First, when you use classes that come from another source, such as the classes in the Java platform, access levels determine which members of those classes your own classes can use. Second, when you write a class, you need to decide what access level every member variable and every method in your class should have.

Let's look at a collection of classes and see how access levels affect visibility. The following figure shows the four classes in this example and how they are related.

Classes and Packages of the Example Used to Illustrate Access Levels

Classes and Packages of the Example Used to Illustrate Access Levels

The following table shows where the members of the Alpha class are visible for each of the access modifiers that can be applied to them.
Visibility
Modifier | Alpha | Beta | Alphasub | Gamma
public | Y | Y | Y | Y
protected | Y | Y | Y | N
no modifier | Y | Y | N | N
private | Y | N | N | N

Tips on Choosing an Access Level: If other programmers use your class, you want to ensure that errors from misuse cannot happen. Access levels can help you do this.
  • Use the most restrictive access level that makes sense for a particular member. Use private unless you have a good reason not to.
  • Avoid public fields except for constants. (Many of the examples in the tutorial use public fields. This may help to illustrate some points concisely, but is not recommended for production code.) Public fields tend to link you to a particular implementation and limit your flexibility in changing your code.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using the this Keyword
Next page: Understanding Instance and Class Members


Understanding Instance and Class Members (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: More on Classes
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Understanding Instance and Class Members
In this section, we discuss the use of the static keyword to create fields and methods that belong to the class, rather than to an instance of the class.

Class Variables

When a number of objects are created from the same class blueprint, they each have their own distinct copies of instance variables. In the case of the Bicycle class, the instance variables are cadence, gear, and speed. Each Bicycle object has its own values for these variables, stored in different memory locations.

Sometimes, you want to have variables that are common to all objects. This is accomplished with the static modifier. Fields that have the static modifier in their declaration are called static fields or class variables. They are associated with the class, rather than with any object. Every instance of the class shares a class variable, which is in one fixed location in memory. Any object can change the value of a class variable, but class variables can also be manipulated without creating an instance of the class.

For example, suppose you want to create a number of Bicycle objects and assign each a serial number, beginning with 1 for the first object. This ID number is unique to each object and is therefore an instance variable. At the same time, you need a field to keep track of how many Bicycle objects have been created so that you know what ID to assign to the next one. Such a field is not related to any individual object, but to the class as a whole. For this you need a class variable, numberOfBicycles, as follows:

public class Bicycle{

    private int cadence;
    private int gear;
    private int speed;

    // add an instance variable for the object ID
    private int id;

    // add a class variable for the number of Bicycle objects instantiated
    private static int numberOfBicycles = 0;
    ......
}
Class variables are referenced by the class name itself, as in
    Bicycle.numberOfBicycles
This makes it clear that they are class variables.
Note: You can also refer to static fields with an object reference like
    myBike.numberOfBicycles
but this is discouraged because it does not make it clear that they are class variables.

You can use the Bicycle constructor to set the id instance variable and increment the numberOfBicycles class variable:

public class Bicycle{

    private int cadence;
    private int gear;
    private int speed;
    private int id;
    private static int numberOfBicycles = 0;

    public Bicycle(int startCadence, int startSpeed, int startGear){
        gear = startGear;
        cadence = startCadence;
        speed = startSpeed;

        // increment number of Bicycles and assign ID number
        id = ++numberOfBicycles;
    }

    // new method to return the ID instance variable
    public int getID() {
        return id;
    }
    .....
}

Class Methods

The Java programming language supports static methods as well as static variables. Static methods, which have the static modifier in their declarations, should be invoked with the class name, without the need for creating an instance of the class, as in
ClassName.methodName(args)
Note: You can also refer to static methods with an object reference like
    instanceName.methodName(args)
but this is discouraged because it does not make it clear that they are class methods.

A common use for static methods is to access static fields. For example, we could add a static method to the Bicycle class to access the numberOfBicycles static field:

public static int getNumberOfBicycles() {
    return numberOfBicycles;
}
Not all combinations of instance and class variables and methods are allowed:
  • Instance methods can access instance variables and instance methods directly.
  • Instance methods can access class variables and class methods directly.
  • Class methods can access class variables and class methods directly.
  • Class methods cannot access instance variables or instance methods directly—they must use an object reference. Also, class methods cannot use the this keyword as there is no instance for this to refer to.

Constants

The static modifier, in combination with the final modifier, is also used to define constants. The final modifier indicates that the value of this field cannot change.

For example, the following variable declaration defines a constant named PI, whose value is an approximation of pi (the ratio of the circumference of a circle to its diameter):

static final double PI = 3.141592653589793;
Constants defined in this way cannot be reassigned, and it is a compile-time error if your program tries to do so. By convention, the names of constant values are spelled in uppercase letters. If the name is composed of more than one word, the words are separated by an underscore (_).
Note: If a primitive type or a string is defined as a constant and the value is known at compile time, the compiler replaces the constant name everywhere in the code with its value. This is called a compile-time constant. If the value of the constant in the outside world changes (for example, if it is legislated that pi actually should be 3.975), you will need to recompile any classes that use this constant to get the current value.

The Bicycle Class

After all the modifications made in this section, the Bicycle class is now:
public class Bicycle{

    private int cadence;
    private int gear;
    private int speed;

    private int id;

    private static int numberOfBicycles = 0;

    public Bicycle(int startCadence, int startSpeed, int startGear){
        gear = startGear;
        cadence = startCadence;
        speed = startSpeed;

        id = ++numberOfBicycles;
    }

    public int getID() {
        return id;
    }

    public static int getNumberOfBicycles() {
        return numberOfBicycles;
    }

    public int getCadence(){
        return cadence;
    }

    public void setCadence(int newValue){
        cadence = newValue;
    }

    public int getGear(){
    return gear;
    }

    public void setGear(int newValue){
        gear = newValue;
    }

    public int getSpeed(){
        return speed;
    }

    public void applyBrake(int decrement){
        speed -= decrement;
    }

    public void speedUp(int increment){
        speed += increment;
    }

}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Controlling Access to Members of a Class
Next page: Initializing Fields


Initializing Fields (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: More on Classes
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Initializing Fields
As you have seen, you can often provide an initial value for a field in its declaration:
public class BedAndBreakfast {

    public static int capacity = 10;  //initialize to 10

    private boolean full = false;  //initialize to false
}
This works well when the initialization value is available and the initialization can be put on one line. However, this form of initialization has limitations because of its simplicity. If initialization requires some logic (for example, error handling or a for loop to fill a complex array), simple assignment is inadequate. Instance variables can be initialized in constructors, where error handling or other logic can be used. To provide the same capability for class variables, the Java programming language includes static initialization blocks.
Note: It is not necessary to declare fields at the beginning of the class definition, although this is the most common practice. It is only necessary that they be declared and initialized before they are used.

Static Initialization Blocks

A static initialization block is a normal block of code enclosed in braces, { }, and preceded by the static keyword. Here is an example:
static {

    // whatever code is needed for initialization goes here
}
A class can have any number of static initialization blocks, and they can appear anywhere in the class body. The runtime system guarantees that static initialization blocks are called in the order that they appear in the source code.

There is an alternative to static blocks —you can write a private static method:

class Whatever {
    public static varType myVar = initializeClassVariable();

    private static varType initializeClassVariable() {

        //initialization code goes here
    }
}
The advantage of private static methods is that they can be reused later if you need to reinitialize the class variable.

Initializing Instance Members

Normally, you would put code to initialize an instance variable in a constructor. There are two alternatives to using a constructor to initialize instance variables: initializer blocks and final methods.

Initializer blocks for instance variables look just like static initializer blocks, but without the static keyword:

{

    // whatever code is needed for initialization goes here
}
The Java compiler copies initializer blocks into every constructor. Therefore, this approach can be used to share a block of code between multiple constructors.

A final method cannot be overridden in a subclass. This is discussed in the lesson on interfaces and inheritance. Here is an example of using a final method for initializing an instance variable:

class Whatever {
    private varType myVar = initializeInstanceVariable();

    protected final varType initializeInstanceVariable() {

        //initialization code goes here
    }
}
This is especially useful if subclasses might want to reuse the initialization method. The method is final because calling non-final methods during instance initialization can cause problems. Joshua Bloch describes this in more detail in Effective Java.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Understanding Instance and Class Members
Next page: Summary of Creating and Using Classes and Objects


Summary of Creating and Using Classes and Objects (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: More on Classes
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Summary of Creating and Using Classes and Objects
A class declaration names the class and encloses the class body between braces. The class name can be preceded by modifiers. The class body contains fields, methods, and constructors for the class. A class uses fields to contain state information and uses methods to implement behavior. Constructors that initialize a new instance of a class use the name of the class and look like methods without a return type.

You control access to classes and members in the same way: by using an access modifier such as public in their declaration.

You specify a class variable or a class method by using the static keyword in the member's declaration. A member that is not declared as static is implicitly an instance member. Class variables are shared by all instances of a class and can be accessed through the class name as well as an instance reference. Instances of a class get their own copy of each instance variable, which must be accessed through an instance reference.

You create an object from a class by using the new operator and a constructor. The new operator returns a reference to the object that was created. You can assign the reference to a variable or use it directly.

Instance variables and methods that are accessible to code outside of the class that they are declared in can be referred to by using a qualified name. The qualified name of an instance variable looks like this:

objectReference.variableName
The qualified name of a method looks like this:
objectReference.methodName(argumentList)

  or

objectReference.methodName()
The garbage collector automatically cleans up unused objects. An object is unused if the program holds no more references to it. You can explicitly drop a reference by setting the variable holding the reference to null.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Initializing Fields
Next page: Questions and Exercises: Classes


Questions and Exercises: Classes (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Questions and Exercises: Classes

Questions

1. Consider the following class:
public class IdentifyMyParts {
    public static int x = 7;
    public int y = 3;
}
a. What are the class variables?

b. What are the instance variables?

c. What is the output from the following code:

IdentifyMyParts a = new IdentifyMyParts();
IdentifyMyParts b = new IdentifyMyParts();
a.y = 5;
b.y = 6;
a.x = 1;
b.x = 2;
System.out.println("a.y = " + a.y);
System.out.println("b.y = " + b.y);
System.out.println("a.x = " + a.x);
System.out.println("b.x = " + b.x);
System.out.println("IdentifyMyParts.x = " + IdentifyMyParts.x);

Exercises

1. Write a class whose instances represent a single playing card from a deck of cards. Playing cards have two distinguishing properties: rank and suit. Be sure to keep your solution as you will be asked to rewrite it in Enum Types.
Hint: You can use the assert statement to check your assignments. You write:
assert (boolean expression to test);
If the boolean expression is false, you will get an error message. For example,
assert toString(ACE) == "Ace";
should return true, so there will be no error message.

If you use the assert statement, you must run your program with the ea flag:

java -ea YourProgram.class
2. Write a class whose instances represent a full deck of cards. You should also keep this solution.

3. Write a small program to test your deck and card classes. The program can be as simple as creating a deck of cards and displaying its cards.

Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary of Creating and Using Classes and Objects
Next page: Questions and Exercises: Objects


Questions and Exercises: Objects (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Questions and Exercises: Objects

Questions

  1. What's wrong with the following program?
    public class SomethingIsWrong {
    public static void main(String[] args) {
        Rectangle myRect;
        myRect.width = 40;
        myRect.height = 50;
        System.out.println("myRect's area is " + myRect.area());
    }
}
  2. The following code creates one Point object and one Rectangle object. How many references to those objects exist after the code executes? Is either object eligible for garbage collection?
    ...
Point point = new Point(2,4);
Rectangle rectangle = new Rectangle(point, 20, 20);
point = null;
...
  3. How does a program destroy an object that it creates?

Exercises

  1. Fix the program called SomethingIsWrong shown in Question 1.
  2. Given the following class, called NumberHolder, write some code that creates an instance of the class, initializes its two member variables, and then displays the value of each member variable.
    public class NumberHolder {
   public int anInt;
   public float aFloat;
}
Check your answers.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Classes
Next page: Nested Classes


Nested Classes (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Nested Classes
The Java programming language allows you to define a class within another class. Such a class is called a nested class and is illustrated here:
class OuterClass {
    ...
    class NestedClass {
        ...
    }
}

Terminology: Nested classes are divided into two categories: static and non-static. Nested classes that are declared static are simply called static nested classes. Non-static nested classes are called inner classes.
class OuterClass {
    ...
    static class StaticNestedClass {
        ...
    }
    class InnerClass {
        ...
    }
}
A nested class is a member of its enclosing class. Non-static nested classes (inner classes) have access to other members of the enclosing class, even if they are declared private. Static nested classes do not have access to other members of the enclosing class. As a member of the OuterClass, a nested class can be declared private, public, protected, or package private. (Recall that outer classes can only be declared public or package private.)

Why Use Nested Classes?

There are several compelling reasons for using nested classes, among them:
  • It is a way of logically grouping classes that are only used in one place.
  • It increases encapsulation.
  • Nested classes can lead to more readable and maintainable code.

Logical grouping of classes—If a class is useful to only one other class, then it is logical to embed it in that class and keep the two together. Nesting such "helper classes" makes their package more streamlined.

Increased encapsulation—Consider two top-level classes, A and B, where B needs access to members of A that would otherwise be declared private. By hiding class B within class A, A's members can be declared private and B can access them. In addition, B itself can be hidden from the outside world.

More readable, maintainable code—Nesting small classes within top-level classes places the code closer to where it is used.

Static Nested Classes

As with class methods and variables, a static nested class is associated with its outer class. And like static class methods, a static nested class cannot refer directly to instance variables or methods defined in its enclosing class — it can use them only through an object reference.

Note: A static nested class interacts with the instance members of its outer class (and other classes) just like any other top-level class. In effect, a static nested class is behaviorally a top-level class that has been nested in another top-level class for packaging convenience.

Static nested classes are accessed using the enclosing class name:

OuterClass.StaticNestedClass
For example, to create an object for the static nested class, use this syntax:
OuterClass.StaticNestedClass nestedObject = new OuterClass.StaticNestedClass();

Inner Classes

As with instance methods and variables, an inner class is associated with an instance of its enclosing class and has direct access to that object's methods and fields. Also, because an inner class is associated with an instance, it cannot define any static members itself.

Objects that are instances of an inner class exist within an instance of the outer class. Consider the following classes:

class OuterClass {
    ...
    class InnerClass {
        ...
    }
}
An instance of InnerClass can exist only within an instance of OuterClass and has direct access to the methods and fields of its enclosing instance. The next figure illustrates this idea.

An InnerClass Exists Within an Instance of OuterClass.

An InnerClass Exists Within an Instance of OuterClass

To instantiate an inner class, you must first instantiate the outer class. Then, create the inner object within the outer object with this syntax:

OuterClass.InnerClass innerObject = outerObject.new InnerClass();
Additionally, there are two special kinds of inner classes: local classes and anonymous classes (also called anonymous inner classes). Both of these will be discussed briefly in the next section.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Objects
Next page: Inner Class Example


Inner Class Example (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: Nested Classes
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Inner Class Example
To see an inner class in use, let's first consider an array. In the following example, we will create an array, fill it with integer values and then output only values of even indices of the array in ascending order.

The DataStructure class below consists of:

  • The DataStructure outer class, which includes methods to add an integer onto the array and print out values of even indices of the array.
  • The InnerEvenIterator inner class, which is similar to a standard Java iterator. Iterators are used to step through a data structure and typically have methods to test for the last element, retrieve the current element, and move to the next element.
  • A main method that instantiates a DataStructure object (ds) and uses it to fill the arrayOfInts array with integer values (0, 1, 2, 3, etc.), then calls a printEven method to print out values of even indices of arrayOfInts.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class DataStructure {
    //create an array
    private final static int SIZE = 15;
    private int[] arrayOfInts = new int[SIZE];

    public DataStructure() {
        //fill the array with ascending integer values
        for (int i = 0; i < SIZE; i++) {
            arrayOfInts[i] = i;
        }
    }

    public void printEven() {
        //print out values of even indices of the array
        InnerEvenIterator iterator = this.new InnerEvenIterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.getNext() + " ");
        }
    }

//inner class implements the Iterator pattern
    private class InnerEvenIterator {
        //start stepping through the array from the beginning
        private int next = 0;

        public boolean hasNext() {
            //check if a current element is the last in the array
            return (next <= SIZE - 1);
        }

        public int getNext() {
            //record a value of an even index of the array
            int retValue = arrayOfInts[next];
            //get the next even element
            next += 2;
            return retValue;
        }
    }

    public static void main(String s[]) {
        //fill the array with integer values and print out only values of even indices
        DataStructure ds = new DataStructure();
        ds.printEven();
    }
}
The output is:
0 2 4 6 8 10 12 14
Note that the InnerEvenIterator class refers directly to the arrayOfInts instance variable of the DataStructure object.

Inner classes can be used to implement helper classes like the one shown in the example above. If you plan on handling user-interface events, you will need to know how to use inner classes because the event-handling mechanism makes extensive use of them.

Local and Anonymous Inner Classes

There are two additional types of inner classes. You can declare an inner class within the body of a method. Such a class is known as a local inner class. You can also declare an inner class within the body of a method without naming it. These classes are known as anonymous inner classes. You will encounter such classes in advanced Java programming.

Modifiers

You can use the same modifiers for inner classes that you use for other members of the outer class. For example, you can use the access specifiers — private, public, and protected — to restrict access to inner classes, just as you do to other class members.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Nested Classes
Next page: Summary of Nested Classes


Summary of Nested Classes (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Section: Nested Classes
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Summary of Nested Classes
A class defined within another class is called a nested class. Like other members of a class, a nested class can be declared static or not. A nonstatic nested class is called an inner class. An instance of an inner class can exist only within an instance of its enclosing class and has access to its enclosing class's members even if they are declared private.

The following table shows the types of nested classes:

Types of Nested Classes
Type | Scope | Inner
static nested class | member | no
inner [non-static] class | member | yes
local class | local | yes
anonymous class | only the point where it is defined | yes
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Inner Class Example
Next page: Questions and Exercises: Nested Classes


Questions and Exercises: Nested Classes (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Questions and Exercises: Nested Classes

Questions

1. The program Problem.java doesn't compile. What do you need to do to make it compile? Why?

2. Use the Java API documentation for the Box class (in the javax.swing package) to help you answer the following questions.

a. What static nested class does Box define?
b. What inner class does Box define?
c. What is the superclass of Box’s inner class?
d. Which of Box’s nested classes can you use from any class?
e. How do you create an instance of Box’s Filler class?

Exercises

1. Get the file Class1.java.

Compile and run Class1. What is the output?
Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary of Nested Classes
Next page: Enum Types


Enum Types (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Enum Types
An enum type is a type whose fields consist of a fixed set of constants. Common examples include compass directions (values of NORTH, SOUTH, EAST, and WEST) and the days of the week.

Because they are constants, the names of an enum type's fields are in uppercase letters.

In the Java programming language, you define an enum type by using the enum keyword. For example, you would specify a days-of-the-week enum type as:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY,
    THURSDAY, FRIDAY, SATURDAY
}
You should use enum types any time you need to represent a fixed set of constants. That includes natural enum types such as the planets in our solar system and data sets where you know all possible values at compile time—for example, the choices on a menu, command line flags, and so on.

Here is some code that shows you how to use the Day enum defined above:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class EnumTest {
    Day day;

    public EnumTest(Day day) {
        this.day = day;
    }

    public void tellItLikeItIs() {
        switch (day) {
            case MONDAY: System.out.println("Mondays are bad.");
                         break;

            case FRIDAY: System.out.println("Fridays are better.");
                         break;

            case SATURDAY:
            case SUNDAY: System.out.println("Weekends are best.");
                         break;

            default:	 System.out.println("Midweek days are so-so.");
                         break;
        }
    }

    public static void main(String[] args) {
        EnumTest firstDay = new EnumTest(Day.MONDAY);
        firstDay.tellItLikeItIs();
        EnumTest thirdDay = new EnumTest(Day.WEDNESDAY);
        thirdDay.tellItLikeItIs();
        EnumTest fifthDay = new EnumTest(Day.FRIDAY);
        fifthDay.tellItLikeItIs();
        EnumTest sixthDay = new EnumTest(Day.SATURDAY);
        sixthDay.tellItLikeItIs();
        EnumTest seventhDay = new EnumTest(Day.SUNDAY);
        seventhDay.tellItLikeItIs();

    }
}
The output is:
Mondays are bad.
Midweek days are so-so.
Fridays are better.
Weekends are best.
Weekends are best.

Java programming language enum types are much more powerful than their counterparts in other languages. The enum declaration defines a class (called an enum type). The enum class body can include methods and other fields. The compiler automatically adds some special methods when it creates an enum. For example, they have a static values method that returns an array containing all of the values of the enum in the order they are declared. This method is commonly used in combination with the for-each construct to iterate over the values of an enum type. For example, this code from the Planet class example below iterates over all the planets in the solar system.

for (Planet p : Planet.values()) {
    System.out.printf("Your weight on %s is %f%n",
                          p, p.surfaceWeight(mass));
}
Note: All enums implicitly extend java.lang.Enum. Since Java does not support multiple inheritance, an enum cannot extend anything else.
In the following example, Planet is an enum type that represents the planets in the solar system. They are defined with constant mass and radius properties.

Each enum constant is declared with values for the mass and radius parameters. These values are passed to the constructor when the constant is created. Java requires that the constants be defined first, prior to any fields or methods. Also, when there are fields and methods, the list of enum constants must end with a semicolon.

Note: The constructor for an enum type must be package-private or private access. It automatically creates the constants that are defined at the beginning of the enum body. You cannot invoke an enum constructor yourself.
In addition to its properties and constructor, Planet has methods that allow you to retrieve the surface gravity and weight of an object on each planet. Here is a sample program that takes your weight on earth (in any unit) and calculates and prints your weight on all of the planets (in the same unit):
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public enum Planet {
    MERCURY (3.303e+23, 2.4397e6),
    VENUS   (4.869e+24, 6.0518e6),
    EARTH   (5.976e+24, 6.37814e6),
    MARS    (6.421e+23, 3.3972e6),
    JUPITER (1.9e+27,   7.1492e7),
    SATURN  (5.688e+26, 6.0268e7),
    URANUS  (8.686e+25, 2.5559e7),
    NEPTUNE (1.024e+26, 2.4746e7);

    private final double mass;   // in kilograms
    private final double radius; // in meters
    Planet(double mass, double radius) {
        this.mass = mass;
        this.radius = radius;
    }
    private double mass()   { return mass; }
    private double radius() { return radius; }

    // universal gravitational constant  (m3 kg-1 s-2)
    public static final double G = 6.67300E-11;

    double surfaceGravity() {
        return G * mass / (radius * radius);
    }
    double surfaceWeight(double otherMass) {
        return otherMass * surfaceGravity();
    }
    public static void main(String[] args) {
        double earthWeight = Double.parseDouble(args[0]);
        double mass = earthWeight/EARTH.surfaceGravity();
        for (Planet p : Planet.values())
           System.out.printf("Your weight on %s is %f%n",
                             p, p.surfaceWeight(mass));
    }
}
If you run Planet.class from the command line with an argument of 175, you get this output:
$ java Planet 175
Your weight on MERCURY is 66.107583
Your weight on VENUS is 158.374842
Your weight on EARTH is 175.000000
Your weight on MARS is 66.279007
Your weight on JUPITER is 442.847567
Your weight on SATURN is 186.552719
Your weight on URANUS is 158.397260
Your weight on NEPTUNE is 199.207413

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Nested Classes
Next page: Questions and Exercises: Enum Types


Questions and Exercises: Enum Types (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Questions and Exercises: Enum Types

Exercises

  1. Rewrite the class Card from the exercise in Questions and Exercises: Classes so that it represents the rank and suit of a card with enum types.

  2. Rewrite the Deck class.

Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Enum Types
Next page: Annotations


Annotations (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Annotations
Annotations provide data about a program that is not part of the program itself. They have no direct effect on the operation of the code they annotate.

Annotations have a number of uses, among them:

  • Information for the compiler — Annotations can be used by the compiler to detect errors or suppress warnings.

  • Compiler-time and deployment-time processing — Software tools can process annotation information to generate code, XML files, and so forth.

  • Runtime processing — Some annotations are available to be examined at runtime.
Annotations can be applied to a program's declarations of classes, fields, methods, and other program elements.

The annotation appears first, often (by convention) on its own line, and may include elements with named or unnamed values:

@Author(
   name = "Benjamin Franklin",
   date = "3/27/2003"
)
class MyClass() { }
or
@SuppressWarnings(value = "unchecked")
void myMethod() { }
If there is just one element named "value," then the name may be omitted, as in:
@SuppressWarnings("unchecked")
void myMethod() { }
Also, if an annotation has no elements, the parentheses may be omitted, as in:
@Override
void mySuperMethod() { }

Documentation

Many annotations replace what would otherwise have been comments in code.

Suppose that a software group has traditionally begun the body of every class with comments providing important information:

public class Generation3List extends Generation2List {

   // Author: John Doe
   // Date: 3/17/2002
   // Current revision: 6
   // Last modified: 4/12/2004
   // By: Jane Doe
   // Reviewers: Alice, Bill, Cindy

   // class code goes here

}
To add this same metadata with an annotation, you must first define the annotation type. The syntax for doing this is:
@interface ClassPreamble {
   String author();
   String date();
   int currentRevision() default 1;
   String lastModified() default "N/A";
   String lastModifiedBy() default "N/A";
   String[] reviewers();  // Note use of array
}
The annotation type definition looks somewhat like an interface definition where the keyword interface is preceded by the @ character (@ = "AT" as in Annotation Type). Annotation types are, in fact, a form of interface, which will be covered in a later lesson. For the moment, you do not need to understand interfaces.

The body of the annotation definition above contains annotation type element declarations, which look a lot like methods. Note that they may define optional default values.

Once the annotation type has been defined, you can use annotations of that type, with the values filled in, like this:

@ClassPreamble (
   author = "John Doe",
   date = "3/17/2002",
   currentRevision = 6,
   lastModified = "4/12/2004",
   lastModifiedBy = "Jane Doe"
   reviewers = {"Alice", "Bob", "Cindy"} // Note array notation
)
public class Generation3List extends Generation2List {

// class code goes here

}
Note: To make the information in @ClassPreamble appear in Javadoc-generated documentation, you must annotate the @ClassPreamble definition itself with the @Documented annotation:
import java.lang.annotation.*; // import this to use @Documented

@Documented
@interface ClassPreamble {

   // Annotation element definitions

}

Annotations Used by the Compiler

There are three annotation types that are predefined by the language specification itself: @Deprecated, @Override, and @SuppressWarnings.

@Deprecated—the @Deprecated annotation indicates that the marked element is deprecated and should no longer be used. The compiler generates a warning whenever a program uses a method, class, or field with the @Deprecated annotation. When an element is deprecated, it should also be documented using the Javadoc @deprecated tag, as shown in the following example. The use of the "@" symbol in both Javadoc comments and in annotations is not coincidental—they are related conceptually. Also, note that the Javadoc tag starts with a lowercase "d" and the annotation starts with an uppercase "D".

   // Javadoc comment follows
    /**
     * @deprecated
     * explanation of why it was deprecated
     */
    @Deprecated
    static void deprecatedMethod() { }
}

@Override—the @Override annotation informs the compiler that the element is meant to override an element declared in a superclass (overriding methods will be discussed in the the lesson titled "Interfaces and Inheritance").

   // mark method as a superclass method
   // that has been overridden
   @Override
   int overriddenMethod() { }
While it's not required to use this annotation when overriding a method, it helps to prevent errors. If a method marked with @Override fails to correctly override a method in one of its superclasses, the compiler generates an error.

@SuppressWarnings—the @SuppressWarnings annotation tells the compiler to suppress specific warnings that it would otherwise generate. In the example below, a deprecated method is used and the compiler would normally generate a warning. In this case, however, the annotation causes the warning to be suppressed.

   // use a deprecated method and tell
   // compiler not to generate a warning
   @SuppressWarnings("deprecation")
    void useDeprecatedMethod() {
        objectOne.deprecatedMethod(); //deprecation warning - suppressed
    }

Every compiler warning belongs to a category. The Java Language Specification lists two categories: "deprecation" and "unchecked." The "unchecked" warning can occur when interfacing with legacy code written before the advent of generics (discussed in the lesson titled "Generics"). To suppress more than one category of warnings, use the following syntax:

@SuppressWarnings({"unchecked", "deprecation"})

Annotation Processing

The more advanced uses of annotations include writing an annotation processor that can read a Java program and take actions based on its annotations. It might, for example, generate auxiliary source code, relieving the programmer of having to create boilerplate code that always follows predictable patterns. To facilitate this task, release 5.0 of the JDK includes an annotation processing tool, called apt. In release 6 of the JDK, the functionality of apt is a standard part of the Java compiler.

To make annotation information available at runtime, the annotation type itself must be annotated with @Retention(RetentionPolicy.RUNTIME), as follows:

import java.lang.annotation.*;

@Retention(RetentionPolicy.RUNTIME)
@interface AnnotationForRuntime {

   // Elements that give information
   // for runtime processing

}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Enum Types
Next page: Questions and Exercises: Annotations


Questions and Exercises: Annotations (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises
Questions and Exercises
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises
Enum Types
Questions and Exercises
Annotations
Questions and Exercises
Home Page > Learning the Java Language > Classes and Objects
« Previous • Trail • Next »
Questions and Exercises: Annotations

Questions

1. What is wrong with the following interface?
public interface House {
    @Deprecated
    void open();
    void openFrontDoor();
    void openBackDoor();
}
2. Compile this program:
interface Closable {
    void close();
}

class File implements Closable {
    @Override
    public void close() {
        //... close this file...
    }
}
What happens? Can you explain why?

3. Consider this implementation of the House interface, shown in Question 1.

public class MyHouse implements House {
    public void open() {}
    public void openFrontDoor() {}
    public void openBackDoor() {}
}
If you compile this program, the compiler complains that open has been deprecated (in the interface). What can you do to get rid of that warning?

Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Annotations
Next page: Interfaces and Inheritance


Lesson: Interfaces and Inheritance (The Java™ Tutorials > Learning the Java Language)

Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Trail: Learning the Java Language
Home Page > Learning the Java Language
« Previous • Trail • Next »
Lesson: Interfaces and Inheritance

Interfaces

You saw an example of implementing an interface in the previous lesson. You can read more about interfaces here—what they are for, why you might want to write one, and how to write one.

Inheritance

This section describes the way in which you can derive one class from another. That is, how a subclass can inherit fields and methods from a superclass. You will learn that all classes are derived from the Object class, and how to modify the methods that a subclass inherits from superclasses. This section also covers interface-like abstract classes.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Interfaces


Interfaces (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Interfaces
There are a number of situations in software engineering when it is important for disparate groups of programmers to agree to a "contract" that spells out how their software interacts. Each group should be able to write their code without any knowledge of how the other group's code is written. Generally speaking, interfaces are such contracts.

For example, imagine a futuristic society where computer-controlled robotic cars transport passengers through city streets without a human operator. Automobile manufacturers write software (Java, of course) that operates the automobile—stop, start, accelerate, turn left, and so forth. Another industrial group, electronic guidance instrument manufacturers, make computer systems that receive GPS (Global Positioning Satellite) position data and wireless transmission of traffic conditions and use that information to drive the car.

The auto manufacturers must publish an industry-standard interface that spells out in detail what methods can be invoked to make the car move (any car, from any manufacturer). The guidance manufacturers can then write software that invokes the methods described in the interface to command the car. Neither industrial group needs to know how the other group's software is implemented. In fact, each group considers its software highly proprietary and reserves the right to modify it at any time, as long as it continues to adhere to the published interface.

Interfaces in Java

In the Java programming language, an interface is a reference type, similar to a class, that can contain only constants, method signatures, and nested types. There are no method bodies. Interfaces cannot be instantiated—they can only be implemented by classes or extended by other interfaces. Extension is discussed later in this lesson.

Defining an interface is similar to creating a new class:

public interface OperateCar {

   // constant declarations, if any

   // method signatures
   int turn(Direction direction,   // An enum with values RIGHT, LEFT
              double radius, double startSpeed, double endSpeed);
   int changeLanes(Direction direction, double startSpeed, double endSpeed);
   int signalTurn(Direction direction, boolean signalOn);
   int getRadarFront(double distanceToCar, double speedOfCar);
   int getRadarRear(double distanceToCar, double speedOfCar);
         ......
   // more method signatures
}
Note that the method signatures have no braces and are terminated with a semicolon.

To use an interface, you write a class that implements the interface. When an instantiable class implements an interface, it provides a method body for each of the methods declared in the interface. For example,

public class OperateBMW760i implements OperateCar {

   // the OperateCar method signatures, with implementation --
   // for example:
   int signalTurn(Direction direction, boolean signalOn) {
      //code to turn BMW's LEFT turn indicator lights on
      //code to turn BMW's LEFT turn indicator lights off
      //code to turn BMW's RIGHT turn indicator lights on
      //code to turn BMW's RIGHT turn indicator lights off
   }

   // other members, as needed -- for example, helper classes
   // not visible to clients of the interface

}
In the robotic car example above, it is the automobile manufacturers who will implement the interface. Chevrolet's implementation will be substantially different from that of Toyota, of course, but both manufacturers will adhere to the same interface. The guidance manufacturers, who are the clients of the interface, will build systems that use GPS data on a car's location, digital street maps, and traffic data to drive the car. In so doing, the guidance systems will invoke the interface methods: turn, change lanes, brake, accelerate, and so forth.

Interfaces as APIs

The robotic car example shows an interface being used as an industry standard Application Programming Interface (API). APIs are also common in commercial software products. Typically, a company sells a software package that contains complex methods that another company wants to use in its own software product. An example would be a package of digital image processing methods that are sold to companies making end-user graphics programs. The image processing company writes its classes to implement an interface, which it makes public to its customers. The graphics company then invokes the image processing methods using the signatures and return types defined in the interface. While the image processing company's API is made public (to its customers), its implementation of the API is kept as a closely guarded secret—in fact, it may revise the implementation at a later date as long as it continues to implement the original interface that its customers have relied on.

Interfaces and Multiple Inheritance

Interfaces have another very important role in the Java programming language. Interfaces are not part of the class hierarchy, although they work in combination with classes. The Java programming language does not permit multiple inheritance (inheritance is discussed later in this lesson), but interfaces provide an alternative.

In Java, a class can inherit from only one class but it can implement more than one interface. Therefore, objects can have multiple types: the type of their own class and the types of all the interfaces that they implement. This means that if a variable is declared to be the type of an interface, its value can reference any object that is instantiated from any class that implements the interface. This is discussed later in this lesson, in the section titled "Using an Interface as a Type."

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Interfaces and Inheritance
Next page: Defining an Interface


Defining an Interface (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Section: Interfaces
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Defining an Interface
An interface declaration consists of modifiers, the keyword interface, the interface name, a comma-separated list of parent interfaces (if any), and the interface body. For example:
public interface GroupedInterface extends Interface1,
                                        Interface2, Interface3 {

   // constant declarations
   double E = 2.718282;  // base of natural logarithms

   // method signatures
   void doSomething (int i, double x);
   int doSomethingElse(String s);

}
The public access specifier indicates that the interface can be used by any class in any package. If you do not specify that the interface is public, your interface will be accessible only to classes defined in the same package as the interface.

An interface can extend other interfaces, just as a class can extend or subclass another class. However, whereas a class can extend only one other class, an interface can extend any number of interfaces. The interface declaration includes a comma-separated list of all the interfaces that it extends.

The Interface Body

The interface body contains method declarations for all the methods included in the interface. A method declaration within an interface is followed by a semicolon, but no braces, because an interface does not provide implementations for the methods declared within it. All methods declared in an interface are implicitly public, so the public modifier can be omitted.

An interface can contain constant declarations in addition to method declarations. All constant values defined in an interface are implicitly public, static, and final. Once again, these modifiers can be omitted.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Interfaces
Next page: Implementing an Interface


Implementing an Interface (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Section: Interfaces
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Implementing an Interface
To declare a class that implements an interface, you include an implements clause in the class declaration. Your class can implement more than one interface, so the implements keyword is followed by a comma-separated list of the interfaces implemented by the class.

By convention, the implements clause follows the extends clause, if there is one.

A Sample Interface, Relatable

Consider an interface that defines how to compare the size of objects.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public interface Relatable {

   // this (object calling isLargerThan) and
   // other must be instances of the same class
   // returns 1, 0, -1 if this is greater
   // than, equal to, or less than other
   public int isLargerThan(Relatable other);

}
If you want to be able to compare the size of similar objects, no matter what they are, the class that instantiates them should implement Relatable.

Any class can implement Relatable if there is some way to compare the relative "size" of objects instantiated from the class. For strings, it could be number of characters; for books, it could be number of pages; for students, it could be weight; and so forth. For planar geometric objects, area would be a good choice (see the RectanglePlus class that follows), while volume would work for three-dimensional geometric objects. All such classes can implement the isLargerThan() method.

If you know that a class implements Relatable, then you know that you can compare the size of the objects instantiated from that class.

Implementing the Relatable Interface

Here is the Rectangle class that was presented in the Creating Objects section, rewritten to implement Relatable.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class RectanglePlus implements Relatable {
    public int width = 0;
    public int height = 0;
    public Point origin;

    // four constructors
    public RectanglePlus() {
    origin = new Point(0, 0);
    }
    public RectanglePlus(Point p) {
    origin = p;
    }
    public RectanglePlus(int w, int h) {
    origin = new Point(0, 0);
    width = w;
    height = h;
    }
    public RectanglePlus(Point p, int w, int h) {
    origin = p;
    width = w;
    height = h;
    }

    // a method for moving the rectangle
    public void move(int x, int y) {
    origin.x = x;
    origin.y = y;
    }

    // a method for computing the area of the rectangle
    public int getArea() {
    return width * height;
    }

    // a method to implement Relatable
    public int isLargerThan(Relatable other) {
        RectanglePlus otherRect = (RectanglePlus)other;
        if (this.getArea() < otherRect.getArea())
            return -1;
        else if (this.getArea() > otherRect.getArea())
            return 1;
        else
            return 0;
    }
}
Because RectanglePlus implements Relatable, the size of any two RectanglePlus objects can be compared.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Defining an Interface
Next page: Using an Interface as a Type


Using an Interface as a Type (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Section: Interfaces
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Using an Interface as a Type
When you define a new interface, you are defining a new reference data type. You can use interface names anywhere you can use any other data type name. If you define a reference variable whose type is an interface, any object you assign to it must be an instance of a class that implements the interface.

As an example, here is a method for finding the largest object in a pair of objects, for any objects that are instantiated from a class that implements Relatable:

public Object findLargest(Object object1, Object object2) {
   Relatable obj1 = (Relatable)object1;
   Relatable obj2 = (Relatable)object2;
   if ( (obj1).isLargerThan(obj2) > 0)
      return object1;
   else
      return object2;
}
By casting object1 to a Relatable type, it can invoke the isLargerThan method.

If you make a point of implementing Relatable in a wide variety of classes, the objects instantiated from any of those classes can be compared with the findLargest() method—provided that both objects are of the same class. Similarly, they can all be compared with the following methods:

public Object findSmallest(Object object1, Object object2) {
   Relatable obj1 = (Relatable)object1;
   Relatable obj2 = (Relatable)object2;
   if ( (obj1).isLargerThan(obj2) < 0)
      return object1;
   else
      return object2;
}

public boolean isEqual(Object object1, Object object2) {
   Relatable obj1 = (Relatable)object1;
   Relatable obj2 = (Relatable)object2;
   if ( (obj1).isLargerThan(obj2) == 0)
      return true;
   else
      return false;
}
These methods work for any "relatable" objects, no matter what their class inheritance is. When they implement Relatable, they can be of both their own class (or superclass) type and a Relatable type. This gives them some of the advantages of multiple inheritance, where they can have behavior from both a superclass and an interface.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Implementing an Interface
Next page: Rewriting Interfaces


Rewriting Interfaces (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Section: Interfaces
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Rewriting Interfaces
Consider an interface that you have developed called DoIt:
public interface DoIt {
   void doSomething(int i, double x);
   int doSomethingElse(String s);
}
Suppose that, at a later time, you want to add a third method to DoIt, so that the interface now becomes:
public interface DoIt {

   void doSomething(int i, double x);
   int doSomethingElse(String s);
   boolean didItWork(int i, double x, String s);

}
If you make this change, all classes that implement the old DoIt interface will break because they don't implement the interface anymore. Programmers relying on this interface will protest loudly.

Try to anticipate all uses for your interface and to specify it completely from the beginning. Given that this is often impossible, you may need to create more interfaces later. For example, you could create a DoItPlus interface that extends DoIt:

public interface DoItPlus extends DoIt {

   boolean didItWork(int i, double x, String s);

}
Now users of your code can choose to continue to use the old interface or to upgrade to the new interface.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using an Interface as a Type
Next page: Summary of Interfaces


Summary of Interfaces (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Section: Interfaces
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Summary of Interfaces
An interface defines a protocol of communication between two objects.

An interface declaration contains signatures, but no implementations, for a set of methods, and might also contain constant definitions.

A class that implements an interface must implement all the methods declared in the interface.

An interface name can be used anywhere a type can be used.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Rewriting Interfaces
Next page: Questions and Exercises: Interfaces


Questions and Exercises: Interfaces (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Questions and Exercises: Interfaces

Questions

  1. What methods would a class that implements the java.lang.CharSequence interface have to implement?

  2. What is wrong with the following interface?
    public interface SomethingIsWrong {
    void aMethod(int aValue){
        System.out.println("Hi Mom");
    }
}

  3. Fix the interface in question 2.

  4. Is the following interface valid?
    public interface Marker {
}

Exercises

  1. Write a class that implements the CharSequence interface found in the java.lang package. Select one of the sentences from this book to use as the data. Write a small main method to test your class; make sure to call all four methods.

  2. Suppose you have written a time server that periodically notifies its clients of the current date and time. Write an interface the server could use to enforce a particular protocol on its clients.

Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary of Interfaces
Next page: Inheritance


Inheritance (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Inheritance
In the preceding lessons, you have seen inheritance mentioned several times. In the Java language, classes can be derived from other classes, thereby inheriting fields and methods from those classes.
Definitions:

A class that is derived from another class is called a subclass (also a derived class, extended class, or child class). The class from which the subclass is derived is called a superclass (also a base class or a parent class).

Excepting Object, which has no superclass, every class has one and only one direct superclass (single inheritance). In the absence of any other explicit superclass, every class is implicitly a subclass of Object.

Classes can be derived from classes that are derived from classes that are derived from classes, and so on, and ultimately derived from the topmost class, Object. Such a class is said to be descended from all the classes in the inheritance chain stretching back to Object.

The idea of inheritance is simple but powerful: When you want to create a new class and there is already a class that includes some of the code that you want, you can derive your new class from the existing class. In doing this, you can reuse the fields and methods of the existing class without having to write (and debug!) them yourself.

A subclass inherits all the members (fields, methods, and nested classes) from its superclass. Constructors are not members, so they are not inherited by subclasses, but the constructor of the superclass can be invoked from the subclass.

The Java Platform Class Hierarchy

The Object class, defined in the java.lang package, defines and implements behavior common to all classes—including the ones that you write. In the Java platform, many classes derive directly from Object, other classes derive from some of those classes, and so on, forming a hierarchy of classes.

All Classes in the Java Platform are Descendants of Object

All Classes in the Java Platform are Descendants of Object

At the top of the hierarchy, Object is the most general of all classes. Classes near the bottom of the hierarchy provide more specialized behavior.

An Example of Inheritance

Here is the sample code for a possible implementation of a Bicycle class that was presented in the Classes and Objects lesson:
public class Bicycle {

    // the Bicycle class has three fields
    public int cadence;
    public int gear;
    public int speed;

    // the Bicycle class has one constructor
    public Bicycle(int startCadence, int startSpeed, int startGear) {
        gear = startGear;
        cadence = startCadence;
        speed = startSpeed;
    }

    // the Bicycle class has four methods
    public void setCadence(int newValue) {
        cadence = newValue;
    }

    public void setGear(int newValue) {
        gear = newValue;
    }

    public void applyBrake(int decrement) {
        speed -= decrement;
    }

    public void speedUp(int increment) {
        speed += increment;
    }

}

A class declaration for a MountainBike class that is a subclass of Bicycle might look like this:

public class MountainBike extends Bicycle {

    // the MountainBike subclass adds one field
    public int seatHeight;

    // the MountainBike subclass has one constructor
    public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear) {
        super(startCadence, startSpeed, startGear);
        seatHeight = startHeight;
    }

    // the MountainBike subclass adds one method
    public void setHeight(int newValue) {
        seatHeight = newValue;
    }

}
MountainBike inherits all the fields and methods of Bicycle and adds the field seatHeight and a method to set it. Except for the constructor, it is as if you had written a new MountainBike class entirely from scratch, with four fields and five methods. However, you didn't have to do all the work. This would be especially valuable if the methods in the Bicycle class were complex and had taken substantial time to debug.

What You Can Do in a Subclass

A subclass inherits all of the public and protected members of its parent, no matter what package the subclass is in. If the subclass is in the same package as its parent, it also inherits the package-private members of the parent. You can use the inherited members as is, replace them, hide them, or supplement them with new members:
  • The inherited fields can be used directly, just like any other fields.
  • You can declare a field in the subclass with the same name as the one in the superclass, thus hiding it (not recommended).
  • You can declare new fields in the subclass that are not in the superclass.
  • The inherited methods can be used directly as they are.
  • You can write a new instance method in the subclass that has the same signature as the one in the superclass, thus overriding it.
  • You can write a new static method in the subclass that has the same signature as the one in the superclass, thus hiding it.
  • You can declare new methods in the subclass that are not in the superclass.
  • You can write a subclass constructor that invokes the constructor of the superclass, either implicitly or by using the keyword super.
The following sections in this lesson will expand on these topics.

Private Members in a Superclass

A subclass does not inherit the private members of its parent class. However, if the superclass has public or protected methods for accessing its private fields, these can also be used by the subclass.

A nested class has access to all the private members of its enclosing class—both fields and methods. Therefore, a public or protected nested class inherited by a subclass has indirect access to all of the private members of the superclass.

Casting Objects

We have seen that an object is of the data type of the class from which it was instantiated. For example, if we write
public MountainBike myBike = new MountainBike();
then myBike is of type MountainBike.

MountainBike is descended from Bicycle and Object. Therefore, a MountainBike is a Bicycle and is also an Object, and it can be used wherever Bicycle or Object objects are called for.

The reverse is not necessarily true: a Bicycle may be a MountainBike, but it isn't necessarily. Similarly, an Object may be a Bicycle or a MountainBike, but it isn't necessarily.

Casting shows the use of an object of one type in place of another type, among the objects permitted by inheritance and implementations. For example, if we write

Object obj = new MountainBike();
then obj is both an Object and a Mountainbike (until such time as obj is assigned another object that is not a Mountainbike). This is called implicit casting.

If, on the other hand, we write

MountainBike myBike = obj;
we would get a compile-time error because obj is not known to the compiler to be a MountainBike. However, we can tell the compiler that we promise to assign a MountainBike to obj by explicit casting:
MountainBike myBike = (MountainBike)obj;
This cast inserts a runtime check that obj is assigned a MountainBike so that the compiler can safely assume that obj is a MountainBike. If obj is not a Mountainbike at runtime, an exception will be thrown.
Note: You can make a logical test as to the type of a particular object using the instanceof operator. This can save you from a runtime error owing to an improper cast. For example:
if (obj instanceof MountainBike) {
   MountainBike myBike = (MountainBike)obj;
}
Here the instanceof operator verifies that obj refers to a MountainBike so that we can make the cast with knowledge that there will be no runtime exception thrown.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Interfaces
Next page: Overriding and Hiding Methods


Overriding and Hiding Methods (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Section: Inheritance
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Overriding and Hiding Methods

Instance Methods

An instance method in a subclass with the same signature (name, plus the number and the type of its parameters) and return type as an instance method in the superclass overrides the superclass's method.

The ability of a subclass to override a method allows a class to inherit from a superclass whose behavior is "close enough" and then to modify behavior as needed. The overriding method has the same name, number and type of parameters, and return type as the method it overrides. An overriding method can also return a subtype of the type returned by the overridden method. This is called a covariant return type.

When overriding a method, you might want to use the @Override annotation that instructs the compiler that you intend to override a method in the superclass. If, for some reason, the compiler detects that the method does not exist in one of the superclasses, it will generate an error. For more information on @Override, see Annotations.

Class Methods

If a subclass defines a class method with the same signature as a class method in the superclass, the method in the subclass hides the one in the superclass.

The distinction between hiding and overriding has important implications. The version of the overridden method that gets invoked is the one in the subclass. The version of the hidden method that gets invoked depends on whether it is invoked from the superclass or the subclass. Let's look at an example that contains two classes. The first is Animal, which contains one instance method and one class method:

public class Animal {
    public static void testClassMethod() {
        System.out.println("The class method in Animal.");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Animal.");
    }
}
The second class, a subclass of Animal, is called Cat:
public class Cat extends Animal {
    public static void testClassMethod() {
        System.out.println("The class method in Cat.");
    }
    public void testInstanceMethod() {
        System.out.println("The instance method in Cat.");
    }

    public static void main(String[] args) {
        Cat myCat = new Cat();
        Animal myAnimal = myCat;
        Animal.testClassMethod();
        myAnimal.testInstanceMethod();
    }
}
The Cat class overrides the instance method in Animal and hides the class method in Animal. The main method in this class creates an instance of Cat and calls testClassMethod() on the class and testInstanceMethod() on the instance.

The output from this program is as follows:

The class method in Animal.
The instance method in Cat.
As promised, the version of the hidden method that gets invoked is the one in the superclass, and the version of the overridden method that gets invoked is the one in the subclass.

Modifiers

The access specifier for an overriding method can allow more, but not less, access than the overridden method. For example, a protected instance method in the superclass can be made public, but not private, in the subclass.

You will get a compile-time error if you attempt to change an instance method in the superclass to a class method in the subclass, and vice versa.

Summary

The following table summarizes what happens when you define a method with the same signature as a method in a superclass.
Defining a Method with the Same Signature as a Superclass's Method
Superclass Instance Method | Superclass Static Method
Subclass Instance Method | Overrides | Generates a compile-time error
Subclass Static Method | Generates a compile-time error | Hides
Note: In a subclass, you can overload the methods inherited from the superclass. Such overloaded methods neither hide nor override the superclass methods—they are new methods, unique to the subclass.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Inheritance
Next page: Hiding Fields


Hiding Fields (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Section: Inheritance
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Hiding Fields
Within a class, a field that has the same name as a field in the superclass hides the superclass's field, even if their types are different. Within the subclass, the field in the superclass cannot be referenced by its simple name. Instead, the field must be accessed through super, which is covered in the next section. Generally speaking, we don't recommend hiding fields as it makes code difficult to read.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Overriding and Hiding Methods
Next page: Using the Keyword super


Using the Keyword super (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Section: Inheritance
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Using the Keyword super

Accessing Superclass Members

If your method overrides one of its superclass's methods, you can invoke the overridden method through the use of the keyword super. You can also use super to refer to a hidden field (although hiding fields is discouraged). Consider this class, Superclass:
public class Superclass {

    public void printMethod() {
        System.out.println("Printed in Superclass.");
    }
}
Here is a subclass, called Subclass, that overrides printMethod():
public class Subclass extends Superclass {

    public void printMethod() { //overrides printMethod in Superclass
        super.printMethod();
        System.out.println("Printed in Subclass");
    }
    public static void main(String[] args) {

    Subclass s = new Subclass();
    s.printMethod();
    }

}
Within Subclass, the simple name printMethod() refers to the one declared in Subclass, which overrides the one in Superclass. So, to refer to printMethod() inherited from Superclass, Subclass must use a qualified name, using super as shown. Compiling and executing Subclass prints the following:
Printed in Superclass.
Printed in Subclass

Subclass Constructors

The following example illustrates how to use the super keyword to invoke a superclass's constructor. Recall from the Bicycle example that MountainBike is a subclass of Bicycle. Here is the MountainBike (subclass) constructor that calls the superclass constructor and then adds initialization code of its own:
    public MountainBike(int startHeight, int startCadence, int startSpeed, int startGear) {
        super(startCadence, startSpeed, startGear);
        seatHeight = startHeight;
    }
Invocation of a superclass constructor must be the first line in the subclass constructor.

The syntax for calling a superclass constructor is

super();
--or--
super(parameter list);
With super(), the superclass no-argument constructor is called. With super(parameter list), the superclass constructor with a matching parameter list is called.
Note: If a constructor does not explicitly invoke a superclass constructor, the Java compiler automatically inserts a call to the no-argument constructor of the superclass. If the super class does not have a no-argument constructor, you will get a compile-time error. Object does have such a constructor, so if Object is the only superclass, there is no problem.
If a subclass constructor invokes a constructor of its superclass, either explicitly or implicitly, you might think that there will be a whole chain of constructors called, all the way back to the constructor of Object. In fact, this is the case. It is called constructor chaining, and you need to be aware of it when there is a long line of class descent.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Hiding Fields
Next page: Object as a Superclass


Object as a Superclass (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Section: Inheritance
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Object as a Superclass
The Object class, in the java.lang package, sits at the top of the class hierarchy tree. Every class is a descendant, direct or indirect, of the Object class. Every class you use or write inherits the instance methods of Object. You need not use any of these methods, but, if you choose to do so, you may need to override them with code that is specific to your class. The methods inherited from Object that are discussed in this section are:
  • protected Object clone() throws CloneNotSupportedException
    Creates and returns a copy of this object.
  • public boolean equals(Object obj)
    Indicates whether some other object is "equal to" this one.
  • protected void finalize() throws Throwable
    Called by the garbage collector on an object when garbage
    collection determines that there are no more references to the object
  • public final Class getClass()
    Returns the runtime class of an object.
  • public int hashCode()
    Returns a hash code value for the object.
  • public String toString()
    Returns a string representation of the object.

The notify, notifyAll, and wait methods of Object all play a part in synchronizing the activities of independently running threads in a program, which is discussed in a later lesson and won't be covered here. There are five of these methods:

  • public final void notify()
  • public final void notifyAll()
  • public final void wait()
  • public final void wait(long timeout)
  • public final void wait(long timeout, int nanos)
Note: There are some subtle aspects to a number of these methods, especially the clone method. You can get information on the correct usage of these methods in the book Effective Java by Josh Bloch.

The clone() Method

If a class, or one of its superclasses, implements the Cloneable interface, you can use the clone() method to create a copy from an existing object. To create a clone, you write:
aCloneableObject.clone();
Object's implementation of this method checks to see whether the object on which clone() was invoked implements the Cloneable interface. If the object does not, the method throws a CloneNotSupportedException exception. Exception handling will be covered in a later lesson. For the moment, you need to know that clone() must be declared as
protected Object clone() throws CloneNotSupportedException
    -- or --
public Object clone() throws CloneNotSupportedException
if you are going to write a clone() method to override the one in Object.

If the object on which clone() was invoked does implement the Cloneable interface, Object's implementation of the clone() method creates an object of the same class as the original object and initializes the new object's member variables to have the same values as the original object's corresponding member variables.

The simplest way to make your class cloneable is to add implements Cloneable to your class's declaration. then your objects can invoke the clone() method.

For some classes, the default behavior of Object's clone() method works just fine. If, however, an object contains a reference to an external object, say ObjExternal, you may need to override clone() to get correct behavior. Otherwise, a change in ObjExternal made by one object will be visible in its clone also. This means that the original object and its clone are not independent—to decouple them, you must override clone() so that it clones the object and ObjExternal. Then the original object references ObjExternal and the clone references a clone of ObjExternal, so that the object and its clone are truly independent.

The equals() Method

The equals() method compares two objects for equality and returns true if they are equal. The equals() method provided in the Object class uses the identity operator (==) to determine whether two objects are equal. For primitive data types, this gives the correct result. For objects, however, it does not. The equals() method provided by Object tests whether the object references are equal—that is, if the objects compared are the exact same object.

To test whether two objects are equal in the sense of equivalency (containing the same information), you must override the equals() method. Here is an example of a Book class that overrides equals():

public class Book {
    ...
    public boolean equals(Object obj) {
        if (obj instanceof Book)
            return ISBN.equals((Book)obj.getISBN());
        else
            return false;
    }
}
Consider this code that tests two instances of the Book class for equality:
Book firstBook  = new Book("0201914670"); //Swing Tutorial, 2nd edition
Book secondBook = new Book("0201914670");
if (firstBook.equals(secondBook)) {
    System.out.println("objects are equal");
} else {
    System.out.println("objects are not equal");
}
This program displays objects are equal even though firstBook and secondBook reference two distinct objects. They are considered equal because the objects compared contain the same ISBN number.

You should always override the equals() method if the identity operator is not appropriate for your class.

Note: If you override equals(), you must override hashCode() as well.

The finalize() Method

The Object class provides a callback method, finalize(), that may be invoked on an object when it becomes garbage. Object's implementation of finalize() does nothing—you can override finalize() to do cleanup, such as freeing resources.

The finalize() method may be called automatically by the system, but when it is called, or even if it is called, is uncertain. Therefore, you should not rely on this method to do your cleanup for you. For example, if you don't close file descriptors in your code after performing I/O and you expect finalize() to close them for you, you may run out of file descriptors.

The getClass() Method

You cannot override getClass.

The getClass() method returns a Class object, which has methods you can use to get information about the class, such as its name (getSimpleName()), its superclass (getSuperclass()), and the interfaces it implements (getInterfaces()). For example, the following method gets and displays the class name of an object:

void printClassName(Object obj) {
    System.out.println("The object's class is "
                          obj.getClass().getSimpleName());
}
The Class class, in the java.lang package, has a large number of methods (more than 50). For example, you can test to see if the class is an annotation (isAnnotation()), an interface (isInterface()), or an enumeration (isEnum()). You can see what the object's fields are (getFields()) or what its methods are (getMethods()), and so on.

The hashCode() Method

The value returned by hashCode() is the object's hash code, which is the object's memory address in hexadecimal.

By definition, if two objects are equal, their hash code must also be equal. If you override the equals() method, you change the way two objects are equated and Object's implementation of hashCode() is no longer valid. Therefore, if you override the equals() method, you must also override the hashCode() method as well.

The toString() Method

You should always consider overriding the toString() method in your classes.

The Object's toString() method returns a String representation of the object, which is very useful for debugging. The String representation for an object depends entirely on the object, which is why you need to override toString() in your classes.

You can use toString() along with System.out.println() to display a text representation of an object, such as an instance of Book:

System.out.println(firstBook.toString());
which would, for a properly overridden toString() method, print something useful, like this:
ISBN: 0201914670; The JFC Swing Tutorial; A Guide to Constructing GUIs, 2nd Edition
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using the Keyword super
Next page: Writing Final Classes and Methods


Writing Final Classes and Methods (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Section: Inheritance
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Writing Final Classes and Methods
You can declare some or all of a class's methods final. You use the final keyword in a method declaration to indicate that the method cannot be overridden by subclasses. The Object class does this—a number of its methods are final.

You might wish to make a method final if it has an implementation that should not be changed and it is critical to the consistent state of the object. For example, you might want to make the getFirstPlayer method in this ChessAlgorithm class final:

class ChessAlgorithm {
    enum ChessPlayer { WHITE, BLACK }
    ...
    final ChessPlayer getFirstPlayer() {
        return ChessPlayer.WHITE;
    }
    ...
}
Methods called from constructors should generally be declared final. If a constructor calls a non-final method, a subclass may redefine that method with surprising or undesirable results.

Note that you can also declare an entire class final — this prevents the class from being subclassed. This is particularly useful, for example, when creating an immutable class like the String class.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Object as a Superclass
Next page: Abstract Methods and Classes


Abstract Methods and Classes (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Section: Inheritance
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Abstract Methods and Classes
An abstract class is a class that is declared abstract—it may or may not include abstract methods. Abstract classes cannot be instantiated, but they can be subclassed.

An abstract method is a method that is declared without an implementation (without braces, and followed by a semicolon), like this:

abstract void moveTo(double deltaX, double deltaY);
If a class includes abstract methods, the class itself must be declared abstract, as in:
public abstract class GraphicObject {
   // declare fields
   // declare non-abstract methods
   abstract void draw();
}
When an abstract class is subclassed, the subclass usually provides implementations for all of the abstract methods in its parent class. However, if it does not, the subclass must also be declared abstract.
Note: All of the methods in an interface (see the Interfaces section) are implicitly abstract, so the abstract modifier is not used with interface methods (it could be—it's just not necessary).

Abstract Classes versus Interfaces

Unlike interfaces, abstract classes can contain fields that are not static and final, and they can contain implemented methods. Such abstract classes are similar to interfaces, except that they provide a partial implementation, leaving it to subclasses to complete the implementation. If an abstract class contains only abstract method declarations, it should be declared as an interface instead.

Multiple interfaces can be implemented by classes anywhere in the class hierarchy, whether or not they are related to one another in any way. Think of Comparable or Cloneable, for example.

By comparison, abstract classes are most commonly subclassed to share pieces of implementation. A single abstract class is subclassed by similar classes that have a lot in common (the implemented parts of the abstract class), but also have some differences (the abstract methods).

An Abstract Class Example

In an object-oriented drawing application, you can draw circles, rectangles, lines, Bezier curves, and many other graphic objects. These objects all have certain states (for example: position, orientation, line color, fill color) and behaviors (for example: moveTo, rotate, resize, draw) in common. Some of these states and behaviors are the same for all graphic objects—for example: position, fill color, and moveTo. Others require different implementations—for example, resize or draw. All GraphicObjects must know how to draw or resize themselves; they just differ in how they do it. This is a perfect situation for an abstract superclass. You can take advantage of the similarities and declare all the graphic objects to inherit from the same abstract parent object—for example, GraphicObject, as shown in the following figure.

Classes Rectangle, Line, Bezier, and Circle inherit from GraphicObject

Classes Rectangle, Line, Bezier, and Circle inherit from GraphicObject

First, you declare an abstract class, GraphicObject, to provide member variables and methods that are wholly shared by all subclasses, such as the current position and the moveTo method. GraphicObject also declares abstract methods for methods, such as draw or resize, that need to be implemented by all subclasses but must be implemented in different ways. The GraphicObject class can look something like this:

abstract class GraphicObject {
    int x, y;
    ...
    void moveTo(int newX, int newY) {
        ...
    }
    abstract void draw();
    abstract void resize();
}
Each non-abstract subclass of GraphicObject, such as Circle and Rectangle, must provide implementations for the draw and resize methods:
class Circle extends GraphicObject {
    void draw() {
        ...
    }
    void resize() {
        ...
    }
}
class Rectangle extends GraphicObject {
    void draw() {
        ...
    }
    void resize() {
        ...
    }
}

When an Abstract Class Implements an Interface

In the section on Interfaces , it was noted that a class that implements an interface must implement all of the interface's methods. It is possible, however, to define a class that does not implement all of the interface methods, provided that the class is declared to be abstract. For example,
abstract class X implements Y {
  // implements all but one method of Y
}

class XX extends X {
  // implements the remaining method in Y
}
In this case, class X must be abstract because it does not fully implement Y, but class XX does, in fact, implement Y.

Class Members

An abstract class may have static fields and static methods. You can use these static members with a class reference—for example, AbstractClass.staticMethod()—as you would with any other class.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Writing Final Classes and Methods
Next page: Summary of Inheritance


Summary of Inheritance (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Section: Inheritance
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Summary of Inheritance
Except for the Object class, a class has exactly one direct superclass. A class inherits fields and methods from all its superclasses, whether direct or indirect. A subclass can override methods that it inherits, or it can hide fields or methods that it inherits. (Note that hiding fields is generally bad programming practice.)

The table in Overriding and Hiding Methods section shows the effect of declaring a method with the same signature as a method in the superclass.

The Object class is the top of the class hierarchy. All classes are descendants from this class and inherit methods from it. Useful methods inherited from Object include toString(), equals(), clone(), and getClass().

You can prevent a class from being subclassed by using the final keyword in the class's declaration. Similarly, you can prevent a method from being overridden by subclasses by declaring it as a final method.

An abstract class can only be subclassed; it cannot be instantiated. An abstract class can contain abstract methods—methods that are declared but not implemented. Subclasses then provide the implementations for the abstract methods.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Abstract Methods and Classes
Next page: Questions and Exercises: Inheritance


Questions and Exercises: Inheritance (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • Trail • Next »
Questions and Exercises: Inheritance

Questions

1. Consider the following two classes:
public class ClassA {
    public void methodOne(int i) {
    }
    public void methodTwo(int i) {
    }
    public static void methodThree(int i) {
    }
    public static void methodFour(int i) {
    }
}

public class ClassB extends ClassA {
    public static void methodOne(int i) {
    }
    public void methodTwo(int i) {
    }
    public void methodThree(int i) {
    }
    public static void methodFour(int i) {
    }
}
a. Which method overrides a method in the superclass?
b. Which method hides a method in the superclass?
c. What do the other methods do?

2. Consider the Card, Deck, and DisplayDeck classes you wrote in Questions and Exercises: Classes . What Object methods should each of these classes override?

Exercises

1. Write the implementations for the methods that you answered in question 2.

Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary of Inheritance
Next page: Numbers and Strings


Lesson: Numbers and Strings (The Java™ Tutorials > Learning the Java Language)

Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Trail: Learning the Java Language
Home Page > Learning the Java Language
« Previous • Trail • Next »
Lesson: Numbers and Strings

Numbers

This section begins with a discussion of the Number class (in the java.lang package) and its subclasses. In particular, this section talks about the situations where you would use instantiations of these classes rather than the primitive data types. Additionally, this section talks about other classes you might need to work with numbers, such as formatting or using mathematical functions to complement the operators built into the language.

Strings

Strings, which are widely used in Java programming, are a sequence of characters. In the Java programming language, strings are objects. This section describes using the String class to create and manipulate strings. It also compares the String and StringBuilder classes.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Numbers


Numbers (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Home Page > Learning the Java Language > Numbers and Strings
« Previous • Trail • Next »
Numbers
This section begins with a discussion of the Number class in the java.lang package, its subclasses, and the situations where you would use instantiations of these classes rather than the primitive number types.

This section also presents the PrintStream and DecimalFormat classes, which provide methods for writing formatted numerical output.

Finally, the Math class in java.lang is discussed. It contains mathematical functions to complement the operators built into the language. This class has methods for the trigonometric functions, exponential functions, and so forth.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Numbers and Strings
Next page: The Numbers Classes


The Numbers Classes (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Section: Numbers
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Home Page > Learning the Java Language > Numbers and Strings
« Previous • Trail • Next »
The Numbers Classes
When working with numbers, most of the time you use the primitive types in your code. For example:
int i = 500;
float gpa = 3.65f;
byte mask = 0xff;
There are, however, reasons to use objects in place of primitives, and the Java platform provides wrapper classes for each of the primitive data types. These classes "wrap" the primitive in an object. Often, the wrapping is done by the compiler—if you use a primitive where an object is expected, the compiler boxes the primitive in its wrapper class for you. Similarly, if you use a number object when a primitive is expected, the compiler unboxes the object for you.

Here is an example of boxing and unboxing:

Integer x, y;
x = 12;
y = 15;
System.out.println(x+y);
When x and y are assigned integer values, the compiler boxes the integers because x and y are integer objects. In the println() statement, x and y are unboxed so that they can be added as integers.

All of the numeric wrapper classes are subclasses of the abstract class Number:

The class hierarchy of Number.

Note: There are four other subclasses of Number that are not discussed here. BigDecimal and BigInteger are used for high-precision calculations. AtomicInteger and AtomicLong are used for multi-threaded applications.
There are three reasons that you might use a Number object rather than a primitive:
  1. As an argument of a method that expects an object (often used when manipulating collections of numbers).

  2. To use constants defined by the class, such as MIN_VALUE and MAX_VALUE, that provide the upper and lower bounds of the data type.

  3. To use class methods for converting values to and from other primitive types, for converting to and from strings, and for converting between number systems (decimal, octal, hexadecimal, binary).

The following table lists the instance methods that all the subclasses of the Number class implement.

Methods Implemented by all Subclasses of Number
Method Description
byte byteValue()
short shortValue()
int intValue()
long longValue()
float floatValue()
double doubleValue() 		Converts the value of this Number object to the primitive data type returned.
int compareTo(Byte anotherByte)
int compareTo(Double anotherDouble)
int compareTo(Float anotherFloat)
int compareTo(Integer anotherInteger)
int compareTo(Long anotherLong)
int compareTo(Short anotherShort) 		Compares this Number object to the argument.
boolean equals(Object obj) Determines whether this number object is equal to the argument.
The methods return true if the argument is not null and is an object of the same type and with the same numeric value.
There are some extra requirements for Double and Float objects that are described in the Java API documentation.

Each Number class contains other methods that are useful for converting numbers to and from strings and for converting between number systems. The following table lists these methods in the Integer class. Methods for the other Number subclasses are similar:

Conversion Methods, Integer Class
Method | Description
static Integer decode(String s) | Decodes a string into an integer. Can accept string representations of decimal, octal, or hexadecimal numbers as input.
static int parseInt(String s) | Returns an integer (decimal only).
static int parseInt(String s, int radix) | Returns an integer, given a string representation of decimal, binary, octal, or hexadecimal (radix equals 10, 2, 8, or 16 respectively) numbers as input.
String toString() | Returns a String object representing the value of this Integer.
static String toString(int i) | Returns a String object representing the specified integer.
static Integer valueOf(int i) | Returns an Integer object holding the value of the specified primitive.
static Integer valueOf(String s) | Returns an Integer object holding the value of the specified string representation.
static Integer valueOf(String s, int radix) | Returns an Integer object holding the integer value of the specified string representation, parsed with the value of radix. For example, if s = "333" and radix = 8, the method returns the base-ten integer equivalent of the octal number 333.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Numbers
Next page: Formatting Numeric Print Output


Formatting Numeric Print Output (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Section: Numbers
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Home Page > Learning the Java Language > Numbers and Strings
« Previous • Trail • Next »
Formatting Numeric Print Output
Earlier you saw the use of the print and println methods for printing strings to standard output (System.out). Since all numbers can be converted to strings (as you will see later in this lesson), you can use these methods to print out an arbitrary mixture of strings and numbers. The Java programming language has other methods, however, that allow you to exercise much more control over your print output when numbers are included.

The printf and format Methods

The java.io package includes a PrintStream class that has two formatting methods that you can use to replace print and println. These methods, format and printf, are equivalent to one another. The familiar System.out that you have been using happens to be a PrintStream object, so you can invoke PrintStream methods on System.out. Thus, you can use format or printf anywhere in your code where you have previously been using print or println. For example,
System.out.format(.....);

The syntax for these two java.io.PrintStream methods is the same:

public PrintStream format(String format, Object... args)
where format is a string that specifies the formatting to be used and args is a list of the variables to be printed using that formatting. A simple example would be
System.out.format("The value of the float variable is %f, while the value of the " +
                   "integer variable is %d, and the string is %s", floatVar, intVar, stringVar);
The first parameter, format, is a format string specifying how the objects in the second parameter, args, are to be formatted. The format string contains plain text as well as format specifiers, which are special characters that format the arguments of Object... args. (The notation Object... args is called varargs, which means that the number of arguments may vary.)

Format specifiers begin with a percent sign (%) and end with a converter. The converter is a character indicating the type of argument to be formatted. In between the percent sign (%) and the converter you can have optional flags and specifiers. There are many converters, flags, and specifiers, which are documented in java.util.Formatter

Here is a basic example:

int i = 461012;
System.out.format("The value of i is: %d%n", i);
The %d specifies that the single variable is a decimal integer. The %n is a platform-independent newline character. The output is:
The value of i is: 461012

The printf and format methods are overloaded. Each has a version with the following syntax:

public PrintStream format(Locale l, String format, Object... args)
To print numbers in the French system (where a comma is used in place of the decimal place in the English representation of floating point numbers), for example, you would use:
System.out.format(Locale.FRANCE, "The value of the float variable is %f, while the value of the " +
                   "integer variable is %d, and the string is %s%n", floatVar, intVar, stringVar);

An Example

The following table lists some of the converters and flags that are used in the sample program, TestFormat.java, that follows the table.

Converters and Flags Used in TestFormat.java
Converter | Flag | Explanation
d | A decimal integer.
f | A float.
n | A new line character appropriate to the platform running the application. You should always use %n, rather than \n.
tB | A date & time conversion—locale-specific full name of month.
td, te | A date & time conversion—2-digit day of month. td has leading zeroes as needed, te does not.
ty, tY | A date & time conversion—ty = 2-digit year, tY = 4-digit year.
tl | A date & time conversion—hour in 12-hour clock.
tM | A date & time conversion—minutes in 2 digits, with leading zeroes as necessary.
tp | A date & time conversion—locale-specific am/pm (lower case).
tm | A date & time conversion—months in 2 digits, with leading zeroes as necessary.
tD | A date & time conversion—date as %tm%td%ty
08 | Eight characters in width, with leading zeroes as necessary.
+ Includes sign, whether positive or negative.
, Includes locale-specific grouping characters.
- Left-justified..
.3 | Three places after decimal point.
10.3 | Ten characters in width, right justified, with three places after decimal point.

The following program shows some of the formatting that you can do with format. The output is shown within double quotes in the embedded comment:

import java.util.Calendar;
import java.util.Locale;

public class TestFormat {

    public static void main(String[] args) {
      long n = 461012;
      System.out.format("%d%n", n);                  //  -->  "461012"
      System.out.format("%08d%n", n);                //  -->  "00461012"
      System.out.format("%+8d%n", n);                //  -->  " +461012"
      System.out.format("%,8d%n", n);                //  -->  " 461,012"
      System.out.format("%+,8d%n%n", n);             //  -->  "+461,012"

      double pi = Math.PI;
      System.out.format("%f%n", pi);                 //  -->  "3.141593"
      System.out.format("%.3f%n", pi);               //  -->  "3.142"
      System.out.format("%10.3f%n", pi);             //  -->  "     3.142"
      System.out.format("%-10.3f%n", pi);            //  -->  "3.142"
      System.out.format(Locale.FRANCE,
                        "%-10.4f%n%n", pi);          //  -->  "3,1416"

      Calendar c = Calendar.getInstance();
      System.out.format("%tB %te, %tY%n", c, c, c);  //  -->  "May 29, 2006"
      System.out.format("%tl:%tM %tp%n", c, c, c);   //  -->  "2:34 am"
      System.out.format("%tD%n", c);                 //  -->  "05/29/06"
    }
}
Note: The discussion in this section covers just the basics of the format and printf methods. Further detail can be found in the Basic I/O section titled "Formatting". Using String.format to create strings is covered in Strings.

The DecimalFormat Class

You can use the java.text.DecimalFormat class to control the display of leading and trailing zeros, prefixes and suffixes, grouping (thousands) separators, and the decimal separator. DecimalFormat offers a great deal of flexibility in the formatting of numbers, but it can make your code more complex.

The example that follows creates a DecimalFormat object, myFormatter, by passing a pattern string to the DecimalFormat constructor. The format() method, which DecimalFormat inherits from NumberFormat, is then invoked by myFormatter—it accepts a double value as an argument and returns the formatted number in a string:

Here is a sample program that illustrates the use of DecimalFormat:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.text.*;

public class DecimalFormatDemo {

   static public void customFormat(String pattern, double value ) {
      DecimalFormat myFormatter = new DecimalFormat(pattern);
      String output = myFormatter.format(value);
      System.out.println(value + "  " + pattern + "  " + output);
   }

   static public void main(String[] args) {

      customFormat("###,###.###", 123456.789);
      customFormat("###.##", 123456.789);
      customFormat("000000.000", 123.78);
      customFormat("$###,###.###", 12345.67);
   }
}

The output is:

123456.789  ###,###.###  123,456.789
123456.789  ###.##  123456.79
123.78  000000.000  000123.780
12345.67  $###,###.###  $12,345.67

The following table explains each line of output.

DecimalFormat.java Output
Value | Pattern | Output | Explanation
123456.789 ###,###.### 123,456.789 The pound sign (#) denotes a digit, the comma is a placeholder for the grouping separator, and the period is a placeholder for the decimal separator.
123456.789 ###.## 123456.79 The value has three digits to the right of the decimal point, but the pattern has only two. The format method handles this by rounding up.
123.78 | 000000.000 | 000123.780 | The pattern specifies leading and trailing zeros, because the 0 character is used instead of the pound sign (#).
12345.67 $###,###.### $12,345.67 The first character in the pattern is the dollar sign ($). Note that it immediately precedes the leftmost digit in the formatted output.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Numbers Classes
Next page: Beyond Basic Arithmetic


Beyond Basic Arithmetic (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Section: Numbers
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Home Page > Learning the Java Language > Numbers and Strings
« Previous • Trail • Next »
Beyond Basic Arithmetic
The Java programming language supports basic arithmetic with its arithmetic operators: +, -, *, /, and %. The Math class in the java.lang package provides methods and constants for doing more advanced mathematical computation.

The methods in the Math class are all static, so you call them directly from the class, like this:

Math.cos(angle);
Note : Using the static import language feature, you don't have to write Math in front of every math function:
import static java.lang.Math.*;
This allows you to invoke the Math class methods by their simple names. For example:
cos(angle);

Constants and Basic Methods

The Math class includes two constants:
  • Math.E, which is the base of natural logarithms, and
  • Math.PI, which is the ratio of the circumference of a circle to its diameter.
The Math class also includes more than 40 static methods. The following table lists a number of the basic methods.

Basic Math Methods
Method | Description
double abs(double d)
float abs(float f)
int abs(int i)
long abs(long lng) 		Returns the absolute value of the argument.
double ceil(double d) | Returns the smallest integer that is greater than or equal to the argument. Returned as a double.
double floor(double d) | Returns the largest integer that is less than or equal to the argument. Returned as a double.
double rint(double d) | Returns the integer that is closest in value to the argument. Returned as a double.
long round(double d)
int round(float f) 		Returns the closest long or int, as indicated by the method's return type, to the argument.
double min(double arg1, double arg2)
float min(float arg1, float arg2)
int min(int arg1, int arg2)
long min(long arg1, long arg2) 		Returns the smaller of the two arguments.
double max(double arg1, double arg2)
float max(float arg1, float arg2)
int max(int arg1, int arg2)
long max(long arg1, long arg2) 		Returns the larger of the two arguments.

The following program, BasicMathDemo , illustrates how to use some of these methods:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class BasicMathDemo {
    public static void main(String[] args) {
        double a = -191.635;
        double b = 43.74;
        int c = 16, d = 45;

        System.out.printf("The absolute value of %.3f is %.3f%n", a, Math.abs(a));
        System.out.printf("The ceiling of %.2f is %.0f%n", b, Math.ceil(b));
        System.out.printf("The floor of %.2f is %.0f%n", b, Math.floor(b));
        System.out.printf("The rint of %.2f is %.0f%n", b, Math.rint(b));
        System.out.printf("The max of %d and %d is %d%n",c, d, Math.max(c, d));
        System.out.printf("The min of of %d and %d is %d%n",c, d, Math.min(c, d));

    }
}
Here's the output from this program:
The absolute value of -191.635 is 191.635
The ceiling of 43.74 is 44
The floor of 43.74 is 43
The rint of 43.74 is 44
The max of 16 and 45 is 45
The min of 16 and 45 is 16

Exponential and Logarithmic Methods

The next table lists exponential and logarithmic methods of the Math class.

Exponential and Logarithmic Methods
Method | Description
double exp(double d) | Returns the base of the natural logarithms, e, to the power of the argument.
double log(double d) | Returns the natural logarithm of the argument.
double pow(double base, double exponent) | Returns the value of the first argument raised to the power of the second argument.
double sqrt(double d) | Returns the square root of the argument.

The following program, ExponentialDemo , displays the value of e, then calls each of the methods listed in the previous table on arbitrarily chosen numbers:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class ExponentialDemo {
    public static void main(String[] args) {
        double x = 11.635;
        double y = 2.76;

        System.out.printf("The value of e is %.4f%n", Math.E);
        System.out.printf("exp(%.3f) is %.3f%n", x, Math.exp(x));
        System.out.printf("log(%.3f) is %.3f%n", x, Math.log(x));
        System.out.printf("pow(%.3f, %.3f) is %.3f%n", x, y, Math.pow(x, y));
        System.out.printf("sqrt(%.3f) is %.3f%n", x, Math.sqrt(x));
    }
}
Here's the output you'll see when you run ExponentialDemo:
The value of e is 2.7183
exp(11.635) is 112983.831
log(11.635) is 2.454
pow(11.635, 2.760) is 874.008
sqrt(11.635) is 3.411

Trigonometric Methods

The Math class also provides a collection of trigonometric functions, which are summarized in the following table. The value passed into each of these methods is an angle expressed in radians. You can use the toRadians method to convert from degrees to radians.

Trigonometric Methods
Method | Description
double sin(double d) | Returns the sine of the specified double value.
double cos(double d) | Returns the cosine of the specified double value.
double tan(double d) | Returns the tangent of the specified double value.
double asin(double d) | Returns the arcsine of the specified double value.
double acos(double d) | Returns the arccosine of the specified double value.
double atan(double d) | Returns the arctangent of the specified double value.
double atan2(double y, double x) | Converts rectangular coordinates (x, y) to polar coordinate (r, theta) and returns theta.
double toDegrees(double d)
double toRadians(double d) 		Converts the argument to degrees or radians.

Here's a program, TrigonometricDemo , that uses each of these methods to compute various trigonometric values for a 45-degree angle:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class TrigonometricDemo {
    public static void main(String[] args) {
        double degrees = 45.0;
        double radians = Math.toRadians(degrees);

        System.out.format("The value of pi is %.4f%n", Math.PI);
        System.out.format("The sine of %.1f degrees is %.4f%n", degrees,
                                                    Math.sin(radians));
        System.out.format("The cosine of %.1f degrees is %.4f%n", degrees,
                               Math.cos(radians));
        System.out.format("The tangent of %.1f degrees is %.4f%n", degrees,
                               Math.tan(radians));
        System.out.format("The arcsine of %.4f is %.4f degrees %n",
                              Math.sin(radians),
                              Math.toDegrees(Math.asin(Math.sin(radians))));
        System.out.format("The arccosine of %.4f is %.4f degrees %n",
                              Math.cos(radians),
                              Math.toDegrees(Math.acos(Math.cos(radians))));
        System.out.format("The arctangent of %.4f is %.4f degrees %n",
                              Math.tan(radians),
                              Math.toDegrees(Math.atan(Math.tan(radians))));

    }
}
The output of this program is as follows:
The value of pi is 3.1416
The sine of 45.0 degrees is 0.7071
The cosine of 45.0 degrees is 0.7071
The tangent of 45.0 degrees is 1.0000
The arcsine of 0.7071 is 45.0000 degrees
The arccosine of 0.7071 is 45.0000 degrees
The arctangent of 1.0000 is 45.0000 degrees

Random Numbers

The random() method returns a pseudo-randomly selected number between 0.0 and 1.0. The range includes 0.0 but not 1.0. In other words: 0.0 <= Math.random()="Math.random()" <="<" 1.0. To get a number in a different range, you can perform arithmetic on the value returned by the random method. For example, to generate an integer between 0 and 9, you would write:
int number = (int)(Math.random() * 10);
By multiplying the value by 10, the range of possible values becomes 0.0 <= number="number" <="<" 10.0.

Using Math.random works well when you need to generate a single random number. If you need to generate a series of random numbers, you should create an instance of java.util.Random and invoke methods on that object to generate numbers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Formatting Numeric Print Output
Next page: Summary of Numbers


Summary of Numbers (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Section: Numbers
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Home Page > Learning the Java Language > Numbers and Strings
« Previous • Trail • Next »
Summary of Numbers
You use one of the wrapper classes – Byte, Double, Float, Integer, Long, or Short – to wrap a number of primitive type in an object. The Java compiler automatically wraps (boxes) primitives for you when necessary and unboxes them, again when necessary.

The Number classes include constants and useful class methods. The MIN_VALUE and MAX_VALUE constants contain the smallest and largest values that can be contained by an object of that type. The byteValue, shortValue, and similar methods convert one numeric type to another. The valueOf method converts a string to a number, and the toString method converts a number to a string.

To format a string containing numbers for output, you can use the printf() or format() methods in the PrintStream class. Alternatively, you can use the NumberFormat class to customize numerical formats using patterns.

The Math class contains a variety of class methods for performing mathematical functions, including exponential, logarithmic, and trigonometric methods. Math also includes basic arithmetic functions, such as absolute value and rounding, and a method, random(), for generating random numbers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beyond Basic Arithmetic
Next page: Questions and Exercises: Numbers


Questions and Exercises: Numbers (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Home Page > Learning the Java Language > Numbers and Strings
« Previous • Trail • Next »
Questions and Exercises: Numbers

Questions

1. Use the API documentation to find the answers to the following questions:
a. What Integer method can you use to convert an int into a string that expresses the number in hexadecimal? For example, what method converts the integer 65 into the string "41"?

b. What Integer method would you use to convert a string expressed in base 5 into the equivalent int? For example, how would you convert the string "230" into the integer value 65? Show the code you would use to accomplish this task.

c. What Double method can you use to detect whether a floating-point number has the special value Not a Number (NaN)?

2. What is the value of the following expression, and why?
Integer.valueOf(1).equals(Long.valueOf(1))

Exercises

1. Change MaxVariablesDemo to show minimum values instead of maximum values. You can delete all code related to the variables aChar and aBoolean. What is the output?

2. Create a program that reads an unspecified number of integer arguments from the command line and adds them together. For example, suppose that you enter the following:

java Adder 1 3 2 10
The program should display 16 and then exit. The program should display an error message if the user enters only one argument. You can base your program on ValueOfDemo.

3. Create a program that is similar to the previous one but has the following differences:

  • Instead of reading integer arguments, it reads floating-point arguments.
  • It displays the sum of the arguments, using exactly two digits to the right of the decimal point.
For example, suppose that you enter the following:
java FPAdder 1 1e2 3.0 4.754
The program would display 108.75. Depending on your locale, the decimal point might be a comma (,) instead of a period (.).

Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary of Numbers
Next page: Characters


Characters (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Home Page > Learning the Java Language > Numbers and Strings
« Previous • Trail • Next »
Characters
Most of the time, if you are using a single character value, you will use the primitive char type. For example:
char ch = 'a';
char uniChar = '\u039A'; // Unicode for uppercase Greek omega character
char[] charArray ={ 'a', 'b', 'c', 'd', 'e' }; // an array of chars
There are times, however, when you need to use a char as an object—for example, as a method argument where an object is expected. The Java programming language provides a wrapper class that "wraps" the char in a Character object for this purpose. An object of type Character contains a single field, whose type is char. This Character class also offers a number of useful class (i.e., static) methods for manipulating characters.

You can create a Character object with the Character constructor:

Character ch = new Character('a');
The Java compiler will also create a Character object for you under some circumstances. For example, if you pass a primitive char into a method that expects an object, the compiler automatically converts the char to a Character for you. This feature is called autoboxing—or unboxing, if the conversion goes the other way.

Here is an example of boxing,

Character ch = 'a'; // the primitive char 'a' is boxed into the Character object ch
and here is an example of both boxing and unboxing,
Character test(Character c) {...} // method parameter and return type = Character object

char c = test('x'); // primitive 'x' is boxed for method test, return is unboxed to char 'c'
Note: The Character class is immutable, so that once it is created, a Character object cannot be changed.
The following table lists some of the most useful methods in the Character class, but is not exhaustive. For a complete listing of all methods in this class (there are more than 50), refer to the java.lang.Character API specification.

Useful Methods in the Character Class
Method | Description
boolean isLetter(char ch)
boolean isDigit(char ch) 		Determines whether the specified char value is a letter or a digit, respectively.
boolean isWhiteSpace(char ch) | Determines whether the specified char value is white space.
boolean isUpperCase(char ch)
boolean isLowerCase(char ch) 		Determines whether the specified char value is uppercase or lowercase, respectively.
char toUpperCase(char ch)
char toLowerCase(char ch) 		Returns the uppercase or lowercase form of the specified char value.
toString(char ch) | Returns a String object representing the specified character value—that is, a one-character string.

Escape Sequences

A character preceded by a backslash (\) is an escape sequence and has special meaning to the compiler. The newline character (\n) has been used frequently in this tutorial in System.out.println() statements to advance to the next line after the string is printed. The following table shows the Java escape sequences:

Escape Sequences
Escape Sequence | Description
\t | Insert a tab in the text at this point.
\b | Insert a backspace in the text at this point.
\n | Insert a newline in the text at this point.
\r | Insert a carriage return in the text at this point.
\f | Insert a formfeed in the text at this point.
\' Insert a single quote character in the text at this point.
\" Insert a double quote character in the text at this point.
\\ Insert a backslash character in the text at this point.

When an escape sequence is encountered in a print statement, the compiler interprets it accordingly. For example, if you want to put quotes within quotes you must use the escape sequence, \", on the interior quotes. To print the sentence

She said "Hello!" to me.
you would write
System.out.println("She said \"Hello!\" to me.");
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Numbers
Next page: Strings


Strings (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Home Page > Learning the Java Language > Numbers and Strings
« Previous • Trail • Next »
Strings
Strings, which are widely used in Java programming, are a sequence of characters. In the Java programming language, strings are objects.

The Java platform provides the String class to create and manipulate strings.

Creating Strings

The most direct way to create a string is to write:
String greeting = "Hello world!";
In this case, "Hello world!" is a string literal—a series of characters in your code that is enclosed in double quotes. Whenever it encounters a string literal in your code, the compiler creates a String object with its value—in this case, Hello world!.

As with any other object, you can create String objects by using the new keyword and a constructor. The String class has 11 constructors that allow you to provide the initial value of the string using different sources, such as an array of characters:

char[] helloArray = { 'h', 'e', 'l', 'l', 'o', '.'};
String helloString = new String(helloArray);
System.out.println(helloString);
The last line of this code snippet displays hello.

Note: The String class is immutable, so that once it is created a String object cannot be changed. The String class has a number of methods, some of which will be discussed below, that appear to modify strings. Since strings are immutable, what these methods really do is create and return a new string that contains the result of the operation.

String Length

Methods used to obtain information about an object are known as accessor methods. One accessor method that you can use with strings is the length() method, which returns the number of characters contained in the string object. After the following two lines of code have been executed, len equals 17:
String palindrome = "Dot saw I was Tod";
int len = palindrome.length();
A palindrome is a word or sentence that is symmetric—it is spelled the same forward and backward, ignoring case and punctuation. Here is a short and inefficient program to reverse a palindrome string. It invokes the String method charAt(i), which returns the ith character in the string, counting from 0.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class StringDemo {
    public static void main(String[] args) {
        String palindrome = "Dot saw I was Tod";
        int len = palindrome.length();
        char[] tempCharArray = new char[len];
        char[] charArray = new char[len];

        // put original string in an array of chars
        for (int i = 0; i < len; i++) {
            tempCharArray[i] = palindrome.charAt(i);
        }

        // reverse array of chars
        for (int j = 0; j < len; j++) {
            charArray[j] = tempCharArray[len - 1 - j];
        }

        String reversePalindrome =  new String(charArray);
        System.out.println(reversePalindrome);
    }
}
Running the program produces this output:
doT saw I was toD
To accomplish the string reversal, the program had to convert the string to an array of characters (first for loop), reverse the array into a second array (second for loop), and then convert back to a string. The String class includes a method, getChars(), to convert a string, or a portion of a string, into an array of characters so we could replace the first for loop in the program above with
palindrome.getChars(0, len - 1, tempCharArray, 0);

Concatenating Strings

The String class includes a method for concatenating two strings:
string1.concat(string2);
This returns a new string that is string1 with string2 added to it at the end.

You can also use the concat() method with string literals, as in:

"My name is ".concat("Rumplestiltskin");
Strings are more commonly concatenated with the + operator, as in
"Hello," + " world" + "!"
which results in
"Hello, world!"
The + operator is widely used in print statements. For example:
String string1 = "saw I was ";
System.out.println("Dot " + string1 + "Tod");
which prints
Dot saw I was Tod
Such a concatenation can be a mixture of any objects. For each object that is not a String, its toString() method is called to convert it to a String.
Note: The Java programming language does not permit literal strings to span lines in source files, so you must use the + concatenation operator at the end of each line in a multi-line string. For example,
String quote = "Now is the time for all good " +
        "men to come to the aid of their country.";
Breaking strings between lines using the + concatenation operator is, once again, very common in print statements.

Creating Format Strings

You have seen the use of the printf() and format() methods to print output with formatted numbers. The String class has an equivalent class method, format(), that returns a String object rather than a PrintStream object.

Using String's static format() method allows you to create a formatted string that you can reuse, as opposed to a one-time print statement. For example, instead of

System.out.printf("The value of the float variable is %f, while the value of the " +
                   "integer variable is %d, and the string is %s", floatVar, intVar, stringVar);
you can write
String fs;
fs = String.format("The value of the float variable is %f, while the value of the " +
                   "integer variable is %d, and the string is %s", floatVar, intVar, stringVar);
System.out.println(fs);
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Characters
Next page: Converting Between Numbers and Strings


Converting Between Numbers and Strings (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Section: Strings
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Home Page > Learning the Java Language > Numbers and Strings
« Previous • Trail • Next »
Converting Between Numbers and Strings

Converting Strings to Numbers

Frequently, a program ends up with numeric data in a string object—a value entered by the user, for example.

The Number subclasses that wrap primitive numeric types ( Byte, Integer, Double, Float, Long, and Short) each provide a class method named valueOf that converts a string to an object of that type. Here is an example, ValueOfDemo , that gets two strings from the command line, converts them to numbers, and performs arithmetic operations on the values:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class ValueOfDemo {
    public static void main(String[] args) {

        //this program requires two arguments on the command line
        if (args.length == 2) {
            //convert strings to numbers
            float a = (Float.valueOf(args[0]) ).floatValue();
            float b = (Float.valueOf(args[1]) ).floatValue();

            //do some arithmetic
            System.out.println("a + b = " + (a + b) );
            System.out.println("a - b = " + (a - b) );
            System.out.println("a * b = " + (a * b) );
            System.out.println("a / b = " + (a / b) );
            System.out.println("a % b = " + (a % b) );
        } else {
           System.out.println("This program requires two command-line arguments.");
        }
    }
}
The following is the output from the program when you use 4.5 and 87.2 for the command-line arguments:
a + b = 91.7
a - b = -82.7
a * b = 392.4
a / b = 0.0516055
a % b = 4.5
Note: Each of the Number subclasses that wrap primitive numeric types also provides a parseXXXX() method (for example, parseFloat()) that can be used to convert strings to primitive numbers. Since a primitive type is returned instead of an object, the parseFloat() method is more direct than the valueOf() method. For example, in the ValueOfDemo program, we could use:
float a = Float.parseFloat(args[0]);
float b = Float.parseFloat(args[1]);

Converting Numbers to Strings

Sometimes you need to convert a number to a string because you need to operate on the value in its string form. There are several easy ways to convert a number to a string:
int i;
String s1 = "" + i; //Concatenate "i" with an empty string;
                    //conversion is handled for you.
or
String s2 = String.valueOf(i);  //The valueOf class method.
Each of the Number subclasses includes a class method, toString(), that will convert its primitive type to a string. For example:
int i;
double d;
String s3 = Integer.toString(i);
String s4 = Double.toString(d);
The ToStringDemo example uses the toString method to convert a number to a string. The program then uses some string methods to compute the number of digits before and after the decimal point:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class ToStringDemo {

    public static void main(String[] args) {
        double d = 858.48;
        String s = Double.toString(d);

        int dot = s.indexOf('.');

        System.out.println(dot + " digits before decimal point.");
        System.out.println( (s.length() - dot - 1) +
        " digits after decimal point.");
    }
}
The output of this program is:
3 digits before decimal point.
2 digits after decimal point.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Strings
Next page: Manipulating Characters in a String


Manipulating Characters in a String (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Section: Strings
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Home Page > Learning the Java Language > Numbers and Strings
« Previous • Trail • Next »
Manipulating Characters in a String
The String class has a number of methods for examining the contents of strings, finding characters or substrings within a string, changing case, and other tasks.

Getting Characters and Substrings by Index

You can get the character at a particular index within a string by invoking the charAt() accessor method. The index of the first character is 0, while the index of the last character is length()-1. For example, the following code gets the character at index 9 in a string:
String anotherPalindrome = "Niagara. O roar again!";
char aChar = anotherPalindrome.charAt(9);
Indices begin at 0, so the character at index 9 is 'O', as illustrated in the following figure:

Use the charAt method to get a character at a particular index.

If you want to get more than one consecutive character from a string, you can use the substring method. The substring method has two versions, as shown in the following table:

The substring Methods in the String Class
Method | Description
String substring(int beginIndex, int endIndex) | Returns a new string that is a substring of this string. The first integer argument specifies the index of the first character. The second integer argument is the index of the last character + 1.
String substring(int beginIndex) | Returns a new string that is a substring of this string. The integer argument specifies the index of the first character. Here, the returned substring extends to the end of the original string.

The following code gets from the Niagara palindrome the substring that extends from index 11 up to, but not including, index 15, which is the word "roar":

String anotherPalindrome = "Niagara. O roar again!";
String roar = anotherPalindrome.substring(11, 15);

Use the substring method to get part of a string.

Other Methods for Manipulating Strings

Here are several other String methods for manipulating strings:

Other Methods in the String Class for Manipulating Strings
Method | Description
String[] split(String regex)
String[] split(String regex, int limit) 		Searches for a match as specified by the string argument (which contains a regular expression) and splits this string into an array of strings accordingly. The optional integer argument specifies the maximum size of the returned array. Regular expressions are covered in the lesson titled "Regular Expressions."
CharSequence subSequence(int beginIndex, int endIndex) | Returns a new character sequence constructed from beginIndex index up until endIndex - 1.
String trim() | Returns a copy of this string with leading and trailing white space removed.
String toLowerCase()
String toUpperCase() 		Returns a copy of this string converted to lowercase or uppercase. If no conversions are necessary, these methods return the original string.

Searching for Characters and Substrings in a String

Here are some other String methods for finding characters or substrings within a string. The String class provides accessor methods that return the position within the string of a specific character or substring: indexOf() and lastIndexOf(). The indexOf() methods search forward from the beginning of the string, and the lastIndexOf() methods search backward from the end of the string. If a character or substring is not found, indexOf() and lastIndexOf() return -1.

The String class also provides a search method, contains, that returns true if the string contains a particular character sequence. Use this method when you only need to know that the string contains a character sequence, but the precise location isn't important.

The following table describes the various string search methods.

The Search Methods in the String Class
Method | Description
int indexOf(int ch)
int lastIndexOf(int ch) 		Returns the index of the first (last) occurrence of the specified character.
int indexOf(int ch, int fromIndex)
int lastIndexOf(int ch, int fromIndex) 		Returns the index of the first (last) occurrence of the specified character, searching forward (backward) from the specified index.
int indexOf(String str)
int lastIndexOf(String str) 		Returns the index of the first (last) occurrence of the specified substring.
int indexOf(String str, int fromIndex)
int lastIndexOf(String str, int fromIndex) 		Returns the index of the first (last) occurrence of the specified substring, searching forward (backward) from the specified index.
boolean contains(CharSequence s) | Returns true if the string contains the specified character sequence.

Note: CharSequence is an interface that is implemented by the String class. Therefore, you can use a string as an argument for the contains() method.

Replacing Characters and Substrings into a String

The String class has very few methods for inserting characters or substrings into a string. In general, they are not needed: You can create a new string by concatenation of substrings you have removed from a string with the substring that you want to insert.

The String class does have four methods for replacing found characters or substrings, however. They are:

Methods in the String Class for Manipulating Strings
Method | Description
String replace(char oldChar, char newChar) | Returns a new string resulting from replacing all occurrences of oldChar in this string with newChar.
String replace(CharSequence target, CharSequence replacement) | Replaces each substring of this string that matches the literal target sequence with the specified literal replacement sequence.
String replaceAll(String regex, String replacement) | Replaces each substring of this string that matches the given regular expression with the given replacement.
String replaceFirst(String regex, String replacement) | Replaces the first substring of this string that matches the given regular expression with the given replacement.

An Example

The following class, Filename, illustrates the use of lastIndexOf() and substring() to isolate different parts of a file name.

Note: The methods in the following Filename class don't do any error checking and assume that their argument contains a full directory path and a filename with an extension. If these methods were production code, they would verify that their arguments were properly constructed.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * This class assumes that the string used to initialize
 * fullPath has a directory path, filename, and extension.
 * The methods won't work if it doesn't.
 */
public class Filename {
    private String fullPath;
    private char pathSeparator, extensionSeparator;

    public Filename(String str, char sep, char ext) {
        fullPath = str;
        pathSeparator = sep;
        extensionSeparator = ext;
    }

    public String extension() {
        int dot = fullPath.lastIndexOf(extensionSeparator);
        return fullPath.substring(dot + 1);
    }

    public String filename() {  // gets filename without extension
        int dot = fullPath.lastIndexOf(extensionSeparator);
        int sep = fullPath.lastIndexOf(pathSeparator);
        return fullPath.substring(sep + 1, dot);
    }

    public String path() {
        int sep = fullPath.lastIndexOf(pathSeparator);
        return fullPath.substring(0, sep);
    }
}
Here is a program, FilenameDemo, that constructs a Filename object and calls all of its methods:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class FilenameDemo {
    public static void main(String[] args) {
        final String FPATH = "/home/mem/index.html";
        Filename myHomePage = new Filename(FPATH,
                                           '/', '.');
        System.out.println("Extension = " +
             myHomePage.extension());
        System.out.println("Filename = " +
             myHomePage.filename());
        System.out.println("Path = " +
             myHomePage.path());
    }
}
And here's the output from the program:
Extension = html
Filename = index
Path = /home/mem
As shown in the following figure, our extension method uses lastIndexOf to locate the last occurrence of the period (.) in the file name. Then substring uses the return value of lastIndexOf to extract the file name extension — that is, the substring from the period to the end of the string. This code assumes that the file name has a period in it; if the file name does not have a period, lastIndexOf returns -1, and the substring method throws a StringIndexOutOfBoundsException.

The use of lastIndexOf and substring in the extension method in the Filename class.

Also, notice that the extension method uses dot + 1 as the argument to substring. If the period character (.) is the last character of the string, dot + 1 is equal to the length of the string, which is one larger than the largest index into the string (because indices start at 0). This is a legal argument to substring because that method accepts an index equal to, but not greater than, the length of the string and interprets it to mean "the end of the string."

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Converting Between Numbers and Strings
Next page: Comparing Strings and Portions of Strings


Comparing Strings and Portions of Strings (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Section: Strings
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Home Page > Learning the Java Language > Numbers and Strings
« Previous • Trail • Next »
Comparing Strings and Portions of Strings
The String class has a number of methods for comparing strings and portions of strings. The following table lists these methods.

Methods for Comparing Strings
Method | Description
boolean endsWith(String suffix)

boolean startsWith(String prefix) 		Returns true if this string ends with or begins with the substring specified as an argument to the method.
boolean startsWith(String prefix, int offset) | Considers the string beginning at the index offset, and returns true if it begins with the substring specified as an argument.
int compareTo(String anotherString) | Compares two strings lexicographically. Returns an integer indicating whether this string is greater than (result is > 0), equal to (result is = 0), or less than (result is < 0) the argument.
int compareToIgnoreCase(String str) | Compares two strings lexicographically, ignoring differences in case. Returns an integer indicating whether this string is greater than (result is > 0), equal to (result is = 0), or less than (result is < 0) the argument.
boolean equals(Object anObject) | Returns true if and only if the argument is a String object that represents the same sequence of characters as this object.
boolean equalsIgnoreCase(String anotherString) | Returns true if and only if the argument is a String object that represents the same sequence of characters as this object, ignoring differences in case.
boolean regionMatches(int toffset, String other, int ooffset, int len) Tests whether the specified region of this string matches the specified region of the String argument.

Region is of length len and begins at the index toffset for this string and ooffset for the other string.

boolean regionMatches(boolean ignoreCase, int toffset, String other, int ooffset, int len) Tests whether the specified region of this string matches the specified region of the String argument.

Region is of length len and begins at the index toffset for this string and ooffset for the other string.

The boolean argument indicates whether case should be ignored; if true, case is ignored when comparing characters.

boolean matches(String regex) | Tests whether this string matches the specified regular expression. Regular expressions are discussed in the lesson titled "Regular Expressions."

The following program, RegionMatchesDemo, uses the regionMatches method to search for a string within another string:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class RegionMatchesDemo {
    public static void main(String[] args) {
        String searchMe = "Green Eggs and Ham";
        String findMe = "Eggs";
        int searchMeLength = searchMe.length();
        int findMeLength = findMe.length();
        boolean foundIt = false;
        for (int i = 0; i <= (searchMeLength - findMeLength); i++) {
           if (searchMe.regionMatches(i, findMe, 0, findMeLength)) {
              foundIt = true;
              System.out.println(searchMe.substring(i, i + findMeLength));
              break;
           }
        }
        if (!foundIt) System.out.println("No match found.");
    }
}
The output from this program is Eggs.

The program steps through the string referred to by searchMe one character at a time. For each character, the program calls the regionMatches method to determine whether the substring beginning with the current character matches the string the program is looking for.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Manipulating Characters in a String
Next page: The StringBuilder Class


The StringBuilder Class (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Section: Strings
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Home Page > Learning the Java Language > Numbers and Strings
« Previous • Trail • Next »
The StringBuilder Class
StringBuilder objects are like String objects, except that they can be modified. Internally, these objects are treated like variable-length arrays that contain a sequence of characters. At any point, the length and content of the sequence can be changed through method invocations.

Strings should always be used unless string builders offer an advantage in terms of simpler code (see the sample program at the end of this section) or better performance. For example, if you need to concatenate a large number of strings, appending to a StringBuilder object is more efficient.

Length and Capacity

The StringBuilder class, like the String class, has a length() method that returns the length of the character sequence in the builder.

Unlike strings, every string builder also has a capacity, the number of character spaces that have been allocated. The capacity, which is returned by the capacity() method, is always greater than or equal to the length (usually greater than) and will automatically expand as necessary to accommodate additions to the string builder.

StringBuilder Constructors
Constructor | Description
StringBuilder() | Creates an empty string builder with a capacity of 16 (16 empty elements).
StringBuilder(CharSequence cs) | Constructs a string builder containing the same characters as the specified CharSequence, plus an extra 16 empty elements trailing the CharSequence.
StringBuilder(int initCapacity) | Creates an empty string builder with the specified initial capacity.
StringBuilder(String s) | Creates a string builder whose value is initialized by the specified string, plus an extra 16 empty elements trailing the string.

For example, the following code

StringBuilder sb = new StringBuilder(); // creates empty builder, capacity 16
sb.append("Greetings");  // adds 9 character string at beginning
will produce a string builder with a length of 9 and a capacity of 16:

A string builder's length is the number of characters it contains; a string builder's

The StringBuilder class has some methods related to length and capacity that the String class does not have:

Length and Capacity Methods
Method | Description
void setLength(int newLength) | Sets the length of the character sequence. If newLength is less than length(), the last characters in the character sequence are truncated. If newLength is greater than length(), null characters are added at the end of the character sequence.
void ensureCapacity(int minCapacity) | Ensures that the capacity is at least equal to the specified minimum.

A number of operations (for example, append(), insert(), or setLength()) can increase the length of the character sequence in the string builder so that the resultant length() would be greater than the current capacity(). When this happens, the capacity is automatically increased.

StringBuilder Operations

The principal operations on a StringBuilder that are not available in String are the append() and insert() methods, which are overloaded so as to accept data of any type. Each converts its argument to a string and then appends or inserts the characters of that string to the character sequence in the string builder. The append method always adds these characters at the end of the existing character sequence, while the insert method adds the characters at a specified point.

Here are a number of the methods of the StringBuilder class.

Various StringBuilder Methods
Method | Description
StringBuilder append(boolean b)
StringBuilder append(char c)
StringBuilder append(char[] str)
StringBuilder append(char[] str, int offset, int len)
StringBuilder append(double d)
StringBuilder append(float f)
StringBuilder append(int i)
StringBuilder append(long lng)
StringBuilder append(Object obj)
StringBuilder append(String s) 		Appends the argument to this string builder. The data is converted to a string before the append operation takes place.
StringBuilder delete(int start, int end)
StringBuilder deleteCharAt(int index) 		Deletes the specified character(s) in this string builder.
StringBuilder insert(int offset, boolean b)
StringBuilder insert(int offset, char c)
StringBuilder insert(int offset, char[] str)
StringBuilder insert(int index, char[] str, int offset, int len)
StringBuilder insert(int offset, double d)
StringBuilder insert(int offset, float f)
StringBuilder insert(int offset, int i)
StringBuilder insert(int offset, long lng)
StringBuilder insert(int offset, Object obj)
StringBuilder insert(int offset, String s) 		Inserts the second argument into the string builder. The first integer argument indicates the index before which the data is to be inserted. The data is converted to a string before the insert operation takes place.
StringBuilder replace(int start, int end, String s)
void setCharAt(int index, char c) 		Replaces the specified character(s) in this string builder.
StringBuilder reverse() | Reverses the sequence of characters in this string builder.
String toString() | Returns a string that contains the character sequence in the builder.

Note: You can use any String method on a StringBuilder object by first converting the string builder to a string with the toString() method of the StringBuilder class. Then convert the string back into a string builder using the StringBuilder(String str) constructor.

An Example

The StringDemo program that was listed in the section titled "Strings" is an example of a program that would be more efficient if a StringBuilder were used instead of a String.

StringDemo reversed a palindrome. Here, once again, is its listing:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class StringDemo {
    public static void main(String[] args) {
        String palindrome = "Dot saw I was Tod";
        int len = palindrome.length();
        char[] tempCharArray = new char[len];
        char[] charArray = new char[len];

        // put original string in an array of chars
        for (int i = 0; i < len; i++) {
            tempCharArray[i] = palindrome.charAt(i);
        }

        // reverse array of chars
        for (int j = 0; j < len; j++) {
            charArray[j] = tempCharArray[len - 1 - j];
        }

        String reversePalindrome =  new String(charArray);
        System.out.println(reversePalindrome);
    }
}
Running the program produces this output:
doT saw I was toD
To accomplish the string reversal, the program converts the string to an array of characters (first for loop), reverses the array into a second array (second for loop), and then converts back to a string.

If you convert the palindrome string to a string builder, you can use the reverse() method in the StringBuilder class. It makes the code simpler and easier to read:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class StringBuilderDemo {
    public static void main(String[] args) {
        String palindrome = "Dot saw I was Tod";

        StringBuilder sb = new StringBuilder(palindrome);

        sb.reverse();  // reverse it

        System.out.println(sb);
    }
}
Running this program produces the same output:
doT saw I was toD
Note that println() prints a string builder, as in:
System.out.println(sb);
because sb.toString() is called implicitly, as it is with any other object in a println() invocation.

Note: There is also a StringBuffer class that is exactly the same as the StringBuilder class, except that it is thread-safe by virtue of having its methods synchronized. Threads will be discussed in the lesson on concurrency.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Comparing Strings and Portions of Strings
Next page: Summary of Characters and Strings


Summary of Characters and Strings (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Section: Strings
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Home Page > Learning the Java Language > Numbers and Strings
« Previous • Trail • Next »
Summary of Characters and Strings
Most of the time, if you are using a single character value, you will use the primitive char type. There are times, however, when you need to use a char as an object—for example, as a method argument where an object is expected. The Java programming language provides a wrapper class that "wraps" the char in a Character object for this purpose. An object of type Character contains a single field whose type is char. This Character class also offers a number of useful class (i.e., static) methods for manipulating characters.

Strings are a sequence of characters and are widely used in Java programming. In the Java programming language, strings are objects. The String class has over 60 methods and 13 constructors.

Most commonly, you create a string with a statement like

String s = "Hello world!";
rather than using one of the String constructors.

The String class has many methods to find and retrieve substrings; these can then be easily reassembled into new strings using the + concatenation operator.

The String class also includes a number of utility methods, among them split(), toLowerCase(), toUpperCase(), and valueOf(). The latter method is indispensable in converting user input strings to numbers. The Number subclasses also have methods for converting strings to numbers and vice versa.

In addition to the String class, there is also a StringBuilder class. Working with StringBuilder objects can sometimes be more efficient than working with strings. The StringBuilder class offers a few methods that can be useful for strings, among them reverse(). In general, however, the String class has a wider variety of methods.

A string can be converted to a string builder using a StringBuilder constructor. A string builder can be converted to a string with the toString() method.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The StringBuilder Class
Next page: Questions and Exercises: Characters and Strings


Questions and Exercises: Characters and Strings (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises
Home Page > Learning the Java Language > Numbers and Strings
« Previous • Trail • Next »
Questions and Exercises: Characters and Strings

Questions

  1. What is the initial capacity of the following string builder?
    StringBuilder sb = new StringBuilder("Able was I ere I saw Elba.");

  2. Consider the following string:
    String hannah = "Did Hannah see bees? Hannah did.";
    1. What is the value displayed by the expression hannah.length()?
    2. What is the value returned by the method call hannah.charAt(12)?
    3. Write an expression that refers to the letter b in the string referred to by hannah.

  3. How long is the string returned by the following expression? What is the string?
    "Was it a car or a cat I saw?".substring(9, 12)

  4. In the following program, called ComputeResult, what is the value of result after each numbered line executes?
    /*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class ComputeResult {
    public static void main(String[] args) {
        String original = "software";
        StringBuilder result = new StringBuilder("hi");
        int index = original.indexOf('a');

/*1*/   result.setCharAt(0, original.charAt(0));
/*2*/   result.setCharAt(1, original.charAt(original.length()-1));
/*3*/   result.insert(1, original.charAt(4));
/*4*/   result.append(original.substring(1,4));
/*5*/   result.insert(3, (original.substring(index, index+2) + " "));

        System.out.println(result);
    }
}

Exercises

  1. Show two ways to concatenate the following two strings together to get the string "Hi, mom.":
    String hi = "Hi, ";
String mom = "mom.";
  2. Write a program that computes your initials from your full name and displays them.
  3. An anagram is a word or a phrase made by transposing the letters of another word or phrase; for example, "parliament" is an anagram of "partial men," and "software" is an anagram of "swear oft." Write a program that figures out whether one string is an anagram of another string. The program should ignore white space and punctuation.
Check your answers.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary of Characters and Strings
Next page: Generics


Lesson: Generics (The Java™ Tutorials > Learning the Java Language)

Generics
Introduction
Generic Types
Generic Methods and Constructors
Bounded Type Parameters
Subtyping
Wildcards
Type Erasure
Summary of Generics
Questions and Exercises
Trail: Learning the Java Language
Home Page > Learning the Java Language
« Previous • Trail • Next »
Lesson: Generics
Generics are a built-in language feature that will make your software more reliable. This lesson discusses the following topics:

Introduction

This section explains some common shortcomings associated with non-generic code. Specifically, it shows how certain kinds of bugs will crash an application at runtime, since they are not detectable by the compiler.

Generic Types

This section explains generic type declarations, type variables, type parameters, and type arguments. It also describes the naming conventions that are specific to generics.

Generic Methods and Constructors

This section shows how type parameters can be used to define generic methods and constructors.

Bounded Type Parameters

This section describes how type parameters can specify an upper bound that limits the kind of types that can be passed in.

Subtyping

This section describes how generic subtyping differs from non-generic subtyping.

Wildcards

This section continues the discussion of subtyping by describing bounded and unbounded wildcards.

Type Erasure

This section describes type erasure, raw types, and unchecked warnings.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Introduction


Introduction (The Java™ Tutorials > Learning the Java Language > Generics)

Trail: Learning the Java Language
Lesson: Generics
Generics
Introduction
Generic Types
Generic Methods and Constructors
Bounded Type Parameters
Subtyping
Wildcards
Type Erasure
Summary of Generics
Questions and Exercises
Home Page > Learning the Java Language > Generics
« Previous • Trail • Next »
Introduction
In any nontrivial software project, bugs are simply a fact of life. Careful planning, programming, and testing can help reduce their pervasiveness, but somehow, somewhere, they'll always find a way to creep into your code. This becomes especially apparent as new features are introduced and your code base grows in size and complexity.

Fortunately, some bugs are easier to detect than others. Compile-time bugs, for example, tell you immediately that something is wrong; you can use the compiler's error messages to figure out what the problem is and fix it, right then and there. Runtime bugs, however, can be much more problematic; they don't always surface immediately, and when they do, it may be at a point in time that's far removed from the actual cause of the problem.

Generics add stability to your code by making more of your bugs detectable at compile time. Some programmers choose to learn generics by studying the Java Collections Framework; after all, generics are heavily used by those classes. However, since we haven't yet covered collections, this chapter will focus primarily on simple "collections-like" examples that we'll design from scratch. This hands-on approach will teach you the necessary syntax and terminology while demonstrating the various kinds of problems that generics were designed to solve.

A Simple Box Class

Let's begin by designing a nongeneric Box class that operates on objects of any type. It need only provide two methods: add, which adds an object to the box, and get, which retrieves it:
    public class Box {

        private Object object;

        public void add(Object object) {
            this.object = object;
        }

        public Object get() {
            return object;
        }
    }
Since its methods accept or return Object, you're free to pass in whatever you want, provided that it's not one of the primitive types. However, should you need to restrict the contained type to something specific (like Integer), your only option would be to specify the requirement in documentation (or in this case, a comment), which of course the compiler knows nothing about:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class BoxDemo1 {

    public static void main(String[] args) {

        // ONLY place Integer objects into this box!
        Box integerBox = new Box();

        integerBox.add(new Integer(10));
        Integer someInteger = (Integer)integerBox.get();
        System.out.println(someInteger);
    }
}
The BoxDemo1 program creates an Integer object, passes it to add, then assigns that same object to someInteger by the return value of get. It then prints the object's value (10) to standard output. We know that the cast from Object to Integer is correct because we've honored the "contract" specified in the comment. But remember, the compiler knows nothing about this — it just trusts that our cast is correct. Furthermore, it will do nothing to prevent a careless programmer from passing in an object of the wrong type, such as String:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class BoxDemo2 {

    public static void main(String[] args) {

        // ONLY place Integer objects into this box!
        Box integerBox = new Box();

        // Imagine this is one part of a large application
        // modified by one programmer.
        integerBox.add("10"); // note how the type is now String

        // ... and this is another, perhaps written
        // by a different programmer
        Integer someInteger = (Integer)integerBox.get();
        System.out.println(someInteger);
    }
}
In BoxDemo2 we've stored the number 10 as a String, which could be the case when, say, a GUI collects input from the user. However, the existing cast from Object to Integer has mistakenly been overlooked. This is clearly a bug, but because the code still compiles, you wouldn't know anything is wrong until runtime, when the application crashes with a ClassCastException:
    Exception in thread "main"
         java.lang.ClassCastException:
            java.lang.String cannot be cast to java.lang.Integer
            at BoxDemo2.main(BoxDemo2.java:6)

If the Box class had been designed with generics in mind, this mistake would have been caught by the compiler, instead of crashing the application at runtime.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Generics
Next page: Generic Types


Generic Types (The Java™ Tutorials > Learning the Java Language > Generics)

Trail: Learning the Java Language
Lesson: Generics
Generics
Introduction
Generic Types
Generic Methods and Constructors
Bounded Type Parameters
Subtyping
Wildcards
Type Erasure
Summary of Generics
Questions and Exercises
Home Page > Learning the Java Language > Generics
« Previous • Trail • Next »
Generic Types

Let's update our Box class to use generics. We'll first create a generic type declaration by changing the code "public class Box" to "public class Box<T>"; this introduces one type variable, named T, that can be used anywhere inside the class. This same technique can be applied to interfaces as well. There's nothing particularly complex about this concept. In fact, it's quite similar to what you already know about variables in general. Just think of T as a special kind of variable, whose "value" will be whatever type you pass in; this can be any class type, any interface type, or even another type variable. It just can't be any of the primitive data types. In this context, we also say that T is a formal type parameter of the Box class.

/**
 * Generic version of the Box class.
 */
public class Box<T> {

    private T t; // T stands for "Type"

    public void add(T t) {
        this.t = t;
    }

    public T get() {
        return t;
    }
}

As you can see, we've replaced all occurrences of Object with T. To reference this generic class from within your own code, you must perform a generic type invocation, which replaces T with some concrete value, such as Integer:

Box<Integer> integerBox;
You can think of a generic type invocation as being similar to an ordinary method invocation, but instead of passing an argument to a method, you're passing a type argument — Integer in this case — to the Box class itself. Like any other variable declaration, this code does not actually create a new Box object. It simply declares that integerBox will hold a reference to a "Box of Integer", which is how Box<Integer> is read.

An invocation of a generic type is generally known as a parameterized type.

To instantiate this class, use the new keyword, as usual, but place <Integer> between the class name and the parenthesis:

integerBox = new Box<Integer>();

Or, you can put the entire statement on one line, such as:

Box<Integer> integerBox = new Box<Integer>();

Once integerBox is initialized, you're free to invoke its get method without providing a cast, as in BoxDemo3:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class BoxDemo3 {

    public static void main(String[] args) {
        Box<Integer> integerBox = new Box<Integer>();
        integerBox.add(new Integer(10));
        Integer someInteger = integerBox.get(); // no cast!
        System.out.println(someInteger);
    }
}
Furthermore, if you try adding an incompatible type to the box, such as String, compilation will fail, alerting you to what previously would have been a runtime bug:
    BoxDemo3.java:5: add(java.lang.Integer) in Box<java.lang.Integer>
    cannot be applied to (java.lang.String)
        integerBox.add("10");
                  ^
    1 error

It's important to understand that type variables are not actually types themselves. In the above examples, you won't find T.java or T.class anywhere on the filesystem. Furthermore, T is not a part of the Box class name. In fact during compilation, all generic information will be removed entirely, leaving only Box.class on the filesystem. We'll discuss this later in the section on Type Erasure

Also note that a generic type may have multiple type parameters, but each parameter must be unique within its declaring class or interface. A declaration of Box<T,T>, for example, would generate an error on the second occurrence of T, but Box<T,U>, however, would be allowed.

Type Parameter Naming Conventions

By convention, type parameter names are single, uppercase letters. This stands in sharp contrast to the variable naming conventions that you already know about, and with good reason: Without this convention, it would be difficult to tell the difference between a type variable and an ordinary class or interface name.

The most commonly used type parameter names are:

  • E - Element (used extensively by the Java Collections Framework)
  • K - Key
  • N - Number
  • T - Type
  • V - Value
  • S,U,V etc. - 2nd, 3rd, 4th types
You'll see these names used throughout the Java SE API and the rest of this tutorial.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Introduction
Next page: Generic Methods and Constructors


Generic Methods and Constructors (The Java™ Tutorials > Learning the Java Language > Generics)

Trail: Learning the Java Language
Lesson: Generics
Generics
Introduction
Generic Types
Generic Methods and Constructors
Bounded Type Parameters
Subtyping
Wildcards
Type Erasure
Summary of Generics
Questions and Exercises
Home Page > Learning the Java Language > Generics
« Previous • Trail • Next »
Generic Methods and Constructors
Type parameters can also be declared within method and constructor signatures to create generic methods and generic constructors. This is similar to declaring a generic type, but the type parameter's scope is limited to the method or constructor in which it's declared.
/**
 * This version introduces a generic method.
 */
public class Box<T> {

    private T t;

    public void add(T t) {
        this.t = t;
    }

    public T get() {
        return t;
    }

    public <U> void inspect(U u){
        System.out.println("T: " + t.getClass().getName());
        System.out.println("U: " + u.getClass().getName());
    }

    public static void main(String[] args) {
        Box<Integer> integerBox = new Box<Integer>();
        integerBox.add(new Integer(10));
        integerBox.inspect("some text");
    }
}
Here we've added one generic method, named inspect, that defines one type parameter, named U. This method accepts an object and prints its type to standard output. For comparison, it also prints out the type of T. For convenience, this class now also has a main method so that it can be run as an application.

The output from this program is:

T: java.lang.Integer
U: java.lang.String

By passing in different types, the output will change accordingly.

A more realistic use of generic methods might be something like the following, which defines a static method that stuffs references to a single item into multiple boxes:

    public static <U> void fillBoxes(U u, List<Box<U>> boxes) {
        for (Box<U> box : boxes) {
            box.add(u);
        }
    }
To use this method, your code would look something like the following:
    Crayon red = ...;
    List<Box<Crayon>> crayonBoxes = ...;
The complete syntax for invoking this method is:
Box.<Crayon>fillBoxes(red, crayonBoxes);
Here we've explicitly provided the type to be used as U, but more often than not, this can be left out and the compiler will infer the type that's needed:
Box.fillBoxes(red, crayonBoxes); // compiler infers that U is Crayon
This feature, known as type inference, allows you to invoke a generic method as you would an ordinary method, without specifying a type between angle brackets.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Generic Types
Next page: Bounded Type Parameters


Bounded Type Parameters (The Java™ Tutorials > Learning the Java Language > Generics)

Trail: Learning the Java Language
Lesson: Generics
Generics
Introduction
Generic Types
Generic Methods and Constructors
Bounded Type Parameters
Subtyping
Wildcards
Type Erasure
Summary of Generics
Questions and Exercises
Home Page > Learning the Java Language > Generics
« Previous • Trail • Next »
Bounded Type Parameters
There may be times when you'll want to restrict the kinds of types that are allowed to be passed to a type parameter. For example, a method that operates on numbers might only want to accept instances of Number or its subclasses. This is what bounded type parameters are for.

To declare a bounded type parameter, list the type parameter's name, followed by the extends keyword, followed by its upper bound, which in this example is Number. Note that, in this context, extends is used in a general sense to mean either "extends" (as in classes) or "implements" (as in interfaces).

/**
 * This version introduces a bounded type parameter.
 */
public class Box<T> {

    private T t;

    public void add(T t) {
        this.t = t;
    }

    public T get() {
        return t;
    }

    public <U extends Number> void inspect(U u){
        System.out.println("T: " + t.getClass().getName());
        System.out.println("U: " + u.getClass().getName());
    }

    public static void main(String[] args) {
        Box<Integer> integerBox = new Box<Integer>();
        integerBox.add(new Integer(10));
        integerBox.inspect("some text"); // error: this is still String!
    }
}
By modifying our generic method to include this bounded type parameter, compilation will now fail, since our invocation of inspect still includes a String:
Box.java:21: <U>inspect(U) in Box<java.lang.Integer> cannot
  be applied to (java.lang.String)
                        integerBox.inspect("10");
                                  ^
1 error

To specify additional interfaces that must be implemented, use the & character, as in:

<U extends Number & MyInterface>
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Generic Methods and Constructors
Next page: Subtyping


Subtyping (The Java™ Tutorials > Learning the Java Language > Generics)

Trail: Learning the Java Language
Lesson: Generics
Generics
Introduction
Generic Types
Generic Methods and Constructors
Bounded Type Parameters
Subtyping
Wildcards
Type Erasure
Summary of Generics
Questions and Exercises
Home Page > Learning the Java Language > Generics
« Previous • Trail • Next »
Subtyping
As you already know, it's possible to assign an object of one type to an object of another type provided that the types are compatible. For example, you can assign an Integer to an Object, since Object is one of Integer's supertypes:
    Object someObject = new Object();
    Integer someInteger = new Integer(10);
    someObject = someInteger; // OK
In object-oriented terminology, this is called an "is a" relationship. Since an Integer is a kind of Object, the assignment is allowed. But Integer is also a kind of Number, so the following code is valid as well:
    public void someMethod(Number n){
        // method body omitted
    }

    someMethod(new Integer(10)); // OK
    someMethod(new Double(10.1)); // OK

The same is also true with generics. You can perform a generic type invocation, passing Number as its type argument, and any subsequent invocation of add will be allowed if the argument is compatible with Number:

    Box<Number> box = new Box<Number>();
    box.add(new Integer(10)); // OK
    box.add(new Double(10.1)); // OK

Now consider the following method:

    public void boxTest(Box<Number> n){
        // method body omitted
    }
What type of argument does it accept? By looking at its signature, we can see that it accepts a single argument whose type is Box<Number>. But what exactly does that mean? Are you allowed to pass in Box<Integer> or Box<Double>, as you might expect? Surprisingly, the answer is "no", because Box<Integer> and Box<Double> are not subtypes of Box<Number>.

Understanding why becomes much easier if you think of tangible objects — things you can actually picture — such as a cage:

    // A cage is a collection of things, with bars to keep them in.
    interface Cage<E> extends Collection<E>;
Note: The Collection interface is the root interface of the collection hierarchy; it represents a group of objects. Since a cage would be used for holding a collection of objects (the animals), it makes sense to include it in this example.

A lion is a kind of animal, so Lion would be a subtype of Animal:

    interface Lion extends Animal {}
    Lion king = ...;

Where we need some animal, we're free to provide a lion:

    Animal a = king;

A lion can of course be put into a lion cage:

    Cage<Lion> lionCage = ...;
    lionCage.add(king);

and a butterfly into a butterfly cage:

    interface Butterfly extends Animal {}
    Butterfly monarch = ...;
    Cage<Butterfly> butterflyCage = ...;
    butterflyCage.add(monarch);

But what about an "animal cage"? English is ambiguous, so to be precise let's assume we're talking about an "all-animal cage":

    Cage<Animal> animalCage = ...;
This is a cage designed to hold all kinds of animals, mixed together. It must have bars strong enough to hold in the lions, and spaced closely enough to hold in the butterflies. Such a cage might not even be feasible to build, but if it is, then:
    animalCage.add(king);
    animalCage.add(monarch);

Since a lion is a kind of animal (Lion is a subtype of Animal), the question then becomes, "Is a lion cage a kind of animal cage? Is Cage<Lion> a subtype of Cage<Animal>?". By the above definition of animal cage, the answer must be "no". This is surprising! But it makes perfect sense when you think about it: A lion cage cannot be assumed to keep in butterflies, and a butterfly cage cannot be assumed to hold in lions. Therefore, neither cage can be considered an "all-animal" cage:

    animalCage = lionCage;	// compile-time error
        animalCage = butterflyCage; // compile-time error
Without generics, the animals could be placed into the wrong kinds of cages, where it would be possible for them to escape.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Bounded Type Parameters
Next page: Wildcards


Wildcards (The Java™ Tutorials > Learning the Java Language > Generics)

Trail: Learning the Java Language
Lesson: Generics
Generics
Introduction
Generic Types
Generic Methods and Constructors
Bounded Type Parameters
Subtyping
Wildcards
Type Erasure
Summary of Generics
Questions and Exercises
Home Page > Learning the Java Language > Generics
« Previous • Trail • Next »
Wildcards
Earlier we mentioned that English is ambiguous. The phrase "animal cage" can reasonably mean "all-animal cage", but it also suggests an entirely different concept: a cage designed not for any kind of animal, but rather for some kind of animal whose type is unknown. In generics, an unknown type is represented by the wildcard character "?".

To specify a cage capable of holding some kind of animal:

    Cage<? extends Animal> someCage = ...;
Read "? extends Animal" as "an unknown type that is a subtype of Animal, possibly Animal itself", which boils down to "some kind of animal". This is an example of a bounded wildcard, where Animal forms the upper bound of the expected type. If you're asked for a cage that simply holds some kind of animal, you're free to provide a lion cage or a butterfly cage.

Note: It's also possible to specify a lower bound by using the super keyword instead of extends. The code <? super Animal>, therefore, would be read as "an unknown type that is a supertype of Animal, possibly Animal itself". You can also specify an unknown type with an unbounded wilcard, which simply looks like <?>. An unbounded wildcard is essentially the same as saying <? extends Object>.

While Cage<Lion> and Cage<Butterfly> are not subtypes of Cage<Animal>, they are in fact subtypes of Cage<? extends Animal>:

    someCage = lionCage; // OK
    someCage = butterflyCage; // OK
So now the question becomes, "Can you add butterflies and lions directly to someCage?". As you can probably guess, the answer to this question is "no".
    someCage.add(king);	// compiler-time error
    someCage.add(monarch);	// compiler-time error
If someCage is a butterfly cage, it would hold butterflies just fine, but the lions would be able to break free. If it's a lion cage, then all would be well with the lions, but the butterflies would fly away. So if you can't put anything at all into someCage, is it useless? No, because you can still read its contents:
    void feedAnimals(Cage<? extends Animal> someCage) {
        for (Animal a : someCage)
        a.feedMe();
    }
Therefore, you could house your animals in their individual cages, as shown earlier, and invoke this method first for the lions and then for the butterflies:
    feedAnimals(lionCage);
    feedAnimals(butterflyCage);
Or, you could choose to combine your animals in the all-animal cage instead:
    feedAnimals(animalCage);

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Subtyping
Next page: Type Erasure


Type Erasure (The Java™ Tutorials > Learning the Java Language > Generics)

Trail: Learning the Java Language
Lesson: Generics
Generics
Introduction
Generic Types
Generic Methods and Constructors
Bounded Type Parameters
Subtyping
Wildcards
Type Erasure
Summary of Generics
Questions and Exercises
Home Page > Learning the Java Language > Generics
« Previous • Trail • Next »
Type Erasure

When a generic type is instantiated, the compiler translates those types by a technique called type erasure — a process where the compiler removes all information related to type parameters and type arguments within a class or method. Type erasure enables Java applications that use generics to maintain binary compatibility with Java libraries and applications that were created before generics.

For instance, Box<String> is translated to type Box, which is called the raw type — a raw type is a generic class or interface name without any type arguments. This means that you can't find out what type of Object a generic class is using at runtime. The following operations are not possible:

public class MyClass<E> {
    public static void myMethod(Object item) {
        if (item instanceof E) {  //Compiler error
            ...
        }
        E item2 = new E();   //Compiler error
        E[] iArray = new E[10]; //Compiler error
        E obj = (E)new Object(); //Unchecked cast warning
    }
}
The operations shown in bold are meaningless at runtime because the compiler removes all information about the actual type argument (represented by the type parameter E) at compile time.

Type erasure exists so that new code may continue to interface with legacy code. Using a raw type for any other reason is considered bad programming practice and should be avoided whenever possible.

When mixing legacy code with generic code, you may encounter warning messages similar to the following:

Note: WarningDemo.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
This can happen when using an older API that operates on raw types, as shown in the following WarningDemo program:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class WarningDemo {
    public static void main(String[] args){
        Box<Integer> bi;
        bi = createBox();
    }

    /**
     * Pretend that this method is part of an old library,
     * written before generics. It returns
     * Box instead of Box<T>.
     */
    static Box createBox(){
        return new Box();
    }
}
Recompiling with -Xlint:unchecked reveals the following additional information:
WarningDemo.java:4: warning: [unchecked] unchecked conversion
found   : Box
required: Box<java.lang.Integer>
        bi = createBox();
                      ^
1 warning
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Wildcards
Next page: Summary of Generics


Summary of Generics (The Java™ Tutorials > Learning the Java Language > Generics)

Trail: Learning the Java Language
Lesson: Generics
Generics
Introduction
Generic Types
Generic Methods and Constructors
Bounded Type Parameters
Subtyping
Wildcards
Type Erasure
Summary of Generics
Questions and Exercises
Home Page > Learning the Java Language > Generics
« Previous • Trail • Next »
Summary of Generics
This chapter described the following problem: We have a Box class, written to be generally useful so it deals with Objects. We need an instance that takes only Integers. The comments say that only Integers go in, so the programmer knows this (or should know it), but the compiler doesn't know it. This means that the compiler can't catch someone erroneously adding a String. When we read the value and cast it to an Integer we'll get an exception, but that's not ideal since the exception may be far removed from the bug in both space and time:
  1. Debugging may be difficult, as the point in the code where the exception is thrown may be far removed from the point in the code where the error is located.

  2. It's always better to catch bugs when compiling than when running.

Specifically, you learned that generic type declarations can include one or more type parameters; you supply one type argument for each type parameter when you use the generic type. You also learned that type parameters can be used to define generic methods and constructors. Bounded type parameters limit the kinds of types that can be passed into a type parameter; they can specify an upper bound only. Wildcards represent unknown types, and they can specify an upper or lower bound. During compilation, type erasure removes all generic information from a generic class or interface, leaving behind only its raw type. It is possible for generic code and legacy code to interact, but in many cases the compiler will emit a warning telling you to recompile with special flags for more details.

For additional information on this topic, see Generics by Gilad Bracha.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Type Erasure
Next page: Questions and Exercises: Generics


Questions and Exercises: Generics (The Java™ Tutorials > Learning the Java Language > Generics)

Trail: Learning the Java Language
Lesson: Generics
Generics
Introduction
Generic Types
Generic Methods and Constructors
Bounded Type Parameters
Subtyping
Wildcards
Type Erasure
Summary of Generics
Questions and Exercises
Home Page > Learning the Java Language > Generics
« Previous • Trail • Next »
Questions and Exercises: Generics

Questions

1. Consider the following classes:
public class AnimalHouse<E> {
    private E animal;
    public void setAnimal(E x) {
        animal = x;
    }
    public E getAnimal() {
        return animal;
    }
}

public class Animal{
}

public class Cat extends Animal {
}

public class Dog extends Animal {
}
For the following code snippets, identify whether the code:
  • fails to compile,
  • compiles with a warning,
  • generates an error at runtime, or
  • none of the above (compiles and runs without problem.)
a. AnimalHouse<Animal> house = new AnimalHouse<Cat>();

b. AnimalHouse<Dog> house = new AnimalHouse<Animal>();

c. AnimalHouse<?> house = new AnimalHouse<Cat>();
   house.setAnimal(new Cat());

d. AnimalHouse house = new AnimalHouse();
   house.setAnimal(new Dog());

Exercises

  1. Design a class that acts as a library for the following kinds of media: book, video, and newspaper. Provide one version of the class that uses generics and one that does not. Feel free to use any additional APIs for storing and retrieving the media.

Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary of Generics
Next page: Packages


Lesson: Packages (The Java™ Tutorials > Learning the Java Language)

Packages
Creating and Using Packages
Creating a Package
Naming a Package
Using Package Members
Managing Source and Class Files
Summary of Creating and Using Packages
Questions and Exercises
Trail: Learning the Java Language
Home Page > Learning the Java Language
« Previous • Trail • Next »
Lesson: Packages
This lesson explains how to bundle classes and interfaces into packages, how to use classes that are in packages, and how to arrange your file system so that the compiler can find your source files.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Creating and Using Packages


Creating and Using Packages (The Java™ Tutorials > Learning the Java Language > Packages)

Trail: Learning the Java Language
Lesson: Packages
Packages
Creating and Using Packages
Creating a Package
Naming a Package
Using Package Members
Managing Source and Class Files
Summary of Creating and Using Packages
Questions and Exercises
Home Page > Learning the Java Language > Packages
« Previous • Trail • Next »
Creating and Using Packages
To make types easier to find and use, to avoid naming conflicts, and to control access, programmers bundle groups of related types into packages.

Definition: A package is a grouping of related types providing access protection and name space management. Note that types refers to classes, interfaces, enumerations, and annotation types. Enumerations and annotation types are special kinds of classes and interfaces, respectively, so types are often referred to in this lesson simply as classes and interfaces.

The types that are part of the Java platform are members of various packages that bundle classes by function: fundamental classes are in java.lang, classes for reading and writing (input and output) are in java.io, and so on. You can put your types in packages too.

Suppose you write a group of classes that represent graphic objects, such as circles, rectangles, lines, and points. You also write an interface, Draggable, that classes implement if they can be dragged with the mouse.

//in the Draggable.java file
public interface Draggable {
    . . .
}

//in the Graphic.java file
public abstract class Graphic {
    . . .
}

//in the Circle.java file
public class Circle extends Graphic implements Draggable {
    . . .
}

//in the Rectangle.java file
public class Rectangle extends Graphic implements Draggable {
    . . .
}

//in the Point.java file
public class Point extends Graphic implements Draggable {
    . . .
}

//in the Line.java file
public class Line extends Graphic implements Draggable {
    . . .
}

You should bundle these classes and the interface in a package for several reasons, including the following:

  • You and other programmers can easily determine that these types are related.
  • You and other programmers know where to find types that can provide graphics-related functions.
  • The names of your types won't conflict with the type names in other packages because the package creates a new namespace.
  • You can allow types within the package to have unrestricted access to one another yet still restrict access for types outside the package.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Packages
Next page: Creating a Package


Creating a Package (The Java™ Tutorials > Learning the Java Language > Packages)

Trail: Learning the Java Language
Lesson: Packages
Section: Creating and Using Packages
Packages
Creating and Using Packages
Creating a Package
Naming a Package
Using Package Members
Managing Source and Class Files
Summary of Creating and Using Packages
Questions and Exercises
Home Page > Learning the Java Language > Packages
« Previous • Trail • Next »
Creating a Package
To create a package, you choose a name for the package (naming conventions are discussed in the next section) and put a package statement with that name at the top of every source file that contains the types (classes, interfaces, enumerations, and annotation types) that you want to include in the package.

The package statement (for example, package graphics;) must be the first line in the source file. There can be only one package statement in each source file, and it applies to all types in the file.

Note: If you put multiple types in a single source file, only one can be public, and it must have the same name as the source file. For example, you can define public class Circle in the file Circle.java, define public interface Draggable in the file Draggable.java, define public enum Day in the file Day.java, and so forth.

You can include non-public types in the same file as a public type (this is strongly discouraged, unless the non-public types are small and closely related to the public type), but only the public type will be accessible from outside of the package. All the top-level, non-public types will be package private.

If you put the graphics interface and classes listed in the preceding section in a package called graphics, you would need six source files, like this:
//in the Draggable.java file
package graphics;
public interface Draggable {
    . . .
}

//in the Graphic.java file
package graphics;
public abstract class Graphic {
    . . .
}

//in the Circle.java file
package graphics;
public class Circle extends Graphic implements Draggable {
    . . .
}

//in the Rectangle.java file
package graphics;
public class Rectangle extends Graphic implements Draggable {
    . . .
}

//in the Point.java file
package graphics;
public class Point extends Graphic implements Draggable {
    . . .
}

//in the Line.java file
package graphics;
public class Line extends Graphic implements Draggable {
    . . .
}
If you do not use a package statement, your type ends up in an unnamed package. Generally speaking, an unnamed package is only for small or temporary applications or when you are just beginning the development process. Otherwise, classes and interfaces belong in named packages.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating and Using Packages
Next page: Naming a Package


Naming a Package (The Java™ Tutorials > Learning the Java Language > Packages)

Trail: Learning the Java Language
Lesson: Packages
Section: Creating and Using Packages
Packages
Creating and Using Packages
Creating a Package
Naming a Package
Using Package Members
Managing Source and Class Files
Summary of Creating and Using Packages
Questions and Exercises
Home Page > Learning the Java Language > Packages
« Previous • Trail • Next »
Naming a Package
With programmers worldwide writing classes and interfaces using the Java programming language, it is likely that many programmers will use the same name for different types. In fact, the previous example does just that: It defines a Rectangle class when there is already a Rectangle class in the java.awt package. Still, the compiler allows both classes to have the same name if they are in different packages. The fully qualified name of each Rectangle class includes the package name. That is, the fully qualified name of the Rectangle class in the graphics package is graphics.Rectangle, and the fully qualified name of the Rectangle class in the java.awt package is java.awt.Rectangle.

This works well unless two independent programmers use the same name for their packages. What prevents this problem? Convention.

Naming Conventions

Package names are written in all lowercase to avoid conflict with the names of classes or interfaces.

Companies use their reversed Internet domain name to begin their package names—for example, com.example.orion for a package named orion created by a programmer at example.com.

Name collisions that occur within a single company need to be handled by convention within that company, perhaps by including the region or the project name after the company name (for example, com.company.region.package).

Packages in the Java language itself begin with java. or javax.

In some cases, the internet domain name may not be a valid package name. This can occur if the domain name contains a hyphen or other special character, if the package name begins with a digit or other character that is illegal to use as the beginning of a Java name, or if the package name contains a reserved Java keyword, such as "int". In this event, the suggested convention is to add an underscore. For example:

Legalizing Package Names
Domain Name | Package Name Prefix
clipart-open.org | org.clipart_open
free.fonts.int | int_.fonts.free
poetry.7days.com | com._7days.poetry

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating a Package
Next page: Using Package Members


Using Package Members (The Java™ Tutorials > Learning the Java Language > Packages)

Trail: Learning the Java Language
Lesson: Packages
Section: Creating and Using Packages
Packages
Creating and Using Packages
Creating a Package
Naming a Package
Using Package Members
Managing Source and Class Files
Summary of Creating and Using Packages
Questions and Exercises
Home Page > Learning the Java Language > Packages
« Previous • Trail • Next »
Using Package Members
The types that comprise a package are known as the package members.

To use a public package member from outside its package, you must do one of the following:

  • Refer to the member by its fully qualified name
  • Import the package member
  • Import the member's entire package
Each is appropriate for different situations, as explained in the sections that follow.

Referring to a Package Member by Its Qualified Name

So far, most of the examples in this tutorial have referred to types by their simple names, such as Rectangle and StackOfInts. You can use a package member's simple name if the code you are writing is in the same package as that member or if that member has been imported.

However, if you are trying to use a member from a different package and that package has not been imported, you must use the member's fully qualified name, which includes the package name. Here is the fully qualified name for the Rectangle class declared in the graphics package in the previous example.

graphics.Rectangle
You could use this qualified name to create an instance of graphics.Rectangle:
graphics.Rectangle myRect = new graphics.Rectangle();
Qualified names are all right for infrequent use. When a name is used repetitively, however, typing the name repeatedly becomes tedious and the code becomes difficult to read. As an alternative, you can import the member or its package and then use its simple name.

Importing a Package Member

To import a specific member into the current file, put an import statement at the beginning of the file before any type definitions but after the package statement, if there is one. Here's how you would import the Rectangle class from the graphics package created in the previous section.
import graphics.Rectangle;
Now you can refer to the Rectangle class by its simple name.
Rectangle myRectangle = new Rectangle();
This approach works well if you use just a few members from the graphics package. But if you use many types from a package, you should import the entire package.

Importing an Entire Package

To import all the types contained in a particular package, use the import statement with the asterisk (*) wildcard character.
import graphics.*;
Now you can refer to any class or interface in the graphics package by its simple name.
Circle myCircle = new Circle();
Rectangle myRectangle = new Rectangle();
The asterisk in the import statement can be used only to specify all the classes within a package, as shown here. It cannot be used to match a subset of the classes in a package. For example, the following does not match all the classes in the graphics package that begin with A.
import graphics.A*;     //does not work
Instead, it generates a compiler error. With the import statement, you generally import only a single package member or an entire package.
Note: Another, less common form of import allows you to import the public nested classes of an enclosing class. For example, if the graphics.Rectangle class contained useful nested classes, such as Rectangle.DoubleWide and Rectangle.Square, you could import Rectangle and its nested classes by using the following two statements.
import graphics.Rectangle;
import graphics.Rectangle.*;
Be aware that the second import statement will not import Rectangle.

Another less common form of import, the static import statement, will be discussed at the end of this section.

For convenience, the Java compiler automatically imports three entire packages for each source file: (1) the package with no name, (2) the java.lang package, and (3) the current package (the package for the current file).

Apparent Hierarchies of Packages

At first, packages appear to be hierarchical, but they are not. For example, the Java API includes a java.awt package, a java.awt.color package, a java.awt.font package, and many others that begin with java.awt. However, the java.awt.color package, the java.awt.font package, and other java.awt.xxxx packages are not included in the java.awt package. The prefix java.awt (the Java Abstract Window Toolkit) is used for a number of related packages to make the relationship evident, but not to show inclusion.

Importing java.awt.* imports all of the types in the java.awt package, but it does not import java.awt.color, java.awt.font, or any other java.awt.xxxx packages. If you plan to use the classes and other types in java.awt.color as well as those in java.awt, you must import both packages with all their files:

import java.awt.*;
import java.awt.color.*;

Name Ambiguities

If a member in one package shares its name with a member in another package and both packages are imported, you must refer to each member by its qualified name. For example, the graphics package defined a class named Rectangle. The java.awt package also contains a Rectangle class. If both graphics and java.awt have been imported, the following is ambiguous.
Rectangle rect;
In such a situation, you have to use the member's fully qualified name to indicate exactly which Rectangle class you want. For example,
graphics.Rectangle rect;

The Static Import Statement

There are situations where you need frequent access to static final fields (constants) and static methods from one or two classes. Prefixing the name of these classes over and over can result in cluttered code. The static import statement gives you a way to import the constants and static methods that you want to use so that you do not need to prefix the name of their class.

The java.lang.Math class defines the PI constant and many static methods, including methods for calculating sines, cosines, tangents, square roots, maxima, minima, exponents, and many more. For example,

public static final double PI 3.141592653589793
public static double cos(double a)
Ordinarily, to use these objects from another class, you prefix the class name, as follows.
double r = Math.cos(Math.PI * theta);
You can use the static import statement to import the static members of java.lang.Math so that you don't need to prefix the class name, Math. The static members of Math can be imported either individually:
import static java.lang.Math.PI;
or as a group:
import static java.lang.Math.*;
Once they have been imported, the static members can be used without qualification. For example, the previous code snippet would become:
double r = cos(PI * theta);
Obviously, you can write your own classes that contain constants and static methods that you use frequently, and then use the static import statement. For example,
import static mypackage.MyConstants.*;
Note: Use static import very sparingly. Overusing static import can result in code that is difficult to read and maintain, because readers of the code won't know which class defines a particular static object. Used properly, static import makes code more readable by removing class name repetition.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Naming a Package
Next page: Managing Source and Class Files


Managing Source and Class Files (The Java™ Tutorials > Learning the Java Language > Packages)

Trail: Learning the Java Language
Lesson: Packages
Section: Creating and Using Packages
Packages
Creating and Using Packages
Creating a Package
Naming a Package
Using Package Members
Managing Source and Class Files
Summary of Creating and Using Packages
Questions and Exercises
Home Page > Learning the Java Language > Packages
« Previous • Trail • Next »
Managing Source and Class Files
Many implementations of the Java platform rely on hierarchical file systems to manage source and class files, although The Java Language Specification does not require this. The strategy is as follows.

Put the source code for a class, interface, enumeration, or annotation type in a text file whose name is the simple name of the type and whose extension is .java. For example:

// in the Rectangle.java file
package graphics;
public class Rectangle() {
   . . .
}
Then, put the source file in a directory whose name reflects the name of the package to which the type belongs:
.....\graphics\Rectangle.java
The qualified name of the package member and the path name to the file are parallel, assuming the Microsoft Windows file name separator backslash (for Unix, use the forward slash).
class name | graphics.Rectangle
pathname to file | graphics\Rectangle.java

As you should recall, by convention a company uses its reversed Internet domain name for its package names. The Example company, whose Internet domain name is example.com, would precede all its package names with com.example. Each component of the package name corresponds to a subdirectory. So, if the Example company had a com.example.graphics package that contained a Rectangle.java source file, it would be contained in a series of subdirectories like this:

....\com\example\graphics\Rectangle.java

When you compile a source file, the compiler creates a different output file for each type defined in it. The base name of the output file is the name of the type, and its extension is .class. For example, if the source file is like this

// in the Rectangle.java file
package com.example.graphics;
public class Rectangle{
      . . .
}

class Helper{
      . . .
}
then the compiled files will be located at:
<path to the parent directory of the output files>\com\example\graphics\Rectangle.class
<path to the parent directory of the output files>\com\example\graphics\Helper.class

Like the .java source files, the compiled .class files should be in a series of directories that reflect the package name. However, the path to the .class files does not have to be the same as the path to the .java source files. You can arrange your source and class directories separately, as:

<path_one>\sources\com\example\graphics\Rectangle.java

<path_two>\classes\com\example\graphics\Rectangle.class
By doing this, you can give the classes directory to other programmers without revealing your sources. You also need to manage source and class files in this manner so that the compiler and the Java Virtual Machine (JVM) can find all the types your program uses.

The full path to the classes directory, <path_two>\classes, is called the class path, and is set with the CLASSPATH system variable. Both the compiler and the JVM construct the path to your .class files by adding the package name to the class path. For example, if

<path_two>\classes
is your class path, and the package name is
com.example.graphics,
then the compiler and JVM look for .class files in
<path_two>\classes\com\example\graphics.

A class path may include several paths, separated by a semicolon (Windows) or colon (Unix). By default, the compiler and the JVM search the current directory and the JAR file containing the Java platform classes so that these directories are automatically in your class path.

Setting the CLASSPATH System Variable

To display the current CLASSPATH variable, use these commands in Windows and Unix (Bourne shell):
In Windows:   C:\> set CLASSPATH
In Unix:      % echo $CLASSPATH
To delete the current contents of the CLASSPATH variable, use these commands:
In Windows:   C:\> set CLASSPATH=
In Unix:      % unset CLASSPATH; export CLASSPATH
To set the CLASSPATH variable, use these commands (for example):
In Windows:   C:\> set CLASSPATH=C:\users\george\java\classes
In Unix:      % CLASSPATH=/home/george/java/classes; export CLASSPATH
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Package Members
Next page: Summary of Creating and Using Packages


Summary of Creating and Using Packages (The Java™ Tutorials > Learning the Java Language > Packages)

Trail: Learning the Java Language
Lesson: Packages
Section: Creating and Using Packages
Packages
Creating and Using Packages
Creating a Package
Naming a Package
Using Package Members
Managing Source and Class Files
Summary of Creating and Using Packages
Questions and Exercises
Home Page > Learning the Java Language > Packages
« Previous • Trail • Next »
Summary of Creating and Using Packages
To create a package for a type, put a package statement as the first statement in the source file that contains the type (class, interface, enumeration, or annotation type).

To use a public type that's in a different package, you have three choices: (1) use the fully qualified name of the type, (2) import the type, or (3) import the entire package of which the type is a member.

The path names for a package's source and class files mirror the name of the package.

You might have to set your CLASSPATH so that the compiler and the JVM can find the .class files for your types.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Managing Source and Class Files
Next page: Questions and Exercises: Creating and Using Packages


Questions and Exercises: Creating and Using Packages (The Java™ Tutorials > Learning the Java Language > Packages)

Trail: Learning the Java Language
Lesson: Packages
Packages
Creating and Using Packages
Creating a Package
Naming a Package
Using Package Members
Managing Source and Class Files
Summary of Creating and Using Packages
Questions and Exercises
Home Page > Learning the Java Language > Packages
« Previous • Trail
Questions and Exercises: Creating and Using Packages

Questions

Assume you have written some classes. Belatedly, you decide they should be split into three packages, as listed in the following table. Furthermore, assume the classes are currently in the default package (they have no package statements).
Destination Packages

Package Name

Class Name

mygame.server

Server

mygame.shared

Utilities

mygame.client

Client

  1. Which line of code will you need to add to each source file to put each class in the right package?

  2. To adhere to the directory structure, you will need to create some subdirectories in the development directory and put source files in the correct subdirectories. What subdirectories must you create? Which subdirectory does each source file go in?

  3. Do you think you'll need to make any other changes to the source files to make them compile correctly? If so, what?

Exercises

Download the source files as listed here.
  • Client
  • Server
  • Utilities
  1. Implement the changes you proposed in questions 1 through 3 using the source files you just downloaded.

  2. Compile the revised source files. (Hint: If you're invoking the compiler from the command line (as opposed to using a builder), invoke the compiler from the directory that contains the mygame directory you just created.)

Check your answers.

« Previous • Trail
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary of Creating and Using Packages
Next page: Solving Common Coding Problems


Trail: Essential Classes (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Essential Classes
This trail discusses classes from the Java platform that are essential to most programmers.

Exceptions explains the exception mechanism and how it is used to handle errors and other exceptional conditions. This lesson describes what an exception is, how to throw and catch exceptions, what to do with an exception once it has been caught, and how to use the exception class hierarchy.

Basic I/O covers the Java platform classes used for basic input and output. It focuses primarily on I/O Streams, a powerful concept that greatly simplifies I/O operations. The lesson also looks at Serialization, which lets a program write whole objects out to streams and read them back again. Then the lesson looks at some file system operations, including random access files. Finally, it touchs briefly on the advanced features of the New I/O API.

Concurrency explains how to write applications that perform multiple tasks simultaneously. The Java platform is designed from the ground up to support concurrent programming, with basic concurrency support in the Java programming language and the Java class libraries. Since version 5.0, the Java platform has also included high-level concurrency APIs. This lesson introduces the platform's basic concurrency support and summarizes some of the high-level APIs in the java.util.concurrent packages.

Regular Expressions are a way to describe a set of strings based on common characteristics shared by each string in the set. They can be used to search, edit, or manipulate text and data. Regular expressions vary in complexity, but once you understand the basics of how they're constructed, you'll be able to decipher (or create) any regular expression. This lesson teaches the regular expression syntax supported by the java.util.regex API, and presents several working examples to illustrate how the various objects interact.

The Platform Environment is defined by the underlying operating system, the Java virtual machine, the class libraries, and various configuration data supplied when the application is launched. This lesson describes some of the APIs an application uses to examine and configure its platform environment.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Exceptions


Lesson: Exceptions (The Java™ Tutorials > Essential Classes)

Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Trail: Essential Classes
Home Page > Essential Classes
« Previous • Trail • Next »
Lesson: Exceptions
The Java programming language uses exceptions to handle errors and other exceptional events. This lesson describes when and how to use exceptions.

What Is an Exception?

An exception is an event that occurs during the execution of a program that disrupts the normal flow of instructions.

The Catch or Specify Requirement

This section covers how to catch and handle exceptions. The discussion includes the try, catch, and finally blocks, as well as chained exceptions and logging.

How to Throw Exceptions

This section covers the throw statement and the Throwable class and its subclasses.

Unchecked Exceptions — The Controversy

This section explains the correct and incorrect use of the unchecked exceptions indicated by subclasses of RuntimeException.

Advantages of Exceptions

The use of exceptions to manage errors has some advantages over traditional error-management techniques. You'll learn more in this section.

Summary

Questions and Exercises

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: What Is an Exception?


What Is an Exception? (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
What Is an Exception?
The term exception is shorthand for the phrase "exceptional event."
Definition: An exception is an event, which occurs during the execution of a program, that disrupts the normal flow of the program's instructions.

When an error occurs within a method, the method creates an object and hands it off to the runtime system. The object, called an exception object, contains information about the error, including its type and the state of the program when the error occurred. Creating an exception object and handing it to the runtime system is called throwing an exception.

After a method throws an exception, the runtime system attempts to find something to handle it. The set of possible "somethings" to handle the exception is the ordered list of methods that had been called to get to the method where the error occurred. The list of methods is known as the call stack (see the next figure).

The call stack showing three method calls, where the first method called has the exception handler.

The call stack.

The runtime system searches the call stack for a method that contains a block of code that can handle the exception. This block of code is called an exception handler. The search begins with the method in which the error occurred and proceeds through the call stack in the reverse order in which the methods were called. When an appropriate handler is found, the runtime system passes the exception to the handler. An exception handler is considered appropriate if the type of the exception object thrown matches the type that can be handled by the handler.

The exception handler chosen is said to catch the exception. If the runtime system exhaustively searches all the methods on the call stack without finding an appropriate exception handler, as shown in the next figure, the runtime system (and, consequently, the program) terminates.

The call stack showing three method calls, where the first method called has the exception handler.

Searching the call stack for the exception handler.

Using exceptions to manage errors has some advantages over traditional error-management techniques. You can learn more in the Advantages of Exceptions section.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Exceptions
Next page: The Catch or Specify Requirement


The Catch or Specify Requirement (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
The Catch or Specify Requirement
Valid Java programming language code must honor the Catch or Specify Requirement. This means that code that might throw certain exceptions must be enclosed by either of the following:
  • A try statement that catches the exception. The try must provide a handler for the exception, as described in Catching and Handling Exceptions.
  • A method that specifies that it can throw the exception. The method must provide a throws clause that lists the exception, as described in Specifying the Exceptions Thrown by a Method.
Code that fails to honor the Catch or Specify Requirement will not compile.

Not all exceptions are subject to the Catch or Specify Requirement. To understand why, we need to look at the three basic categories of exceptions, only one of which is subject to the Requirement.

The Three Kinds of Exceptions

The first kind of exception is the checked exception. These are exceptional conditions that a well-written application should anticipate and recover from. For example, suppose an application prompts a user for an input file name, then opens the file by passing the name to the constructor for java.io.FileReader. Normally, the user provides the name of an existing, readable file, so the construction of the FileReader object succeeds, and the execution of the application proceeds normally. But sometimes the user supplies the name of a nonexistent file, and the constructor throws java.io.FileNotFoundException. A well-written program will catch this exception and notify the user of the mistake, possibly prompting for a corrected file name.

Checked exceptions are subject to the Catch or Specify Requirement. All exceptions are checked exceptions, except for those indicated by Error, RuntimeException, and their subclasses.

The second kind of exception is the error. These are exceptional conditions that are external to the application, and that the application usually cannot anticipate or recover from. For example, suppose that an application successfully opens a file for input, but is unable to read the file because of a hardware or system malfunction. The unsuccessful read will throw java.io.IOError. An application might choose to catch this exception, in order to notify the user of the problem — but it also might make sense for the program to print a stack trace and exit.

Errors are not subject to the Catch or Specify Requirement. Errors are those exceptions indicated by Error and its subclasses.

The third kind of exception is the runtime exception. These are exceptional conditions that are internal to the application, and that the application usually cannot anticipate or recover from. These usually indicate programming bugs, such as logic errors or improper use of an API. For example, consider the application described previously that passes a file name to the constructor for FileReader. If a logic error causes a null to be passed to the constructor, the constructor will throw NullPointerException. The application can catch this exception, but it probably makes more sense to eliminate the bug that caused the exception to occur.

Runtime exceptions are not subject to the Catch or Specify Requirement. Runtime exceptions are those indicated by RuntimeException and its subclasses.

Errors and runtime exceptions are collectively known as unchecked exceptions.

Bypassing Catch or Specify

Some programmers consider the Catch or Specify Requirement a serious flaw in the exception mechanism and bypass it by using unchecked exceptions in place of checked exceptions. In general, this is not recommended. The section Unchecked Exceptions — The Controversy talks about when it is appropriate to use unchecked exceptions.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: What Is an Exception?
Next page: Catching and Handling Exceptions


Catching and Handling Exceptions (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
Catching and Handling Exceptions
This section describes how to use the three exception handler components — the try, catch, and finally blocks — to write an exception handler. The last part of this section walks through an example and analyzes what occurs during various scenarios.

The following example defines and implements a class named ListOfNumbers. When constructed, ListOfNumbers creates a Vector that contains 10 Integer elements with sequential values 0 through 9. The ListOfNumbers class also defines a method named writeList, which writes the list of numbers into a text file called OutFile.txt. This example uses output classes defined in java.io, which are covered in Basic I/O.

//Note: This class won't compile by design!
import java.io.*;
import java.util.Vector;

public class ListOfNumbers {

    private Vector vector;
    private static final int SIZE = 10;

    public ListOfNumbers () {
        vector = new Vector(SIZE);
        for (int i = 0; i < SIZE; i++) {
            vector.addElement(new Integer(i));
        }
    }

    public void writeList() {
        PrintWriter out = new PrintWriter(
                            new FileWriter("OutFile.txt"));

        for (int i = 0; i < SIZE; i++) {
            out.println("Value at: " + i + " = " +
                         vector.elementAt(i));
        }

        out.close();
    }
}
The first line in boldface is a call to a constructor. The constructor initializes an output stream on a file. If the file cannot be opened, the constructor throws an IOException. The second boldface line is a call to the Vector class's elementAt method, which throws an ArrayIndexOutOfBoundsException if the value of its argument is too small (less than 0) or too large (more than the number of elements currently contained by the Vector).

If you try to compile the ListOfNumbers class, the compiler prints an error message about the exception thrown by the FileWriter constructor. However, it does not display an error message about the exception thrown by elementAt. The reason is that the exception thrown by the constructor, IOException, is a checked exception, and the one thrown by the elementAt method, ArrayIndexOutOfBoundsException, is an unchecked exception.

Now that you're familiar with the ListOfNumbers class and where the exceptions can be thrown within it, you're ready to write exception handlers to catch and handle those exceptions.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Catch or Specify Requirement
Next page: The try Block


The try Block (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Section: Catching and Handling Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
The try Block
The first step in constructing an exception handler is to enclose the code that might throw an exception within a try block. In general, a try block looks like the following.
try {
    code
}
catch and finally blocks . . .
The segment in the example labeled code contains one or more legal lines of code that could throw an exception. (The catch and finally blocks are explained in the next two subsections.)

To construct an exception handler for the writeList method from the ListOfNumbers class, enclose the exception-throwing statements of the writeList method within a try block. There is more than one way to do this. You can put each line of code that might throw an exception within its own try block and provide separate exception handlers for each. Or, you can put all the writeList code within a single try block and associate multiple handlers with it. The following listing uses one try block for the entire method because the code in question is very short.

private Vector vector;
private static final int SIZE = 10;

PrintWriter out = null;

try {
    System.out.println("Entered try statement");
    out = new PrintWriter(new FileWriter("OutFile.txt"));
    for (int i = 0; i < SIZE; i++) {
        out.println("Value at: " + i + " = "
                     + vector.elementAt(i));
    }
}
catch and finally statements . . .
If an exception occurs within the try block, that exception is handled by an exception handler associated with it. To associate an exception handler with a try block, you must put a catch block after it; the next section shows you how.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Catching and Handling Exceptions
Next page: The catch Blocks


The catch Blocks (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Section: Catching and Handling Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
The catch Blocks
You associate exception handlers with a try block by providing one or more catch blocks directly after the try block. No code can be between the end of the try block and the beginning of the first catch block.
try {

} catch (ExceptionType name) {

} catch (ExceptionType name) {

}
Each catch block is an exception handler and handles the type of exception indicated by its argument. The argument type, ExceptionType, declares the type of exception that the handler can handle and must be the name of a class that inherits from the Throwable class. The handler can refer to the exception with name.

The catch block contains code that is executed if and when the exception handler is invoked. The runtime system invokes the exception handler when the handler is the first one in the call stack whose ExceptionType matches the type of the exception thrown. The system considers it a match if the thrown object can legally be assigned to the exception handler's argument.

The following are two exception handlers for the writeList method — one for two types of checked exceptions that can be thrown within the try statement.

try {

} catch (FileNotFoundException e) {
    System.err.println("FileNotFoundException: "
                        + e.getMessage());
    throw new SampleException(e);

} catch (IOException e) {
    System.err.println("Caught IOException: "
                        + e.getMessage());
}
Both handlers print an error message. The second handler does nothing else. By catching any IOException that's not caught by the first handler, it allows the program to continue executing.

The first handler, in addition to printing a message, throws a user-defined exception. (Throwing exceptions is covered in detail later in this chapter in the How to Throw Exceptions section.) In this example, when the FileNotFoundException is caught it causes a user-defined exception called SampleException to be thrown. You might want to do this if you want your program to handle an exception in this situation in a specific way.

Exception handlers can do more than just print error messages or halt the program. They can do error recovery, prompt the user to make a decision, or propagate the error up to a higher-level handler using chained exceptions, as described in the Chained Exceptions section.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The try Block
Next page: The finally Block


The finally Block (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Section: Catching and Handling Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
The finally Block
The finally block always executes when the try block exits. This ensures that the finally block is executed even if an unexpected exception occurs. But finally is useful for more than just exception handling — it allows the programmer to avoid having cleanup code accidentally bypassed by a return, continue, or break. Putting cleanup code in a finally block is always a good practice, even when no exceptions are anticipated.

The try block of the writeList method that you've been working with here opens a PrintWriter. The program should close that stream before exiting the writeList method. This poses a somewhat complicated problem because writeList's try block can exit in one of three ways.

  1. The new FileWriter statement fails and throws an IOException.
  2. The vector.elementAt(i) statement fails and throws an ArrayIndexOutOfBoundsException.
  3. Everything succeeds and the try block exits normally.
The runtime system always executes the statements within the finally block regardless of what happens within the try block. So it's the perfect place to perform cleanup.

The following finally block for the writeList method cleans up and then closes the PrintWriter.

finally {
    if (out != null) {
        System.out.println("Closing PrintWriter");
        out.close();
    } else {
        System.out.println("PrintWriter not open");
    }
}
In the writeList example, you could provide for cleanup without the intervention of a finally block. For example, you could put the code to close the PrintWriter at the end of the try block and again within the exception handler for ArrayIndexOutOfBoundsException, as follows.
try {

    out.close();       //Don't do this; it duplicates code.

} catch (FileNotFoundException e) {
    out.close();       //Don't do this; it duplicates code.
    System.err.println("Caught: FileNotFoundException: "
                      + e.getMessage());
    throw new RuntimeException(e);

} catch (IOException e) {
    System.err.println("Caught IOException: "
                      + e.getMessage());
}
However, this duplicates code, thus making the code difficult to read and error-prone should you modify it later. For example, if you add code that can throw a new type of exception to the try block, you have to remember to close the PrintWriter within the new exception handler.
Important: The finally block is a key tool for preventing resource leaks. When closing a file or otherwise recovering resources, place the code in a finally block to insure that resource is always recovered.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The catch Blocks
Next page: Putting It All Together


Putting It All Together (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Section: Catching and Handling Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
Putting It All Together
The previous sections described how to construct the try, catch, and finally code blocks for the writeList method in the ListOfNumbers class. Now, let's walk through the code and investigate what can happen.

When all the components are put together, the writeList method looks like the following.

public void writeList() {
    PrintWriter out = null;

    try {
        System.out.println("Entering try statement");
        out = new PrintWriter(
                      new FileWriter("OutFile.txt"));
            for (int i = 0; i < SIZE; i++)
                out.println("Value at: " + i + " = "
                             + vector.elementAt(i));

    } catch (ArrayIndexOutOfBoundsException e) {
         System.err.println("Caught "
                     + "ArrayIndexOutOfBoundsException: "
                     +   e.getMessage());

    } catch (IOException e) {
         System.err.println("Caught IOException: "
                             +  e.getMessage());

    } finally {
         if (out != null) {
             System.out.println("Closing PrintWriter");
             out.close();

         }
         else {
             System.out.println("PrintWriter not open");
         }
     }
}
As mentioned previously, this method's try block has three different exit possibilities; here are two of them.
  1. Code in the try statement fails and throws an exception. This could be an IOException caused by the new FileWriter statement or an ArrayIndexOutOfBoundsException caused by a wrong index value in the for loop.
  2. Everything succeeds and the try statement exits normally.
Let's look at what happens in the writeList method during these two exit possibilities.

Scenario 1: An Exception Occurs

The statement that creates a FileWriter can fail for a number of reasons. For example, the constructor for the FileWriter throws an IOException if the program cannot create or write to the file indicated.

When FileWriter throws an IOException, the runtime system immediately stops executing the try block; method calls being executed are not completed. The runtime system then starts searching at the top of the method call stack for an appropriate exception handler. In this example, when the IOException occurs, the FileWriter constructor is at the top of the call stack. However, the FileWriter constructor doesn't have an appropriate exception handler, so the runtime system checks the next method — the writeList method — in the method call stack. The writeList method has two exception handlers: one for IOException and one for ArrayIndexOutOfBoundsException.

The runtime system checks writeList's handlers in the order in which they appear after the try statement. The argument to the first exception handler is ArrayIndexOutOfBoundsException. This does not match the type of exception thrown, so the runtime system checks the next exception handler — IOException. This matches the type of exception that was thrown, so the runtime system ends its search for an appropriate exception handler. Now that the runtime has found an appropriate handler, the code in that catch block is executed.

After the exception handler executes, the runtime system passes control to the finally block. Code in the finally block executes regardless of the exception caught above it. In this scenario, the FileWriter was never opened and doesn't need to be closed. After the finally block finishes executing, the program continues with the first statement after the finally block.

Here's the complete output from the ListOfNumbers program that appears when an IOException is thrown.

Entering try statement
Caught IOException: OutFile.txt
PrintWriter not open
The boldface code in the following listing shows the statements that get executed during this scenario:
public void writeList() {
   PrintWriter out = null;

    try {
        System.out.println("Entering try statement");
        out = new PrintWriter(
                   new FileWriter("OutFile.txt"));
        for (int i = 0; i < SIZE; i++)
            out.println("Value at: " + i
                + " = " + vector.elementAt(i));

    } catch (ArrayIndexOutOfBoundsException e) {
          System.err.println("Caught "
                    + "ArrayIndexOutOfBoundsException: "
                    + e.getMessage());

    } catch (IOException e) {
            System.err.println("Caught IOException: "
                                +  e.getMessage());

    } finally {
        if (out != null) {
            System.out.println("Closing PrintWriter");
            out.close();
        }
     else {
            System.out.println("PrintWriter not open");
        }
    }
}

Scenario 2: The try Block Exits Normally

In this scenario, all the statements within the scope of the try block execute successfully and throw no exceptions. Execution falls off the end of the try block, and the runtime system passes control to the finally block. Because everything was successful, the PrintWriter is open when control reaches the finally block, which closes the PrintWriter. Again, after the finally block finishes executing, the program continues with the first statement after the finally block.

Here is the output from the ListOfNumbers program when no exceptions are thrown.

Entering try statement
Closing PrintWriter
The boldface code in the following sample shows the statements that get executed during this scenario.
public void writeList() {
    PrintWriter out = null;
    try {
        System.out.println("Entering try statement");
        out = new PrintWriter(
                  new FileWriter("OutFile.txt"));
        for (int i = 0; i < SIZE; i++)
            out.println("Value at: " + i + " = "
                         +  vector.elementAt(i));

    } catch (ArrayIndexOutOfBoundsException e) {
         System.err.println("Caught "
                     + "ArrayIndexOutOfBoundsException: "
                     + e.getMessage());

    } catch (IOException e) {
         System.err.println("Caught IOException: "
                            + e.getMessage());

    } finally {
         if (out != null) {
             System.out.println("Closing PrintWriter");
             out.close();
          }
          else {
             System.out.println("PrintWriter not open");
          }
    }
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The finally Block
Next page: Specifying the Exceptions Thrown by a Method


Specifying the Exceptions Thrown by a Method (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
Specifying the Exceptions Thrown by a Method
The previous section showed how to write an exception handler for the writeList method in the ListOfNumbers class. Sometimes, it's appropriate for code to catch exceptions that can occur within it. In other cases, however, it's better to let a method further up the call stack handle the exception. For example, if you were providing the ListOfNumbers class as part of a package of classes, you probably couldn't anticipate the needs of all the users of your package. In this case, it's better to not catch the exception and to allow a method further up the call stack to handle it.

If the writeList method doesn't catch the checked exceptions that can occur within it, the writeList method must specify that it can throw these exceptions. Let's modify the original writeList method to specify the exceptions it can throw instead of catching them. To remind you, here's the original version of the writeList method that won't compile.

// Note: This method won't compile by design!
public void writeList() {
    PrintWriter out =
               new PrintWriter(new FileWriter("OutFile.txt"));
    for (int i = 0; i < SIZE; i++) {
        out.println("Value at: " + i + " = "
                     + vector.elementAt(i));
    }
    out.close();
}
To specify that writeList can throw two exceptions, add a throws clause to the method declaration for the writeList method. The throws clause comprises the throws keyword followed by a comma-separated list of all the exceptions thrown by that method. The clause goes after the method name and argument list and before the brace that defines the scope of the method; here's an example.
public void writeList() throws IOException,
                               ArrayIndexOutOfBoundsException {
Remember that ArrayIndexOutOfBoundsException is an unchecked exception; including it in the throws clause is not mandatory. You could just write the following.
public void writeList() throws IOException {
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Putting It All Together
Next page: How to Throw Exceptions


How to Throw Exceptions (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
How to Throw Exceptions
Before you can catch an exception, some code somewhere must throw one. Any code can throw an exception: your code, code from a package written by someone else such as the packages that come with the Java platform, or the Java runtime environment. Regardless of what throws the exception, it's always thrown with the throw statement.

As you have probably noticed, the Java platform provides numerous exception classes. All the classes are descendants of the Throwable class, and all allow programs to differentiate among the various types of exceptions that can occur during the execution of a program.

You can also create your own exception classes to represent problems that can occur within the classes you write. In fact, if you are a package developer, you might have to create your own set of exception classes to allow users to differentiate an error that can occur in your package from errors that occur in the Java platform or other packages.

You can also create chained exceptions. For more information, see the Chained Exceptions section.

The throw Statement

All methods use the throw statement to throw an exception. The throw statement requires a single argument: a throwable object. Throwable objects are instances of any subclass of the Throwable class. Here's an example of a throw statement.
throw someThrowableObject;
Let's look at the throw statement in context. The following pop method is taken from a class that implements a common stack object. The method removes the top element from the stack and returns the object.
public Object pop() {
    Object obj;

    if (size == 0) {
        throw new EmptyStackException();
    }

    obj = objectAt(size - 1);
    setObjectAt(size - 1, null);
    size--;
    return obj;
}
The pop method checks to see whether any elements are on the stack. If the stack is empty (its size is equal to 0), pop instantiates a new EmptyStackException object (a member of java.util) and throws it. The Creating Exception Classes section in this chapter explains how to create your own exception classes. For now, all you need to remember is that you can throw only objects that inherit from the java.lang.Throwable class.

Note that the declaration of the pop method does not contain a throws clause. EmptyStackException is a not a checked exception, so pop is not required to state that it might occur.

Throwable Class and Its Subclasses

The objects that inherit from the Throwable class include direct descendants (objects that inherit directly from the Throwable class) and indirect descendants (objects that inherit from children or grandchildren of the Throwable class). The figure below illustrates the class hierarchy of the Throwable class and its most significant subclasses. As you can see, Throwable has two direct descendants: Error and Exception.

The Throwable class and its most significant subclasses.

The Throwable class.

Error Class

When a dynamic linking failure or other hard failure in the Java virtual machine occurs, the virtual machine throws an Error. Simple programs typically do not catch or throw Errors.

Exception Class

Most programs throw and catch objects that derive from the Exception class. An Exception indicates that a problem occurred, but it is not a serious system problem. Most programs you write will throw and catch Exceptions as opposed to Errors.

The Java platform defines the many descendants of the Exception class. These descendants indicate various types of exceptions that can occur. For example, IllegalAccessException signals that a particular method could not be found, and NegativeArraySizeException indicates that a program attempted to create an array with a negative size.

One Exception subclass, RuntimeException, is reserved for exceptions that indicate incorrect use of an API. An example of a runtime exception is NullPointerException, which occurs when a method tries to access a member of an object through a null reference. The section Unchecked Exceptions — The Controversy discusses why most applications shouldn't throw runtime exceptions or subclass RuntimeException.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Specifying the Exceptions Thrown by a Method
Next page: Chained Exceptions


Chained Exceptions (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Section: How to Throw Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
Chained Exceptions
An application often responds to an exception by throwing another exception. In effect, the first exception causes the second exception. It can be very helpful to know when one exception causes another. Chained Exceptions help the programmer do this.

The following are the methods and constructors in Throwable that support chained exceptions.

Throwable getCause()
Throwable initCause(Throwable)
Throwable(String, Throwable)
Throwable(Throwable)
The Throwable argument to initCause and the Throwable constructors is the exception that caused the current exception. getCause returns the exception that caused the current exception, and initCause returns the current exception.

The following example shows how to use a chained exception.

try {

} catch (IOException e) {
    throw new SampleException("Other IOException", e);
}
In this example, when an IOException is caught, a new SampleException exception is created with the original cause attached and the chain of exceptions is thrown up to the next higher level exception handler.

Accessing Stack Trace Information

Now let's suppose that the higher-level exception handler wants to dump the stack trace in its own format.
Definition: A stack trace provides information on the execution history of the current thread and lists the names of the classes and methods that were called at the point when the exception occurred. A stack trace is a useful debugging tool that you'll normally take advantage of when an exception has been thrown.
The following code shows how to call the getStackTrace method on the exception object.
catch (Exception cause) {
    StackTraceElement elements[] = cause.getStackTrace();
    for (int i = 0, n = elements.length; i < n; i++) {
        System.err.println(elements[i].getFileName() + ":"
                      + elements[i].getLineNumber()
                      + ">> "
                      + elements[i].getMethodName() + "()");
    }
}

Logging API

The next code snippet logs where an exception occurred from within the catch block. However, rather than manually parsing the stack trace and sending the output to System.err(), it sends the output to a file using the logging facility in the java.util.logging package.
try {
    Handler handler = new FileHandler("OutFile.log");
    Logger.getLogger("").addHandler(handler);

} catch (IOException e) {
    Logger logger = Logger.getLogger("package.name");
    StackTraceElement elements[] = e.getStackTrace();
    for (int i = 0, n = elements.length; i < n; i++) {
        logger.log(Level.WARNING,
                   elements[i].getMethodName());
    }
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Throw Exceptions
Next page: Creating Exception Classes


Creating Exception Classes (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Section: How to Throw Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
Creating Exception Classes
When faced with choosing the type of exception to throw, you can either use one written by someone else — the Java platform provides a lot of exception classes you can use — or you can write one of your own. You should write your own exception classes if you answer yes to any of the following questions; otherwise, you can probably use someone else's.
  • Do you need an exception type that isn't represented by those in the Java platform?
  • Would it help users if they could differentiate your exceptions from those thrown by classes written by other vendors?
  • Does your code throw more than one related exception?
  • If you use someone else's exceptions, will users have access to those exceptions? A similar question is, should your package be independent and self-contained?

An Example

Suppose you are writing a linked list class. The class supports the following methods, among others:
  • objectAt(int n) — Returns the object in the nth position in the list. Throws an exception if the argument is less than 0 or more than the number of objects currently in the list.
  • firstObject() — Returns the first object in the list. Throws an exception if the list contains no objects.
  • indexOf(Object o) — Searches the list for the specified Object and returns its position in the list. Throws an exception if the object passed into the method is not in the list.
The linked list class can throw multiple exceptions, and it would be convenient to be able to catch all exceptions thrown by the linked list with one exception handler. Also, if you plan to distribute your linked list in a package, all related code should be packaged together. Thus, the linked list should provide its own set of exception classes.

The next figure illustrates one possible class hierarchy for the exceptions thrown by the linked list.

A possible class hierarchy for the exceptions thrown by a linked list.

Example exception class hierarchy.

Choosing a Superclass

Any Exception subclass can be used as the parent class of LinkedListException. However, a quick perusal of those subclasses shows that they are inappropriate because they are either too specialized or completely unrelated to LinkedListException. Therefore, the parent class of LinkedListException should be Exception.

Most applets and applications you write will throw objects that are Exceptions. Errors are normally used for serious, hard errors in the system, such as those that prevent the JVM from running.

Note: For readable code, it's good practice to append the string Exception to the names of all classes that inherit (directly or indirectly) from the Exception class.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Chained Exceptions
Next page: Unchecked Exceptions — The Controversy


Unchecked Exceptions — The Controversy (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
Unchecked Exceptions — The Controversy

Because the Java programming language does not require methods to catch or to specify unchecked exceptions (RuntimeException, Error, and their subclasses), programmers may be tempted to write code that throws only unchecked exceptions or to make all their exception subclasses inherit from RuntimeException. Both of these shortcuts allow programmers to write code without bothering with compiler errors and without bothering to specify or to catch any exceptions. Although this may seem convenient to the programmer, it sidesteps the intent of the catch or specify requirement and can cause problems for others using your classes.

Why did the designers decide to force a method to specify all uncaught checked exceptions that can be thrown within its scope? Any Exception that can be thrown by a method is part of the method's public programming interface. Those who call a method must know about the exceptions that a method can throw so that they can decide what to do about them. These exceptions are as much a part of that method's programming interface as its parameters and return value.

The next question might be: "If it's so good to document a method's API, including the exceptions it can throw, why not specify runtime exceptions too?" Runtime exceptions represent problems that are the result of a programming problem, and as such, the API client code cannot reasonably be expected to recover from them or to handle them in any way. Such problems include arithmetic exceptions, such as dividing by zero; pointer exceptions, such as trying to access an object through a null reference; and indexing exceptions, such as attempting to access an array element through an index that is too large or too small.

Runtime exceptions can occur anywhere in a program, and in a typical one they can be very numerous. Having to add runtime exceptions in every method declaration would reduce a program's clarity. Thus, the compiler does not require that you catch or specify runtime exceptions (although you can).

One case where it is common practice to throw a RuntimeException is when the user calls a method incorrectly. For example, a method can check if one of its arguments is incorrectly null. If an argument is null, the method might throw a NullPointerException, which is an unchecked exception.

Generally speaking, do not throw a RuntimeException or create a subclass of RuntimeException simply because you don't want to be bothered with specifying the exceptions your methods can throw.

Here's the bottom line guideline: If a client can reasonably be expected to recover from an exception, make it a checked exception. If a client cannot do anything to recover from the exception, make it an unchecked exception.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating Exception Classes
Next page: Advantages of Exceptions


Advantages of Exceptions (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
Advantages of Exceptions
Now that you know what exceptions are and how to use them, it's time to learn the advantages of using exceptions in your programs.

Advantage 1: Separating Error-Handling Code from "Regular" Code

Exceptions provide the means to separate the details of what to do when something out of the ordinary happens from the main logic of a program. In traditional programming, error detection, reporting, and handling often lead to confusing spaghetti code. For example, consider the pseudocode method here that reads an entire file into memory.
readFile {
    open the file;
    determine its size;
    allocate that much memory;
    read the file into memory;
    close the file;
}
At first glance, this function seems simple enough, but it ignores all the following potential errors.
  • What happens if the file can't be opened?
  • What happens if the length of the file can't be determined?
  • What happens if enough memory can't be allocated?
  • What happens if the read fails?
  • What happens if the file can't be closed?
To handle such cases, the readFile function must have more code to do error detection, reporting, and handling. Here is an example of what the function might look like.
errorCodeType readFile {
    initialize errorCode = 0;

    open the file;
    if (theFileIsOpen) {
        determine the length of the file;
        if (gotTheFileLength) {
            allocate that much memory;
            if (gotEnoughMemory) {
                read the file into memory;
                if (readFailed) {
                    errorCode = -1;
                }
            } else {
                errorCode = -2;
            }
        } else {
            errorCode = -3;
        }
        close the file;
        if (theFileDidntClose && errorCode == 0) {
            errorCode = -4;
        } else {
            errorCode = errorCode and -4;
        }
    } else {
        errorCode = -5;
    }
    return errorCode;
}
There's so much error detection, reporting, and returning here that the original seven lines of code are lost in the clutter. Worse yet, the logical flow of the code has also been lost, thus making it difficult to tell whether the code is doing the right thing: Is the file really being closed if the function fails to allocate enough memory? It's even more difficult to ensure that the code continues to do the right thing when you modify the method three months after writing it. Many programmers solve this problem by simply ignoring it — errors are reported when their programs crash.

Exceptions enable you to write the main flow of your code and to deal with the exceptional cases elsewhere. If the readFile function used exceptions instead of traditional error-management techniques, it would look more like the following.

readFile {
    try {
        open the file;
        determine its size;
        allocate that much memory;
        read the file into memory;
        close the file;
    } catch (fileOpenFailed) {
       doSomething;
    } catch (sizeDeterminationFailed) {
        doSomething;
    } catch (memoryAllocationFailed) {
        doSomething;
    } catch (readFailed) {
        doSomething;
    } catch (fileCloseFailed) {
        doSomething;
    }
}
Note that exceptions don't spare you the effort of doing the work of detecting, reporting, and handling errors, but they do help you organize the work more effectively.

Advantage 2: Propagating Errors Up the Call Stack

A second advantage of exceptions is the ability to propagate error reporting up the call stack of methods. Suppose that the readFile method is the fourth method in a series of nested method calls made by the main program: method1 calls method2, which calls method3, which finally calls readFile.
method1 {
    call method2;
}

method2 {
    call method3;
}

method3 {
    call readFile;
}
Suppose also that method1 is the only method interested in the errors that might occur within readFile. Traditional error-notification techniques force method2 and method3 to propagate the error codes returned by readFile up the call stack until the error codes finally reach method1—the only method that is interested in them.
method1 {
    errorCodeType error;
    error = call method2;
    if (error)
        doErrorProcessing;
    else
        proceed;
}

errorCodeType method2 {
    errorCodeType error;
    error = call method3;
    if (error)
        return error;
    else
        proceed;
}

errorCodeType method3 {
    errorCodeType error;
    error = call readFile;
    if (error)
        return error;
    else
        proceed;
}
Recall that the Java runtime environment searches backward through the call stack to find any methods that are interested in handling a particular exception. A method can duck any exceptions thrown within it, thereby allowing a method farther up the call stack to catch it. Hence, only the methods that care about errors have to worry about detecting errors.
method1 {
    try {
        call method2;
    } catch (exception e) {
        doErrorProcessing;
    }
}

method2 throws exception {
    call method3;
}

method3 throws exception {
    call readFile;
}
However, as the pseudocode shows, ducking an exception requires some effort on the part of the middleman methods. Any checked exceptions that can be thrown within a method must be specified in its throws clause.

Advantage 3: Grouping and Differentiating Error Types

Because all exceptions thrown within a program are objects, the grouping or categorizing of exceptions is a natural outcome of the class hierarchy. An example of a group of related exception classes in the Java platform are those defined in java.io — IOException and its descendants. IOException is the most general and represents any type of error that can occur when performing I/O. Its descendants represent more specific errors. For example, FileNotFoundException means that a file could not be located on disk.

A method can write specific handlers that can handle a very specific exception. The FileNotFoundException class has no descendants, so the following handler can handle only one type of exception.

catch (FileNotFoundException e) {
    ...
}
A method can catch an exception based on its group or general type by specifying any of the exception's superclasses in the catch statement. For example, to catch all I/O exceptions, regardless of their specific type, an exception handler specifies an IOException argument.
catch (IOException e) {
    ...
}
This handler will be able to catch all I/O exceptions, including FileNotFoundException, EOFException, and so on. You can find details about what occurred by querying the argument passed to the exception handler. For example, use the following to print the stack trace.
catch (IOException e) {
    e.printStackTrace();  //Output goes to System.err.
    e.printStackTrace(System.out);  //Send trace to stdout.
}
You could even set up an exception handler that handles any Exception with the handler here.
catch (Exception e) {    //A (too) general exception handler
    ...
}
The Exception class is close to the top of the Throwable class hierarchy. Therefore, this handler will catch many other exceptions in addition to those that the handler is intended to catch. You may want to handle exceptions this way if all you want your program to do, for example, is print out an error message for the user and then exit.

In most situations, however, you want exception handlers to be as specific as possible. The reason is that the first thing a handler must do is determine what type of exception occurred before it can decide on the best recovery strategy. In effect, by not catching specific errors, the handler must accommodate any possibility. Exception handlers that are too general can make code more error-prone by catching and handling exceptions that weren't anticipated by the programmer and for which the handler was not intended.

As noted, you can create groups of exceptions and handle exceptions in a general fashion, or you can use the specific exception type to differentiate exceptions and handle exceptions in an exact fashion.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Unchecked Exceptions — The Controversy
Next page: Summary


Summary (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
Summary
A program can use exceptions to indicate that an error occurred. To throw an exception, use the throw statement and provide it with an exception object — a descendant of Throwable — to provide information about the specific error that occurred. A method that throws an uncaught, checked exception must include a throws clause in its declaration.

A program can catch exceptions by using a combination of the try, catch, and finally blocks.

  • The try block identifies a block of code in which an exception can occur.
  • The catch block identifies a block of code, known as an exception handler, that can handle a particular type of exception.
  • The finally block identifies a block of code that is guaranteed to execute, and is the right place to close files, recover resources, and otherwise clean up after the code enclosed in the try block.
The try statement should contain at least one catch block or a finally block and may have multiple catch blocks.

The class of the exception object indicates the type of exception thrown. The exception object can contain further information about the error, including an error message. With exception chaining, an exception can point to the exception that caused it, which can in turn point to the exception that caused it, and so on.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Advantages of Exceptions
Next page: Questions and Exercises


Questions and Exercises (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Home Page > Essential Classes > Exceptions
« Previous • Trail • Next »
Questions and Exercises

Questions

  1. Is the following code legal?
    try {

} finally {

}
  2. What exception types can be caught by the following handler?
    catch (Exception e) {

}
    What is wrong with using this type of exception handler?

  3. Is there anything wrong with the following exception handler as written? Will this code compile?
    try {

} catch (Exception e) {

} catch (ArithmeticException a) {

}

  4. Match each situation in the first list with an item in the second list.
    1. int[] A;
      A[0] = 0;
    2. The JVM starts running your program, but the JVM can't find the Java platform classes. (The Java platform classes reside in classes.zip or rt.jar.)
    3. A program is reading a stream and reaches the end of stream marker.
    4. Before closing the stream and after reaching the end of stream marker, a program tries to read the stream again.

    1. __error
    2. __checked exception
    3. __compile error
    4. __no exception

Exercises

  1. Add a readList method to ListOfNumbers.java. This method should read in int values from a file, print each value, and append them to the end of the vector. You should catch all appropriate errors. You will also need a text file containing numbers to read in.

  2. Modify the following cat method so that it will compile.
    public static void cat(File file) {
    RandomAccessFile input = null;
    String line = null;

    try {
        input = new RandomAccessFile(file, "r");
        while ((line = input.readLine()) != null) {
            System.out.println(line);
        }
        return;
    } finally {
        if (input != null) {
            input.close();
        }
    }
}
Check your answers.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary
Next page: Basic I/O


Lesson: Basic I/O (The Java™ Tutorials > Essential Classes)

Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Trail: Essential Classes
Home Page > Essential Classes
« Previous • Trail • Next »
Lesson: Basic I/O
This lesson covers the Java platform classes used for basic I/O. It focuses primarily on I/O Streams, a powerful concept that greatly simplifies I/O operations. The lesson also looks at serialization, which lets a program write whole objects out to streams and read them back again. Then the lesson looks at some file system operations, including random access files. Finally, it touches briefly on the advanced features of the New I/O API. Most of the classes covered are in the java.io package.

I/O Streams

  • Byte Streams handle I/O of raw binary data.
  • Character Streams handle I/O of character data, automatically handling translation to and from the local character set.
  • Buffered Streams optimize input and output by reducing the number of calls to the native API.
  • Scanning and Formatting allows a program to read and write formatted text.
  • I/O from the Command Line describes the Standard Streams and the Console object.
  • Data Streams handle binary I/O of primitive data type and String values.
  • Object Streams handle binary I/O of objects.

File I/O

  • File Objects help you to write platform-independent code that examines and manipulates files.
  • Random Access Files handle non-sequential file access.

An Overview of the New IO

This section talks about the advanced I/O packages added to version 1.4 of the Java Platform.

Summary

A summary of the key points covered in this trail.

Questions and Exercises

Test what you've learned in this trail by trying these questions and exercises.

The I/O Classes in Action

Many of the examples in the next trail, Custom Networking use the I/O streams described in this lesson to read from and write to network connections.

Security consideration: Some I/O operations are subject to approval by the current security manager. The example programs contained in these lessons are standalone applications, which by default have no security manager. To work in an applet, most of these examples would have to be modified. See Security Restrictions for information about the security restrictions placed on applets.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: I/O Streams


I/O Streams (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
I/O Streams
An I/O Stream represents an input source or an output destination. A stream can represent many different kinds of sources and destinations, including disk files, devices, other programs, and memory arrays.

Streams support many different kinds of data, including simple bytes, primitive data types, localized characters, and objects. Some streams simply pass on data; others manipulate and transform the data in useful ways.

No matter how they work internally, all streams present the same simple model to programs that use them: A stream is a sequence of data. A program uses an input stream to read data from a source, one item at a time:

Reading information into a program.

Reading information into a program.

A program uses an output stream to write data to a destination, one item at time:

Writing information from a program.

Writing information from a program.

In this lesson, we'll see streams that can handle all kinds of data, from primitive values to advanced objects.

The data source and data destination pictured above can be anything that holds, generates, or consumes data. Obviously this includes disk files, but a source or destination can also be another program, a peripheral device, a network socket, or an array.

In the next section, we'll use the most basic kind of streams, byte streams, to demonstrate the common operations of Stream I/O. For sample input, we'll use the example file xanadu.txt, which contains the following verse:

In Xanadu did Kubla Khan
A stately pleasure-dome decree:
Where Alph, the sacred river, ran
Through caverns measureless to man
Down to a sunless sea.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Basic I/O
Next page: Byte Streams


Byte Streams (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Section: I/O Streams
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
Byte Streams
Programs use byte streams to perform input and output of 8-bit bytes. All byte stream classes are descended from InputStream and OutputStream.

There are many byte stream classes. To demonstrate how byte streams work, we'll focus on the file I/O byte streams, FileInputStream and FileOutputStream. Other kinds of byte streams are used in much the same way; they differ mainly in the way they are constructed.

Using Byte Streams

We'll explore FileInputStream and FileOutputStream by examining an example program named CopyBytes, which uses byte streams to copy xanadu.txt, one byte at a time.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class CopyBytes {
    public static void main(String[] args) throws IOException {
        FileInputStream in = null;
        FileOutputStream out = null;
        try {
            in = new FileInputStream("xanadu.txt");
            out = new FileOutputStream("outagain.txt");
            int c;

            while ((c = in.read()) != -1) {
                out.write(c);
            }

        } finally {
            if (in != null) {
                in.close();
            }
            if (out != null) {
                out.close();
            }
        }
    }
}
CopyBytes spends most of its time in a simple loop that reads the input stream and writes the output stream, one byte at a time, as shown in the following figure.

Simple byte stream input and output.

Simple byte stream input and output.

Notice that read() returns an int value. If the input is a stream of bytes, why doesn't read() return a byte value? Using a int as a return type allows read() to use -1 to indicate that it has reached the end of the stream.

Always Close Streams

Closing a stream when it's no longer needed is very important — so important that CopyBytes uses a finally block to guarantee that both streams will be closed even if an error occurs. This practice helps avoid serious resource leaks.

One possible error is that CopyBytes was unable to open one or both files. When that happens, the stream variable corresponding to the file never changes from its initial null value. That's why CopyBytes makes sure that each stream variable contains an object reference before invoking close.

When Not to Use Byte Streams

CopyBytes seems like a normal program, but it actually represents a kind of low-level I/O that you should avoid. Since xanadu.txt contains character data, the best approach is to use character streams, as discussed in the next section. There are also streams for more complicated data types. Byte streams should only be used for the most primitive I/O.

So why talk about byte streams? Because all other stream types are built on byte streams.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: I/O Streams
Next page: Character Streams


Character Streams (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Section: I/O Streams
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
Character Streams
The Java platform stores character values using Unicode conventions. Character stream I/O automatically translates this internal format to and from the local character set. In Western locales, the local character set is usually an 8-bit superset of ASCII.

For most applications, I/O with character streams is no more complicated than I/O with byte streams. Input and output done with stream classes automatically translates to and from the local character set. A program that uses character streams in place of byte streams automatically adapts to the local character set and is ready for internationalization — all without extra effort by the programmer.

If internationalization isn't a priority, you can simply use the character stream classes without paying much attention to character set issues. Later, if internationalization becomes a priority, your program can be adapted without extensive recoding. See the Internationalization trail for more information.

Using Character Streams

All character stream classes are descended from Reader and Writer. As with byte streams, there are character stream classes that specialize in file I/O: FileReader and FileWriter. The CopyCharacters example illustrates these classes.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

public class CopyCharacters {
    public static void main(String[] args) throws IOException {
        FileReader inputStream = null;
        FileWriter outputStream = null;

        try {
            inputStream = new FileReader("xanadu.txt");
            outputStream = new FileWriter("characteroutput.txt");

            int c;
            while ((c = inputStream.read()) != -1) {
                outputStream.write(c);
            }
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
        }
    }
}
CopyCharacters is very similar to CopyBytes. The most important difference is that CopyCharacters uses FileReader and FileWriter for input and output in place of FileInputStream and FileOutputStream. Notice that both CopyBytes and CopyCharacters use an int variable to read to and write from. However, in CopyCharacters, the int variable holds a character value in its last 16 bits; in CopyBytes, the int variable holds a byte value in its last 8 bits.

Character Streams that Use Byte Streams

Character streams are often "wrappers" for byte streams. The character stream uses the byte stream to perform the physical I/O, while the character stream handles translation between characters and bytes. FileReader, for example, uses FileInputStream, while FileWriter uses FileOutputStream.

There are two general-purpose byte-to-character "bridge" streams: InputStreamReader and OutputStreamWriter. Use them to create character streams when there are no prepackaged character stream classes that meet your needs. The sockets lesson in the networking trail shows how to create character streams from the byte streams provided by socket classes.

Line-Oriented I/O

Character I/O usually occurs in bigger units than single characters. One common unit is the line: a string of characters with a line terminator at the end. A line terminator can be a carriage-return/line-feed sequence ("\r\n"), a single carriage-return ("\r"), or a single line-feed ("\n"). Supporting all possible line terminators allows programs to read text files created on any of the widely used operating systems.

Let's modify the CopyCharacters example to use line-oriented I/O. To do this, we have to use two classes we haven't seen before, BufferedReader and PrintWriter. We'll explore these classes in greater depth in Buffered I/O and Formatting. Right now, we're just interested in their support for line-oriented I/O.

The CopyLines example invokes BufferedReader.readLine and PrintWriter.println to do input and output one line at a time.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.FileReader;
import java.io.FileWriter;
import java.io.BufferedReader;
import java.io.PrintWriter;
import java.io.IOException;

public class CopyLines {
    public static void main(String[] args) throws IOException {
        BufferedReader inputStream = null;
        PrintWriter outputStream = null;

        try {
            inputStream =
                new BufferedReader(new FileReader("xanadu.txt"));
            outputStream =
                new PrintWriter(new FileWriter("characteroutput.txt"));

            String l;
            while ((l = inputStream.readLine()) != null) {
                outputStream.println(l);
            }
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
            if (outputStream != null) {
                outputStream.close();
            }
        }
    }
}
Invoking readLine returns a line of text with the line CopyLines outputs each line using println, which appends the line terminator for the current operating system. This might not be the same line terminator that was used in the input file.

There are many ways to structure text input and output beyond characters and lines. For more information, see Scanning and Formatting.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Byte Streams
Next page: Buffered Streams


Buffered Streams (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Section: I/O Streams
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
Buffered Streams
Most of the examples we've seen so far use unbuffered I/O. This means each read or write request is handled directly by the underlying OS. This can make a program much less efficient, since each such request often triggers disk access, network activity, or some other operation that is relatively expensive.

To reduce this kind of overhead, the Java platform implements buffered I/O streams. Buffered input streams read data from a memory area known as a buffer; the native input API is called only when the buffer is empty. Similarly, buffered output streams write data to a buffer, and the native output API is called only when the buffer is full.

A program can convert an unbuffered stream into a buffered stream using the wrapping idiom we've used several times now, where the unbuffered stream object is passed to the constructor for a buffered stream class. Here's how you might modify the constructor invocations in the CopyCharacters example to use buffered I/O:

        inputStream =
            new BufferedReader(new FileReader("xanadu.txt"));
        outputStream =
            new BufferedWriter(new FileWriter("characteroutput.txt"));
There are four buffered stream classes used to wrap unbuffered streams: BufferedInputStream and BufferedOutputStream create buffered byte streams, while BufferedReader and BufferedWriter create buffered character streams.

Flushing Buffered Streams

It often makes sense to write out a buffer at critical points, without waiting for it to fill. This is known as flushing the buffer.

Some buffered output classes support autoflush, specified by an optional constructor argument. When autoflush is enabled, certain key events cause the buffer to be flushed. For example, an autoflush PrintWriter object flushes the buffer on every invocation of println or format. See Formatting for more on these methods.

To flush a stream manually, invoke its flush method. The flush method is valid on any output stream, but has no effect unless the stream is buffered.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Character Streams
Next page: Scanning and Formatting


Scanning and Formatting (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Section: I/O Streams
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
Scanning and Formatting
Programming I/O often involves translating to and from the neatly formatted data humans like to work with. To assist you with these chores, the Java platform provides two APIs. The scanner API breaks input into individual tokens associated with bits of data. The formatting API assembles data into nicely formatted, human-readable form.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Buffered Streams
Next page: Scanning


Scanning (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Section: I/O Streams
Subsection: Scanning and Formatting
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
Scanning
Objects of type Scanner are useful for breaking down formatted input into tokens and translating individual tokens according to their data type.

Breaking Input into Tokens

By default, a scanner uses white space to separate tokens. (White space characters include blanks, tabs, and line terminators. For the full list, refer to the documentation for Character.isWhitespace.) To see how scanning works, let's look at ScanXan, a program that reads the individual words in xanadu.txt and prints them out, one per line.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.*;
import java.util.Scanner;

public class ScanXan {
    public static void main(String[] args) throws IOException {
        Scanner s = null;
        try {
            s = new Scanner(new BufferedReader(new FileReader("xanadu.txt")));

            while (s.hasNext()) {
                System.out.println(s.next());
            }
        } finally {
            if (s != null) {
                s.close();
            }
        }
    }
}
Notice that ScanXan invokes Scanner's close method when it is done with the scanner object. Even though a scanner is not a stream, you need to close it to indicate that you're done with its underlying stream.

The output of ScanXan looks like this:

In
Xanadu
did
Kubla
Khan
A
stately
pleasure-dome
...
To use a different token separator, invoke useDelimiter(), specifying a regular expression. For example, suppose you wanted the token separator to be a comma, optionally followed by white space. You would invoke,
s.useDelimiter(",\\s*");

Translating Individual Tokens

The ScanXan example treats all input tokens as simple String values. Scanner also supports tokens for all of the Java language's primitive types (except for char), as well as BigInteger and BigDecimal. Also, numeric values can use thousands separators. Thus, in a US locale, Scanner correctly reads the string "32,767" as representing an integer value.

We have to mention the locale, because thousands separators and decimal symbols are locale specific. So, the following example would not work correctly in all locales if we didn't specify that the scanner should use the US locale. That's not something you usually have to worry about, because your input data usually comes from sources that use the same locale as you do. But this example is part of the Java Tutorial and gets distributed all over the world.

The ScanSum example reads a list of double values and adds them up. Here's the source:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.FileReader;
import java.io.BufferedReader;
import java.io.IOException;
import java.util.Scanner;
import java.util.Locale;

public class ScanSum {
    public static void main(String[] args) throws IOException {
        Scanner s = null;
        double sum = 0;
        try {
            s = new Scanner(
                    new BufferedReader(new FileReader("usnumbers.txt")));
            s.useLocale(Locale.US);

            while (s.hasNext()) {
                if (s.hasNextDouble()) {
                        sum += s.nextDouble();
                    } else {
                        s.next();
                    }
            }
        } finally {
            s.close();
        }

        System.out.println(sum);
    }
}
And here's the sample input file, usnumbers.txt
8.5
32,767
3.14159
1,000,000.1
The output string is "1032778.74159". The period will be a different character in some locales, because System.out is a PrintStream object, and that class doesn't provide a way to override the default locale. We could override the locale for the whole program — or we could just use formatting, as described in the next topic, Formatting.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Scanning and Formatting
Next page: Formatting


Formatting (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Section: I/O Streams
Subsection: Scanning and Formatting
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
Formatting
Stream objects that implement formatting are instances of either PrintWriter, a character stream class, and PrintStream, a byte stream class.
Note: The only PrintStream objects you are likely to need are System.out and System.err. (See I/O from the Command Line for more on these objects.) When you need to create a formatted output stream, instantiate PrintWriter, not PrintStream.

Like all byte and character stream objects, instances of PrintStream and PrintWriter implement a standard set of write methods for simple byte and character output. In addition, both PrintStream and PrintWriter implement the same set of methods for converting internal data into formatted output. Two levels of formatting are provided:

  • print and println format individual values in a standard way.
  • format formats almost any number of values based on a format string, with many options for precise formatting.

The print and println Methods

Invoking print or println outputs a single value after converting the value using the appropriate toString method. We can see this in the Root example:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class Root {
    public static void main(String[] args) {
        int i = 2;
        double r = Math.sqrt(i);

        System.out.print("The square root of ");
        System.out.print(i);
        System.out.print(" is ");
        System.out.print(r);
        System.out.println(".");

        i = 5;
        r = Math.sqrt(i);
        System.out.println("The square root of " + i + " is " + r + ".");
    }
}
Here is the output of Root:
The square root of 2 is 1.4142135623730951.
The square root of 5 is 2.23606797749979.
The i and r variables are formatted twice: the first time using code in an overload of print, the second time by conversion code automatically generated by the Java compiler, which also utilizes toString. You can format any value this way, but you don't have much control over the results.

The format Method

The format method formats multiple arguments based on a format string. The format string consists of static text embedded with format specifiers; except for the format specifiers, the format string is output unchanged.

Format strings support many features. In this tutorial, we'll just cover some basics. For a complete description, see format string syntax in the API specification.

The Root2 example formats two values with a single format invocation:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class Root2 {
    public static void main(String[] args) {
        int i = 2;
        double r = Math.sqrt(i);

        System.out.format("The square root of %d is %f.%n", i, r);
    }
}
Here is the output:
The square root of 2 is 1.414214.
Like the three used in this example, all format specifiers begin with a % and end with a 1- or 2-character conversion that specifies the kind of formatted output being generated. The three conversions used here are:
  • d formats an integer value as a decimal value.
  • f formats a floating point value as a decimal value.
  • n outputs a platform-specific line terminator.
Here are some other conversions:
  • x formats an integer as a hexadecimal value.
  • s formats any value as a string.
  • tB formats an integer as a locale-specific month name.
There are many other conversions.
Note: Except for %% and %n, all format specifiers must match an argument. If they don't, an exception is thrown.

In the Java programming language, the \n escape always generates the linefeed character (\u000A). Don't use \n unless you specifically want a linefeed character. To get the correct line separator for the local platform, use %n.

In addition to the conversion, a format specifier can contain several additional elements that further customize the formatted output. Here's an example, Format, that uses every possible kind of element.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class Format {
    public static void main(String[] args) {
        System.out.format("%f, %1$+020.10f %n", Math.PI);
    }
}
Here's the output:
3.141593, +00000003.1415926536
The additional elements are all optional. The following figure shows how the longer specifier breaks down into elements.

Elements of a format specifier

Elements of a Format Specifier.

The elements must appear in the order shown. Working from the right, the optional elements are:
  • Precision. For floating point values, this is the mathematical precision of the formatted value. For s and other general conversions, this is the maximum width of the formatted value; the value is right-truncated if necessary.
  • Width. The minimum width of the formatted value; the value is padded if necessary. By default the value is left-padded with blanks.
  • Flags specify additional formatting options. In the Format example, the + flag specifies that the number should always be formatted with a sign, and the 0 flag specifies that 0 is the padding character. Other flags include - (pad on the right) and , (format number with locale-specific thousands separators). Note that some flags cannot be used with certain other flags or with certain conversions.
  • The Argument Index allows you to explicitly match a designated argument. You can also specify < to match the same argument as the previous specifier. Thus the example could have said:
    System.out.format("%f, %<+020.10f %n", Math.PI);
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Scanning
Next page: I/O from the Command Line


I/O from the Command Line (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Section: I/O Streams
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
I/O from the Command Line
A program is often run from the command line and interacts with the user in the command line environment. The Java platform supports this kind of interaction in two ways: through the Standard Streams and through the Console.

Standard Streams

Standard Streams are a feature of many operating systems. By default, they read input from the keyboard and write output to the display. They also support I/O on files and between programs, but that feature is controlled by the command line interpreter, not the program.

The Java platform supports three Standard Streams: Standard Input, accessed through System.in; Standard Output, accessed through System.out; and Standard Error, accessed through System.err. These objects are defined automatically and do not need to be opened. Standard Output and Standard Error are both for output; having error output separately allows the user to divert regular output to a file and still be able to read error messages. For more information, refer to the documentation for your command line interpreter.

You might expect the Standard Streams to be character streams, but, for historical reasons, they are byte streams. System.out and System.err are defined as PrintStream objects. Although it is technically a byte stream, PrintStream utilizes an internal character stream object to emulate many of the features of character streams.

By contrast, System.in is a byte stream with no character stream features. To use Standard Input as a character stream, wrap System.in in InputStreamReader.

InputStreamReader cin = new InputStreamReader(System.in);

The Console

A more advanced alternative to the Standard Streams is the Console. This is a single, predefined object of type Console that has most of the features provided by the Standard Streams, and others besides. The Console is particularly useful for secure password entry. The Console object also provides input and output streams that are true character streams, through its reader and writer methods.

Before a program can use the Console, it must attempt to retrieve the Console object by invoking System.console(). If the Console object is available, this method returns it. If System.console returns NULL, then Console operations are not permitted, either because the OS doesn't support them or because the program was launched in a noninteractive environment.

The Console object supports secure password entry through its readPassword method. This method helps secure password entry in two ways. First, it suppresses echoing, so the password is not visible on the user's screen. Second, readPassword returns a character array, not a String, so the password can be overwritten, removing it from memory as soon as it is no longer needed.

The Password example is a prototype program for changing a user's password. It demonstrates several Console methods.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.Console;
import java.util.Arrays;
import java.io.IOException;

public class Password {

    public static void main (String args[]) throws IOException {

        Console c = System.console();
        if (c == null) {
            System.err.println("No console.");
            System.exit(1);
        }

        String login = c.readLine("Enter your login: ");
        char [] oldPassword = c.readPassword("Enter your old password: ");

        if (verify(login, oldPassword)) {
            boolean noMatch;
            do {
                char [] newPassword1 =
                    c.readPassword("Enter your new password: ");
                char [] newPassword2 =
                    c.readPassword("Enter new password again: ");
                noMatch = ! Arrays.equals(newPassword1, newPassword2);
                if (noMatch) {
                    c.format("Passwords don't match. Try again.%n");
                } else {
                    change(login, newPassword1);
                    c.format("Password for %s changed.%n", login);
                }
                Arrays.fill(newPassword1, ' ');
                Arrays.fill(newPassword2, ' ');
            } while (noMatch);
        }

        Arrays.fill(oldPassword, ' ');

    }

    //Dummy verify method.
    static boolean verify(String login, char[] password) {
        return true;
    }

    //Dummy change method.
    static void change(String login, char[] password) {}
}
Password follows these steps:
  1. Attempt to retrieve the Console object. If the object is not available, abort.
  2. Invoke Console.readLine to prompt for and read the user's login name.
  3. Invoke Console.readPassword to prompt for and read the user's existing password.
  4. Invoke verify to confirm that the user is authorized to change the password. (In this example, verify is a dummy method that always returns true.)
  5. Repeat the following steps until the user enters the same password twice:
    1. Invoke Console.readPassword twice to prompt for and read a new password.
    2. If the user entered the same password both times, invoke change to change it. (Again, change is a dummy method.)
    3. Overwrite both passwords with blanks.
  6. Overwrite the old password with blanks.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Formatting
Next page: Data Streams


Data Streams (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Section: I/O Streams
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
Data Streams
Data streams support binary I/O of primitive data type values (boolean, char, byte, short, int, long, float, and double) as well as String values. All data streams implement either the DataInput interface or the DataOutput interface. This section focuses on the most widely-used implementations of these interfaces, DataInputStream and DataOutputStream.

The DataStreams example demonstrates data streams by writing out a set of data records, and then reading them in again. Each record consists of three values related to an item on an invoice, as shown in the following table:

Order in record | Data type | Data description | Output Method | Input Method | Sample Value
1 | double | Item price | DataOutputStream.writeDouble | DataInputStream.readDouble | 19.99
2 | int | Unit count | DataOutputStream.writeInt | DataInputStream.readInt | 12
3 | String | Item description | DataOutputStream.writeUTF | DataInputStream.readUTF | "Java T-Shirt"

Let's examine crucial code in DataStreams. First, the program defines some constants containing the name of the data file and the data that will be written to it:

static final String dataFile = "invoicedata";

static final double[] prices = { 19.99, 9.99, 15.99, 3.99, 4.99 };
static final int[] units = { 12, 8, 13, 29, 50 };
static final String[] descs = { "Java T-shirt",
        "Java Mug",
        "Duke Juggling Dolls",
        "Java Pin",
        "Java Key Chain" };
Then DataStreams opens an output stream. Since a DataOutputStream can only be created as a wrapper for an existing byte stream object, DataStreams provides a buffered file output byte stream.
out = new DataOutputStream(new
            BufferedOutputStream(new FileOutputStream(dataFile)));
DataStreams writes out the records and closes the output stream.
for (int i = 0; i < prices.length; i ++) {
    out.writeDouble(prices[i]);
    out.writeInt(units[i]);
    out.writeUTF(descs[i]);
}
The writeUTF method writes out String values in a modified form of UTF-8. This is a variable-width character encoding that only needs a single byte for common Western characters.

Now DataStreams reads the data back in again. First it must provide an input stream, and variables to hold the input data. Like DataOutputStream, DataInputStream must be constructed as a wrapper for a byte stream.

in = new DataInputStream(new
            BufferedInputStream(new FileInputStream(dataFile)));

double price;
int unit;
String desc;
double total = 0.0;
Now DataStreams can read each record in the stream, reporting on the data it encounters.
try {
    while (true) {
        price = in.readDouble();
        unit = in.readInt();
        desc = in.readUTF();
        System.out.format("You ordered %d units of %s at $%.2f%n",
                unit, desc, price);
        total += unit * price;
    }
} catch (EOFException e) {
}
Notice that DataStreams detects an end-of-file condition by catching EOFException, instead of testing for an invalid return value. All implementations of DataInput methods use EOFException instead of return values.

Also notice that each specialized write in DataStreams is exactly matched by the corresponding specialized read. It is up to the programmer to make sure that output types and input types are matched in this way: The input stream consists of simple binary data, with nothing to indicate the type of individual values, or where they begin in the stream.

DataStreams uses one very bad programming technique: it uses floating point numbers to represent monetary values. In general, floating point is bad for precise values. It's particularly bad for decimal fractions, because common values (such as 0.1) do not have a binary representation.

The correct type to use for currency values is java.math.BigDecimal. Unfortunately, BigDecimal is an object type, so it won't work with data streams. However, BigDecimal will work with object streams, which are covered in the next section.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: I/O from the Command Line
Next page: Object Streams


Object Streams (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Section: I/O Streams
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
Object Streams
Just as data streams support I/O of primitive data types, object streams support I/O of objects. Most, but not all, standard classes support serialization of their objects. Those that do implement the marker interface Serializable.

The object stream classes are ObjectInputStream and ObjectOutputStream. These classes implement ObjectInput and ObjectOutput, which are subinterfaces of DataInput and DataOutput. That means that all the primitive data I/O methods covered in Data Streams are also implemented in object streams. So an object stream can contain a mixture of primitive and object values. The ObjectStreams example illustrates this. ObjectStreams creates the same application as DataStreams, with a couple of changes. First, prices are now BigDecimalobjects, to better represent fractional values. Second, a Calendar object is written to the data file, indicating an invoice date.

If readObject() doesn't return the object type expected, attempting to cast it to the correct type may throw a ClassNotFoundException. In this simple example, that can't happen, so we don't try to catch the exception. Instead, we notify the compiler that we're aware of the issue by adding ClassNotFoundException to the main method's throws clause.

Output and Input of Complex Objects

The writeObject and readObject methods are simple to use, but they contain some very sophisticated object management logic. This isn't important for a class like Calendar, which just encapsulates primitive values. But many objects contain references to other objects. If readObject is to reconstitute an object from a stream, it has to be able to reconstitute all of the objects the original object referred to. These additional objects might have their own references, and so on. In this situation, writeObject traverses the entire web of object references and writes all objects in that web onto the stream. Thus a single invocation of writeObject can cause a large number of objects to be written to the stream.

This is demonstrated in the following figure, where writeObject is invoked to write a single object named a. This object contains references to objects b and c, while b contains references to d and e. Invoking writeobject(a) writes not just a, but all the objects necessary to reconstitute a, so the other four objects in this web are written also. When a is read back by readObject, the other four objects are read back as well, and all the original object references are preserved.

I/O of multiple referred-to objects

I/O of multiple referred-to objects

You might wonder what happens if two objects on the same stream both contain references to a single object. Will they both refer to a single object when they're read back? The answer is "yes." A stream can only contain one copy of an object, though it can contain any number of references to it. Thus if you explicitly write an object to a stream twice, you're really writing only the reference twice. For example, if the following code writes an object ob twice to a stream:
Object ob = new Object();
out.writeObject(ob);
out.writeObject(ob);
Each writeObject has to be matched by a readObject, so the code that reads the stream back will look something like this:
Object ob1 = in.readObject();
Object ob2 = in.readObject();
This results in two variables, ob1 and ob2, that are references to a single object.

However, if a single object is written to two different streams, it is effectively duplicated — a single program reading both streams back will see two distinct objects.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Data Streams
Next page: File I/O


File I/O (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
File I/O
So far, this lesson has focused on streams, which provide a simple model for reading and writing data. Streams work with a large variety of data sources and destinations, including disk files. However, streams don't support all the operations that are common with disk files. In this part of the lesson, we'll focus on non-stream file I/O. There are two topics:
  • File is a class that helps you write platform-independent code that examines and manipulates files and directories.
  • Random access files support nonsequential access to disk file data.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Object Streams
Next page: File Objects


File Objects (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Section: File I/O
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
File Objects
The File class makes it easier to write platform-independent code that examines and manipulates files. The name of this class is misleading: File instances represent file names, not files. The file corresponding to the file name might not even exist.

Why create a File object for a file that doesn't exist? A program can use the object to parse a file name. Also, the file can be created by passing the File object to the constructor of some classes, such as FileWriter.

If the file does exist, a program can examine its attributes and perform various operations on the file, such as renaming it, deleting it, or changing its permissions.

A File Has Many Names

A File object contains the file name string used to construct it. That string never changes throughout the lifetime of the object. A program can use the File object to obtain other versions of the file name, some of which may or may not be the same as the original file name string passed to the constructor.

Suppose a program creates a File object with the constructor invocation

File a = new File("xanadu.txt");
The program invokes a number of methods to obtain different versions of the file name. The program is then run both on a Microsoft Windows system (in directory c:\java\examples) and a Solaris system (in directory /home/cafe/java/examples). Here is what the methods would return:

Method Invoked | Returns on Microsoft Windows | Returns on Solaris
a.toString() | xanadu.txt | xanadu.txt
a.getName() | xanadu.txt | xanadu.txt
b.getParent() | NULL | NULL
a.getAbsolutePath() | c:\java\examples\xanadu.txt | /home/cafe/java/examples/xanadu.txt
a.getCanonicalPath() | c:\java\examples\xanadu.txt | /home/cafe/java/examples/xanadu.txt

Then the same program constructs a File object from a more complicated file name, using File.separator to specify the file name in a platform-independent way.

File b = new File(".." + File.separator + "examples" + File.separator + "xanadu.txt");
Although b refers to the same file as a, the methods return slightly different values:

Method Invoked | Returns on Microsoft Windows | Returns on Solaris
b.toString() | ..\examples\xanadu.txt | ../examples/xanadu.txt
b.getName() | xanadu.txt | xanadu.txt
b.getParent() | ..\examples | ../examples
b.getAbsolutePath() | c:\java\examples\..\examples\xanadu.txt | /home/cafe/java/examples/../examples/xanadu.txt
b.getCanonicalPath() | c:\java\examples\xanadu.txt | /home/cafe/java/examples/xanadu.txt

Running the same program on a Linux system would give results similar to those on the Solaris system.

It's worth mentioning that File.compareTo()would not consider a and b to be the same. Even though they refer to the same file, the names used to construct them are different.

The FileStuff example creates File objects from names passed from the command line and exercises various information methods on them. You'll find it instructive to run FileStuff on a variety of file names. Be sure to include directory names as well as the names of files that don't actually exist. Try passing FileStuff a variety of relative and absolute path names.

Manipulating Files

If a File object names an actual file, a program can use it to perform a number of useful operations on the file. These include passing the object to the constructor for a stream to open the file for reading or writing.

The delete method deletes the file immediately, while the deleteOnExit method deletes the file when the virtual machine terminates.

The setLastModified sets the modification date/time for the file. For example, to set the modification time of xanadu.txt to the current time, a program could do

new File("xanadu.txt").setLastModified(new Date().getTime());

The renameTo() method renames the file. Note that the file name string behind the File object remains unchanged, so the File object will not refer to the renamed file.

Working with Directories

File has some useful methods for working with directories.

The mkdir method creates a directory. The mkdirs method does the same thing, after first creating any parent directories that don't yet exist.

The list and listFiles methods list the contents of a directory. The list method returns an array of String file names, while listFiles returns an array of File objects.

Static Methods

File contains some useful static methods.

The createTempFile method creates a new file with a unique name and returns a File object referring to it

The listRoots returns a list of file system root names. On Microsoft Windows, this will be the root directories of mounted drives, such as a:\ and c:\. On UNIX and Linux systems, this will be the root directory, /.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: File I/O
Next page: Random Access Files


Random Access Files (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Section: File I/O
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
Random Access Files
Random access files permit nonsequential, or random, access to a file's contents.

Consider the archive format known as ZIP. A ZIP archive contains files and is typically compressed to save space. It also contains a directory entry at the end that indicates where the various files contained within the ZIP archive begin, as shown in the following figure.

A ZIP archive.

A ZIP archive.

Suppose that you want to extract a specific file from a ZIP archive. If you use a sequential access stream, you have to:
  1. Open the ZIP archive.
  2. Search through the ZIP archive until you locate the file you want to extract.
  3. Extract the file.
  4. Close the ZIP archive.
Using this procedure, on average, you'd have to read half the ZIP archive before finding the file that you want to extract. You can extract the same file from the ZIP archive more efficiently by using the seek feature of a random access file and following these steps:
  • Open the ZIP archive.
  • Seek to the directory entry and locate the entry for the file you want to extract from the ZIP archive.
  • Seek (backward) within the ZIP archive to the position of the file to extract.
  • Extract the file.
  • Close the ZIP archive.
This algorithm is more efficient because you read only the directory entry and the file that you want to extract.

The java.io.RandomAccessFile class implements both the DataInput and DataOutput interfaces and therefore can be used for both reading and writing. RandomAccessFile is similar to FileInputStream and FileOutputStream in that you specify a file on the native file system to open when you create it. When you create a RandomAccessFile, you must indicate whether you will be just reading the file or also writing to it. (You have to be able to read a file in order to write it.) The following code creates a RandomAccessFile to read the file named xanadu.txt:

new RandomAccessFile("xanadu.txt", "r");
And this one opens the same file for both reading and writing:
new RandomAccessFile("xanadu.txt", "rw");
After the file has been opened, you can use the common read or write methods defined in the DataInput and DataOutput interfaces to perform I/O on the file.

RandomAccessFile supports the notion of a file pointer. The file pointer indicates the current location in the file. When the file is first created, the file pointer is set to 0, indicating the beginning of the file. Calls to the read and write methods adjust the file pointer by the number of bytes read or written.

A ZIP file has the notion of a current file pointer.

A ZIP file has the notion of a current file pointer.

In addition to the normal file I/O methods that implicitly move the file pointer when the operation occurs, RandomAccessFile contains three methods for explicitly manipulating the file pointer.
  • int skipBytes(int) — Moves the file pointer forward the specified number of bytes
  • void seek(long) — Positions the file pointer just before the specified byte
  • long getFilePointer() — Returns the current byte location of the file pointer
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: File Objects
Next page: The New I/O Packages


The New I/O Packages (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
The New I/O Packages
This lesson has mostly talked about the java.io package. This package provides all the I/O features most programmers will ever need. The package implements basic I/O services — data streams, random access files, character translation, and buffering — with a simple and easy-to-use API.

However, some programmers of high-performance applications will need more flexibility than the java.io package supplies. They'll find it in the java.nio.* packages. These packages provide APIs for scalable I/O, fast buffered byte and character I/O, and character set conversion

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Random Access Files
Next page: Summary


Summary (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
Summary
The java.io package contains many classes that your programs can use to read and write data. Most of the classes implement sequential access streams. The sequential access streams can be divided into two groups: those that read and write bytes and those that read and write Unicode characters. Each sequential access stream has a speciality, such as reading from or writing to a file, filtering data as its read or written, or serializing an object.

One class, RandomAccessFile, implements random input/output access to a file. An object of this type maintains a file pointer, which indicates the current location from which data will be read or to which data will be written.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The New I/O Packages
Next page: Questions and Exercises: Basic I/O


Questions and Exercises: Basic I/O (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises
Home Page > Essential Classes > Basic I/O
« Previous • Trail • Next »
Questions and Exercises: Basic I/O

Questions

1. What class would you use to read a few pieces of data that are at known positions near the end of a large file?

2. In a format call, what's the best way to indicate a new line?

3. How would you append data to the end of a file? Show the constructor for the class you would use and explain your answer.

Exercises

1. Implement a pair of classes, one Reader and one Writer, that count the number of times a particular character, such as e, is read or written. The character can be specified when the stream is created. Write a program to test your classes. You can use xanadu.txt as the input file.

2. The file datafile begins with a single long that tells you the offset of a single int piece of data within the same file. Using the RandomAccessFile class, write a program that gets the int piece of data. What is the int data?

Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary
Next page: Concurrency


Lesson: Concurrency (The Java™ Tutorials > Essential Classes)

Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Trail: Essential Classes
Home Page > Essential Classes
« Previous • Trail • Next »
Lesson: Concurrency
Computer users take it for granted that their systems can do more than one thing at a time. They assume that they can continue to work in a word processor, while other applications download files, manage the print queue, and stream audio. Even a single application is often expected to do more than one thing at a time. For example, that streaming audio application must simultaneously read the digital audio off the network, decompress it, manage playback, and update its display. Even the word processor should always be ready to respond to keyboard and mouse events, no matter how busy it is reformatting text or updating the display. Software that can do such things is known as concurrent software.

The Java platform is designed from the ground up to support concurrent programming, with basic concurrency support in the Java programming language and the Java class libraries. Since version 5.0, the Java platform has also included high-level concurrency APIs. This lesson introduces the platform's basic concurrency support and summarizes some of the high-level APIs in the java.util.concurrent packages.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Processes and Threads


Processes and Threads (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Processes and Threads
In concurrent programming, there are two basic units of execution: processes and threads. In the Java programming language, concurrent programming is mostly concerned with threads. However, processes are also important.

A computer system normally has many active processes and threads. This is true even in systems that only have a single execution core, and thus only have one thread actually executing at any given moment. Processing time for a single core is shared among processes and threads through an OS feature called time slicing.

It's becoming more and more common for computer systems to have multiple processors or processors with multiple execution cores. This greatly enhances a system's capacity for concurrent execution of processes and threads — but concurrency is possible even on simple systems, without multiple processors or execution cores.

Processes

A process has a self-contained execution environment. A process generally has a complete, private set of basic run-time resources; in particular, each process has its own memory space.

Processes are often seen as synonymous with programs or applications. However, what the user sees as a single application may in fact be a set of cooperating processes. To facilitate communication between processes, most operating systems support Inter Process Communication (IPC) resources, such as pipes and sockets. IPC is used not just for communication between processes on the same system, but processes on different systems.

Most implementations of the Java virtual machine run as a single process. A Java application can create additional processes using a ProcessBuilder object. Multiprocess applications are beyond the scope of this lesson.

Threads

Threads are sometimes called lightweight processes. Both processes and threads provide an execution environment, but creating a new thread requires fewer resources than creating a new process.

Threads exist within a process — every process has at least one. Threads share the process's resources, including memory and open files. This makes for efficient, but potentially problematic, communication.

Multithreaded execution is an essential feature of the Java platform. Every application has at least one thread — or several, if you count "system" threads that do things like memory management and signal handling. But from the application programmer's point of view, you start with just one thread, called the main thread. This thread has the ability to create additional threads, as we'll demonstrate in the next section.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Concurrency
Next page: Thread Objects


Thread Objects (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Thread Objects
Each thread is associated with an instance of the class Thread. There are two basic strategies for using Thread objects to create a concurrent application.
  • To directly control thread creation and management, simply instantiate Thread each time the application needs to initiate an asynchronous task.
  • To abstract thread management from the rest of your application, pass the application's tasks to an executor.
This section documents the use of Thread objects. Executors are discussed with other high-level concurrency objects.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Processes and Threads
Next page: Defining and Starting a Thread


Defining and Starting a Thread (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: Thread Objects
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Defining and Starting a Thread
An application that creates an instance of Thread must provide the code that will run in that thread. There are two ways to do this:
  • Provide a Runnable object. The Runnable interface defines a single method, run, meant to contain the code executed in the thread. The Runnable object is passed to the Thread constructor, as in the HelloRunnable example:
    /*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class HelloRunnable implements Runnable {

    public void run() {
        System.out.println("Hello from a thread!");
    }

    public static void main(String args[]) {
        (new Thread(new HelloRunnable())).start();
    }

}
  • Subclass Thread. The Thread class itself implements Runnable, though its run method does nothing. An application can subclass Thread, providing its own implementation of run, as in the HelloThread example:
    /*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class HelloThread extends Thread {

    public void run() {
        System.out.println("Hello from a thread!");
    }

    public static void main(String args[]) {
        (new HelloThread()).start();
    }

}
Notice that both examples invoke Thread.start in order to start the new thread.

Which of these idioms should you use? The first idiom, which employs a Runnable object, is more general, because the Runnable object can subclass a class other than Thread. The second idiom is easier to use in simple applications, but is limited by the fact that your task class must be a descendant of Thread. This lesson focuses on the first approach, which separates the Runnable task from the Thread object that executes the task. Not only is this approach more flexible, but it is applicable to the high-level thread management APIs covered later.

The Thread class defines a number of methods useful for thread management. These include static methods, which provide information about, or affect the status of, the thread invoking the method. The other methods are invoked from other threads involved in managing the thread and Thread object. We'll examine some of these methods in the following sections.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Thread Objects
Next page: Pausing Execution with Sleep


Pausing Execution with Sleep (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: Thread Objects
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Pausing Execution with Sleep
Thread.sleep causes the current thread to suspend execution for a specified period. This is an efficient means of making processor time available to the other threads of an application or other applications that might be running on a computer system. The sleep method can also be used for pacing, as shown in the example that follows, and waiting for another thread with duties that are understood to have time requirements, as with the SimpleThreads example in a later section.

Two overloaded versions of sleep are provided: one that specifies the sleep time to the millisecond and one that specifies the sleep time to the nanosecond. However, these sleep times are not guaranteed to be precise, because they are limited by the facilities provided by the underlying OS. Also, the sleep period can be terminated by interrupts, as we'll see in a later section. In any case, you cannot assume that invoking sleep will suspend the thread for precisely the time period specified.

The SleepMessages example uses sleep to print messages at four-second intervals:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class SleepMessages {
    public static void main(String args[]) throws InterruptedException {
        String importantInfo[] = {
            "Mares eat oats",
            "Does eat oats",
            "Little lambs eat ivy",
            "A kid will eat ivy too"
        };

        for (int i = 0; i < importantInfo.length; i++) {
            //Pause for 4 seconds
            Thread.sleep(4000);
            //Print a message
            System.out.println(importantInfo[i]);
        }
    }
}
Notice that main declares that it throws InterruptedException. This is an exception that sleep throws when another thread interrupts the current thread while sleep is active. Since this application has not defined another thread to cause the interrupt, it doesn't bother to catch InterruptedException.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Defining and Starting a Thread
Next page: Interrupts


Interrupts (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: Thread Objects
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Interrupts
An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate. This is the usage emphasized in this lesson.

A thread sends an interrupt by invoking interrupt on the Thread object for the thread to be interrupted. For the interrupt mechanism to work correctly, the interrupted thread must support its own interruption.

Supporting Interruption

How does a thread support its own interruption? This depends on what it's currently doing. If the thread is frequently invoking methods that throw InterruptedException, it simply returns from the run method after it catches that exception. For example, suppose the central message loop in the SleepMessages example were in the run method of a thread's Runnable object. Then it might be modified as follows to support interrupts:
for (int i = 0; i < importantInfo.length; i++) {
    //Pause for 4 seconds
    try {
        Thread.sleep(4000);
    } catch (InterruptedException e) {
        //We've been interrupted: no more messages.
        return;
    }
    //Print a message
    System.out.println(importantInfo[i]);
}
Many methods that throw InterruptedException, such as sleep, are designed to cancel their current operation and return immediately when an interrupt is received.

What if a thread goes a long time without invoking a method that throws InterruptedException? Then it must periodically invoke Thread.interrupted, which returns true if an interrupt has been received. For example:

for (int i = 0; i < inputs.length; i++) {
    heavyCrunch(inputs[i]);
    if (Thread.interrupted()) {
        //We've been interrupted: no more crunching.
        return;
    }
}
In this simple example, the code simply tests for the interrupt and exits the thread if one has been received. In more complex applications, it might make more sense to throw an InterruptedException:
if (Thread.interrupted()) {
    throw new InterruptedException();
}
This allows interrupt handling code to be centralized in a catch clause.

The Interrupt Status Flag

The interrupt mechanism is implemented using an internal flag known as the interrupt status. Invoking Thread.interrupt sets this flag. When a thread checks for an interrupt by invoking the static method Thread.interrupted, interrupt status is cleared. The non-static Thread.isInterrupted, which is used by one thread to query the interrupt status of another, does not change the interrupt status flag.

By convention, any method that exits by throwing an InterruptedException clears interrupt status when it does so. However, it's always possible that interrupt status will immediately be set again, by another thread invoking interrupt.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Pausing Execution with Sleep
Next page: Joins


Joins (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: Thread Objects
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Joins
The join method allows one thread to wait for the completion of another. If t is a Thread object whose thread is currently executing,
t.join();
causes the current thread to pause execution until t's thread terminates. Overloads of join allow the programmer to specify a waiting period. However, as with sleep, join is dependent on the OS for timing, so you should not assume that join will wait exactly as long as you specify.

Like sleep, join responds to an interrupt by exiting with an InterruptedException.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Interrupts
Next page: The SimpleThreads Example


The SimpleThreads Example (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: Thread Objects
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
The SimpleThreads Example
The following example brings together some of the concepts of this section. SimpleThreads consists of two threads. The first is the main thread that every Java application has. The main thread creates a new thread from the Runnable object, MessageLoop, and waits for it to finish. If the MessageLoop thread takes too long to finish, the main thread interrupts it.

The MessageLoop thread prints out a series of messages. If interrupted before it has printed all its messages, the MessageLoop thread prints a message and exits.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class SimpleThreads {

    //Display a message, preceded by the name of the current thread
    static void threadMessage(String message) {
        String threadName = Thread.currentThread().getName();
        System.out.format("%s: %s%n", threadName, message);
    }

    private static class MessageLoop implements Runnable {
        public void run() {
            String importantInfo[] = {
                "Mares eat oats",
                "Does eat oats",
                "Little lambs eat ivy",
                "A kid will eat ivy too"
            };
            try {
                for (int i = 0; i < importantInfo.length; i++) {
                    //Pause for 4 seconds
                    Thread.sleep(4000);
                    //Print a message
                    threadMessage(importantInfo[i]);
                }
            } catch (InterruptedException e) {
                threadMessage("I wasn't done!");
            }
        }
    }

    public static void main(String args[]) throws InterruptedException {

        //Delay, in milliseconds before we interrupt MessageLoop
        //thread (default one hour).
        long patience = 1000 * 60 * 60;

        //If command line argument present, gives patience in seconds.
        if (args.length > 0) {
            try {
                patience = Long.parseLong(args[0]) * 1000;
            } catch (NumberFormatException e) {
                System.err.println("Argument must be an integer.");
                System.exit(1);
            }

        }

        threadMessage("Starting MessageLoop thread");
        long startTime = System.currentTimeMillis();
        Thread t = new Thread(new MessageLoop());
        t.start();

        threadMessage("Waiting for MessageLoop thread to finish");
        //loop until MessageLoop thread exits
        while (t.isAlive()) {
            threadMessage("Still waiting...");
            //Wait maximum of 1 second for MessageLoop thread to
            //finish.
            t.join(1000);
            if (((System.currentTimeMillis() - startTime) > patience) &&
                    t.isAlive()) {
                threadMessage("Tired of waiting!");
                t.interrupt();
                //Shouldn't be long now -- wait indefinitely
                t.join();
            }

        }
        threadMessage("Finally!");
    }
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Joins
Next page: Synchronization


Synchronization (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Synchronization
Threads communicate primarily by sharing access to fields and the objects reference fields refer to. This form of communication is extremely efficient, but makes two kinds of errors possible: thread interference and memory consistency errors. The tool needed to prevent these errors is synchronization.
  • Thread Interference describes how errors are introduced when multiple threads access shared data.
  • Memory Consistency Errors describes errors that result from inconsistent views of shared memory.
  • Synchronized Methods describes a simple idiom that can effectively prevent thread interference and memory consistency errors.
  • Implicit Locks and Synchronization describes a more general synchronization idiom, and describes how synchronization is based on implicit locks.
  • Atomic Access talks about the general idea of operations that can't be interfered with by other threads.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The SimpleThreads Example
Next page: Thread Interference


Thread Interference (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: Synchronization
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Thread Interference
Consider a simple class called Counter
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class Counter {
    private int c = 0;

    public void increment() {
        c++;
    }

    public void decrement() {
        c--;
    }

    public int value() {
        return c;
    }

}
Counter is designed so that each invocation of increment will add 1 to c, and each invocation of decrement will subtract 1 from c. However, if a Counter object is referenced from multiple threads, interference between threads may prevent this from happening as expected.

Interference happens when two operations, running in different threads, but acting on the same data, interleave. This means that the two operations consist of multiple steps, and the sequences of steps overlap.

It might not seem possible for operations on instances of Counter to interleave, since both operations on c are single, simple statements. However, even simple statements can translate to multiple steps by the virtual machine. We won't examine the specific steps the virtual machine takes — it is enough to know that the single expression c++ can be decomposed into three steps:

  1. Retrieve the current value of c.
  2. Increment the retrieved value by 1.
  3. Store the incremented value back in c.
The expression c-- can be decomposed the same way, except that the second step decrements instead of increments.

Suppose Thread A invokes increment at about the same time Thread B invokes decrement. If the initial value of c is 0, their interleaved actions might follow this sequence:

  1. Thread A: Retrieve c.
  2. Thread B: Retrieve c.
  3. Thread A: Increment retrieved value; result is 1.
  4. Thread B: Decrement retrieved value; result is -1.
  5. Thread A: Store result in c; c is now 1.
  6. Thread B: Store result in c; c is now -1.
Thread A's result is lost, overwritten by Thread B. This particular interleaving is only one possibility. Under different circumstances it might be Thread B's result that gets lost, or there could be no error at all. Because they are unpredictable, thread interference bugs can be difficult to detect and fix.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Synchronization
Next page: Memory Consistency Errors


Memory Consistency Errors (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: Synchronization
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Memory Consistency Errors
Memory consistency errors occur when different threads have inconsistent views of what should be the same data. The causes of memory consistency errors are complex and beyond the scope of this tutorial. Fortunately, the programmer does not need a detailed understanding of these causes. All that is needed is a strategy for avoiding them.

The key to avoiding memory consistency errors is understanding the happens-before relationship. This relationship is simply a guarantee that memory writes by one specific statement are visible to another specific statement. To see this, consider the following example. Suppose a simple int field is defined and initialized:

int counter = 0;
The counter field is shared between two threads, A and B. Suppose thread A increments counter:
counter++;
Then, shortly afterwords, thread B prints out counter:
System.out.println(counter);
If the two statements had been executed in the same thread, it would be safe to assume that the value printed out would be "1". But if the two statements are executed in separate threads, the value printed out might well be "0", because there's no guarantee that thread A's change to counter will be visible to thread B — unless the programmer has established a happens-before relationship between these two statements.

There are several actions that create happens-before relationships. One of them is synchronization, as we will see in the following sections.

We've already seen two actions that create happens-before relationships.

  • When a statement invokes Thread.start, every statement that has a happens-before relationship with that statement also has a happens-before relationship with every statement executed by the new thread. The effects of the code that led up to the creation of the new thread are visible to the new thread.
  • When a thread terminates and causes a Thread.join in another thread to return, then all the statements executed by the terminated thread have a happens-before relationship with all the statements following the successful join. The effects of the code in the thread are now visible to the thread that performed the join.
For a list of actions that create happens-before relationships, refer to the Summary page of the java.util.concurrent package..
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Thread Interference
Next page: Synchronized Methods


Synchronized Methods (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: Synchronization
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Synchronized Methods
The Java programming language provides two basic synchronization idioms: synchronized methods and synchronized statements. The more complex of the two, synchronized statements, are described in the next section. This section is about synchronized methods.

To make a method synchronized, simply add the synchronized keyword to its declaration:

public class SynchronizedCounter {
    private int c = 0;

    public synchronized void increment() {
        c++;
    }

    public synchronized void decrement() {
        c--;
    }

    public synchronized int value() {
        return c;
    }
}
If count is an instance of SynchronizedCounter, then making these methods synchronized has two effects:
  • First, it is not possible for two invocations of synchronized methods on the same object to interleave. When one thread is executing a synchronized method for an object, all other threads that invoke synchronized methods for the same object block (suspend execution) until the first thread is done with the object.
  • Second, when a synchronized method exits, it automatically establishes a happens-before relationship with any subsequent invocation of a synchronized method for the same object. This guarantees that changes to the state of the object are visible to all threads.

Note that constructors cannot be synchronized — using the synchronized keyword with a constructor is a syntax error. Synchronizing constructors doesn't make sense, because only the thread that creates an object should have access to it while it is being constructed.

Warning: When constructing an object that will be shared between threads, be very careful that a reference to the object does not "leak" prematurely. For example, suppose you want to maintain a List called instances containing every instance of class. You might be tempted to add the line
instances.add(this);
to your constructor. But then other threads can use instances to access the object before construction of the object is complete.

Synchronized methods enable a simple strategy for preventing thread interference and memory consistency errors: if an object is visible to more than one thread, all reads or writes to that object's variables are done through synchronized methods. (An important exception: final fields, which cannot be modified after the object is constructed, can be safely read through non-synchronized methods, once the object is constructed) This strategy is effective, but can present problems with liveness, as we'll see later in this lesson.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Memory Consistency Errors
Next page: Intrinsic Locks and Synchronization


Intrinsic Locks and Synchronization (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: Synchronization
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Intrinsic Locks and Synchronization
Synchronization is built around an internal entity known as the intrinsic lock or monitor lock. (The API specification often refers to this entity simply as a "monitor.") Intrinsic locks play a role in both aspects of synchronization: enforcing exclusive access to an object's state and establishing happens-before relationships that are essential to visibility.

Every object has an intrinsic lock associated with it. By convention, a thread that needs exclusive and consistent access to an object's fields has to acquire the object's intrinsic lock before accessing them, and then release the intrinsic lock when it's done with them. A thread is said to own the intrinsic lock between the time it has acquired the lock and released the lock. As long as a thread owns an intrinsic lock, no other thread can acquire the same lock. The other thread will block when it attempts to acquire the lock.

When a thread releases an intrinsic lock, a happens-before relationship is established between that action and any subsequent acquistion of the same lock.

Locks In Synchronized Methods

When a thread invokes a synchronized method, it automatically acquires the intrinsic lock for that method's object and releases it when the method returns. The lock release occurs even if the return was caused by an uncaught exception.

You might wonder what happens when a static synchronized method is invoked, since a static method is associated with a class, not an object. In this case, the thread acquires the intrinsic lock for the Class object associated with the class. Thus access to class's static fields is controlled by a lock that's distinct from the lock for any instance of the class.

Synchronized Statements

Another way to create synchronized code is with synchronized statements. Unlike synchronized methods, synchronized statements must specify the object that provides the intrinsic lock:
public void addName(String name) {
    synchronized(this) {
        lastName = name;
        nameCount++;
    }
    nameList.add(name);
}
In this example, the addName method needs to synchronize changes to lastName and nameCount, but also needs to avoid synchronizing invocations of other objects' methods. (Invoking other objects' methods from synchronized code can create problems that are described in the section on Liveness.) Without synchronized statements, there would have to be a separate, unsynchronized method for the sole purpose of invoking nameList.add.

Synchronized statements are also useful for improving concurrency with fine-grained synchronization. Suppose, for example, class MsLunch has two instance fields, c1 and c2, that are never used together. All updates of these fields must be synchronized, but there's no reason to prevent an update of c1 from being interleaved with an update of c2 — and doing so reduces concurrency by creating unnecessary blocking. Instead of using synchronized methods or otherwise using the lock associated with this, we create two objects solely to provide locks.

public class MsLunch {
    private long c1 = 0;
    private long c2 = 0;
    private Object lock1 = new Object();
    private Object lock2 = new Object();

    public void inc1() {
        synchronized(lock1) {
            c1++;
        }
    }

    public void inc2() {
        synchronized(lock2) {
            c2++;
        }
    }
}
Use this idiom with extreme care. You must be absolutely sure that it really is safe to interleave access of the affected fields.

Reentrant Synchronization

Recall that a thread cannot acquire a lock owned by another thread. But a thread can acquire a lock that it already owns. Allowing a thread to acquire the same lock more than once enables reentrant synchronization. This describes a situation where synchronized code, directly or indirectly, invokes a method that also contains synchronized code, and both sets of code use the same lock. Without reentrant synchronization, synchronized code would have to take many additional precautions to avoid having a thread cause itself to block.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Synchronized Methods
Next page: Atomic Access


Atomic Access (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: Synchronization
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Atomic Access
In programming, an atomic action is one that effectively happens all at once. An atomic action cannot stop in the middle: it either happens completely, or it doesn't happen at all. No side effects of an atomic action are visible until the action is complete.

We have already seen that an increment expression, such as c++, does not describe an atomic action. Even very simple expressions can define complex actions that can decompose into other actions. However, there are actions you can specify that are atomic:

  • Reads and writes are atomic for reference variables and for most primitive variables (all types except long and double).
  • Reads and writes are atomic for all variables declared volatile (including long and double variables).
Atomic actions cannot be interleaved, so they can be used without fear of thread interference. However, this does not eliminate all need to synchronize atomic actions, because memory consistency errors are still possible. Using volatile variables reduces the risk of memory consistency errors, because any write to a volatile variable establishes a happens-before relationship with subsequent reads of that same variable. This means that changes to a volatile variable are always visible to other threads. What's more, it also means that when a thread reads a volatile variable, it sees not just the latest change to the volatile, but also the side effects of the code that led up the change.

Using simple atomic variable access is more efficient than accessing these variables through synchronized code, but requires more care by the programmer to avoid memory consistency errors. Whether the extra effort is worthwhile depends on the size and complexity of the application.

Some of the classes in the java.util.concurrent package provide atomic methods that do not rely on synchronization. We'll discuss them in the section on High Level Concurrency Objects.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Intrinsic Locks and Synchronization
Next page: Liveness


Liveness (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Liveness
A concurrent application's ability to execute in a timely manner is known as its liveness. This section describes the most common kind of liveness problem, deadlock, and goes on to briefly describe two other liveness problems, starvation and livelock.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Atomic Access
Next page: Deadlock


Deadlock (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: Liveness
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Deadlock
Deadlock describes a situation where two or more threads are blocked forever, waiting for each other. Here's an example.

Alphonse and Gaston are friends, and great believers in courtesy. A strict rule of courtesy is that when you bow to a friend, you must remain bowed until your friend has a chance to return the bow. Unfortunately, this rule does not account for the possibility that two friends might bow to each other at the same time. This example application, Deadlock, models this possibility:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class Deadlock {
    static class Friend {
        private final String name;
        public Friend(String name) {
            this.name = name;
        }
        public String getName() {
            return this.name;
        }
        public synchronized void bow(Friend bower) {
            System.out.format("%s: %s has bowed to me!%n",
                    this.name, bower.getName());
            bower.bowBack(this);
        }
        public synchronized void bowBack(Friend bower) {
            System.out.format("%s: %s has bowed back to me!%n",
                    this.name, bower.getName());
        }
    }

    public static void main(String[] args) {
        final Friend alphonse = new Friend("Alphonse");
        final Friend gaston = new Friend("Gaston");
        new Thread(new Runnable() {
            public void run() { alphonse.bow(gaston); }
        }).start();
        new Thread(new Runnable() {
            public void run() { gaston.bow(alphonse); }
        }).start();
    }
}
When Deadlock runs, it's extremely likely that both threads will block when they attempt to invoke bowBack. Neither block will ever end, because each thread is waiting for the other to exit bow.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Liveness
Next page: Starvation and Livelock


Starvation and Livelock (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: Liveness
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Starvation and Livelock
Starvation and livelock are much less common a problem than deadlock, but are still problems that every designer of concurrent software is likely to encounter.

Starvation

Starvation describes a situation where a thread is unable to gain regular access to shared resources and is unable to make progress. This happens when shared resources are made unavailable for long periods by "greedy" threads. For example, suppose an object provides a synchronized method that often takes a long time to return. If one thread invokes this method frequently, other threads that also need frequent synchronized access to the same object will often be blocked.

Livelock

A thread often acts in response to the action of another thread. If the other thread's action is also a response to the action of another thread, then livelock may result. As with deadlock, livelocked threads are unable to make further progress. However, the threads are not blocked — they are simply too busy responding to each other to resume work. This is comparable to two people attempting to pass each other in a corridor: Alphonse moves to his left to let Gaston pass, while Gaston moves to his right to let Alphonse pass. Seeing that they are still blocking each other, Alphone moves to his right, while Gaston moves to his left. They're still blocking each other, so...
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Deadlock
Next page: Guarded Blocks


Guarded Blocks (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Guarded Blocks
Threads often have to coordinate their actions. The most common coordination idiom is the guarded block. Such a block begins by polling a condition that must be true before the block can proceed. There are a number of steps to follow in order to do this correctly.

Suppose, for example guardedJoy is a method that must not proceed until a shared variable joy has been set by another thread. Such a method could, in theory, simply loop until the condition is satisfied, but that loop is wasteful, since it executes continuously while waiting.

public void guardedJoy() {
    //Simple loop guard. Wastes processor time. Don't do this!
    while(!joy) {}
    System.out.println("Joy has been achieved!");
}
A more efficient guard invokes Object.wait to suspend the current thread. The invocation of wait does not return until another thread has issued a notification that some special event may have occurred — though not necessarily the event this thread is waiting for:
public synchronized guardedJoy() {
    //This guard only loops once for each special event, which may not
    //be the event we're waiting for.
    while(!joy) {
        try {
            wait();
        } catch (InterruptedException e) {}
    }
    System.out.println("Joy and efficiency have been achieved!");
}
Note: Always invoke wait inside a loop that tests for the condition being waited for. Don't assume that the interrupt was for the particular condition you were waiting for, or that the condition is still true.
Like many methods that suspend execution, wait can throw InterruptedException. In this example, we can just ignore that exception — we only care about the value of joy.

Why is this version of guardedJoy synchronized? Suppose d is the object we're using to invoke wait. When a thread invokes d.wait, it must own the intrinsic lock for d — otherwise an error is thrown. Invoking wait inside a synchronized method is a simple way to acquire the intrinsic lock.

When wait is invoked, the thread releases the lock and suspends execution. At some future time, another thread will acquire the same lock and invoke Object.notifyAll, informing all threads waiting on that lock that something important has happened:

public synchronized notifyJoy() {
    joy = true;
    notifyAll();
}
Some time after the second thread has released the lock, the first thread reacquires the lock and resumes by returning from the invocation of wait.
Note: There is a second notification method, notify, which wakes up a single thread. Because notify doesn't allow you to specify the thread that is woken up, it is useful only in massively parallel applications — that is, programs with a large number of threads, all doing similar chores. In such an application, you don't care which thread gets woken up.

Let's use guarded blocks to create a Producer-Consumer application. This kind of application shares data between two threads: the producer, that creates the data, and the consumer, that does something with it. The two threads communicate using a shared object. Coordination is essential: the consumer thread must not attempt to retrieve the data before the producer thread has delivered it, and the producer thread must not attempt to deliver new data if the consumer hasn't retrieved the old data.

In this example, the data is a series of text messages, which are shared through an object of type Drop:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class Drop {
    //Message sent from producer to consumer.
    private String message;
    //True if consumer should wait for producer to send message, false
    //if producer should wait for consumer to retrieve message.
    private boolean empty = true;

    public synchronized String take() {
        //Wait until message is available.
        while (empty) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        //Toggle status.
        empty = true;
        //Notify producer that status has changed.
        notifyAll();
        return message;
    }

    public synchronized void put(String message) {
        //Wait until message has been retrieved.
        while (!empty) {
            try {
                wait();
            } catch (InterruptedException e) {}
        }
        //Toggle status.
        empty = false;
        //Store message.
        this.message = message;
        //Notify consumer that status has changed.
        notifyAll();
    }
}
The producer thread, defined in Producer, sends a series of familiar messages. The string "DONE" indicates that all messages have been sent. To simulate the unpredictable nature of real-world applications, the producer thread pauses for random intervals between messages.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.Random;

public class Producer implements Runnable {
    private Drop drop;

    public Producer(Drop drop) {
        this.drop = drop;
    }

    public void run() {
        String importantInfo[] = {
            "Mares eat oats",
            "Does eat oats",
            "Little lambs eat ivy",
            "A kid will eat ivy too"
        };
        Random random = new Random();

        for (int i = 0; i < importantInfo.length; i++) {
            drop.put(importantInfo[i]);
            try {
                Thread.sleep(random.nextInt(5000));
            } catch (InterruptedException e) {}
        }
        drop.put("DONE");
    }
}
The consumer thread, defined in Consumer, simply retrieves the messages and prints them out, until it retrieves the "DONE" string. This thread also pauses for random intervals.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.Random;

public class Consumer implements Runnable {
    private Drop drop;

    public Consumer(Drop drop) {
        this.drop = drop;
    }

    public void run() {
        Random random = new Random();
        for (String message = drop.take(); ! message.equals("DONE");
                message = drop.take()) {
            System.out.format("MESSAGE RECEIVED: %s%n", message);
            try {
                Thread.sleep(random.nextInt(5000));
            } catch (InterruptedException e) {}
        }
    }
}
Finally, here is the main thread, defined in ProducerConsumerExample, that launches the producer and consumer threads.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class ProducerConsumerExample {
    public static void main(String[] args) {
        Drop drop = new Drop();
        (new Thread(new Producer(drop))).start();
        (new Thread(new Consumer(drop))).start();
    }
}
Note: The Drop class was written in order to demonstrate guarded blocks. To avoid re-inventing the wheel, examine the existing data structures in the Java Collections Framework before trying to code your own data-sharing objects. For more information, refer to the Questions and Exercises section.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Starvation and Livelock
Next page: Immutable Objects


Immutable Objects (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Immutable Objects
An object is considered immutable if its state cannot change after it is constructed. Maximum reliance on immutable objects is widely accepted as a sound strategy for creating simple, reliable code.

Immutable objects are particularly useful in concurrent applications. Since they cannot change state, they cannot be corrupted by thread interference or observed in an inconsistent state.

Programmers are often reluctant to employ immutable objects, because they worry about the cost of creating a new object as opposed to updating an object in place. The impact of object creation is often overestimated, and can be offset by some of the efficiencies associated with immutable objects. These include decreased overhead due to garbage collection, and the elimination of code needed to protect mutable objects from corruption.

The following subsections take a class whose instances are mutable and derives a class with immutable instances from it. In so doing, they give general rules for this kind of conversion and demonstrate some of the advantages of immutable objects.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Guarded Blocks
Next page: A Synchronized Class Example


A Synchronized Class Example (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: Immutable Objects
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
A Synchronized Class Example
The class, SynchronizedRGB, defines objects that represent colors. Each object represents the color as three integers that stand for primary color values and a string that gives the name of the color.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class SynchronizedRGB {

    //Values must be between 0 and 255.
    private int red;
    private int green;
    private int blue;
    private String name;

    private void check(int red, int green, int blue) {
        if (red < 0 || red > 255
                || green < 0 || green > 255
                || blue < 0 || blue > 255) {
            throw new IllegalArgumentException();
        }
    }

    public SynchronizedRGB(int red, int green, int blue, String name) {
        check(red, green, blue);
        this.red = red;
        this.green = green;
        this.blue = blue;
        this.name = name;
    }

    public void set(int red, int green, int blue, String name) {
        check(red, green, blue);
        synchronized (this) {
            this.red = red;
            this.green = green;
            this.blue = blue;
            this.name = name;
        }
    }

    public synchronized int getRGB() {
        return ((red << 16) | (green << 8) | blue);
    }

    public synchronized String getName() {
        return name;
    }

    public synchronized void invert() {
        red = 255 - red;
        green = 255 - green;
        blue = 255 - blue;
        name = "Inverse of " + name;
    }
}
SynchronizedRGB must be used carefully to avoid being seen in an inconsistent state. Suppose, for example, a thread executes the following code:
SynchronizedRGB color = new SynchronizedRGB(0, 0, 0, "Pitch Black");
...
int myColorInt = color.getRGB();      //Statement 1
String myColorName = color.getName(); //Statement 2
If another thread invokes color.set after Statement 1 but before Statement 2, the value of myColorInt won't match the value of myColorName. To avoid this outcome, the two statements must be bound together:
synchronized (color) {
    int myColorInt = color.getRGB();
    String myColorName = color.getName();
}
This kind of inconsistency is only possible for mutable objects — it will not be an issue for the immutable version of SynchronizedRGB.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Immutable Objects
Next page: A Strategy for Defining Immutable Objects


A Strategy for Defining Immutable Objects (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: Immutable Objects
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
A Strategy for Defining Immutable Objects
The following rules define a simple strategy for creating immutable objects. Not all classes documented as "immutable" follow these rules. This does not necessarily mean the creators of these classes were sloppy — they may have good reason for believing that instances of their classes never change after construction. However, such strategies require sophisticated analysis and are not for beginners.
  1. Don't provide "setter" methods — methods that modify fields or objects referred to by fields.
  2. Make all fields final and private.
  3. Don't allow subclasses to override methods. The simplest way to do this is to declare the class as final. A more sophisticated approach is to make the constructor private and construct instances in factory methods.
  4. If the instance fields include references to mutable objects, don't allow those objects to be changed:
    • Don't provide methods that modify the mutable objects.
    • Don't share references to the mutable objects. Never store references to external, mutable objects passed to the constructor; if necessary, create copies, and store references to the copies. Similarly, create copies of your internal mutable objects when necessary to avoid returning the originals in your methods.

Applying this strategy to SynchronizedRGB results in the following steps:

  1. There are two setter methods in this class. The first one, set, arbitrarily transforms the object, and has no place in an immutable version of the class. The second one, invert, can be adapted by having it create a new object instead of modifying the existing one.
  2. All fields are already private; they are further qualified as final.
  3. The class itself is declared final.
  4. Only one field refers to an object, and that object is itself immutable. Therefore, no safeguards against changing the state of "contained" mutable objects are necessary.
After these changes, we have ImmutableRGB:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

final public class ImmutableRGB {

    //Values must be between 0 and 255.
    final private int red;
    final private int green;
    final private int blue;
    final private String name;

    private void check(int red, int green, int blue) {
        if (red < 0 || red > 255
                || green < 0 || green > 255
                || blue < 0 || blue > 255) {
            throw new IllegalArgumentException();
        }
    }

    public ImmutableRGB(int red, int green, int blue, String name) {
        check(red, green, blue);
        this.red = red;
        this.green = green;
        this.blue = blue;
        this.name = name;
    }

    public int getRGB() {
        return ((red << 16) | (green << 8) | blue);
    }

    public String getName() {
        return name;
    }

    public ImmutableRGB invert() {
        return new ImmutableRGB(255 - red, 255 - green, 255 - blue,
                "Inverse of " + name);
    }
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: A Synchronized Class Example
Next page: High Level Concurrency Objects


High Level Concurrency Objects (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
High Level Concurrency Objects
So far, this lesson has focused on the low-level APIs that have been part of the Java platform from the very beginning. These APIs are adequate for very basic tasks, but higher-level building blocks are needed for more advanced tasks. This is especially true for massively concurrent applications that fully exploit today's multiprocessor and multi-core systems.

In this section we'll look at some of the high-level concurrency features introduced with version 5.0 of the Java platform. Most of these features are implemented in the new java.util.concurrent packages. There are also new concurrent data structures in the Java Collections Framework.

  • Lock objects support locking idioms that simplify many concurrent applications.
  • Executors define a high-level API for launching and managing threads. Executor implementations provided by java.util.concurrent provide thread pool management suitable for large-scale applications.
  • Concurrent collections make it easier to manage large collections of data, and can greatly reduce the need for synchronization.
  • Atomic variables have features that minimize synchronization and help avoid memory consistency errors.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: A Strategy for Defining Immutable Objects
Next page: Lock Objects


Lock Objects (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: High Level Concurrency Objects
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Lock Objects
Synchronized code relies on a simple kind of reentrant lock. This kind of lock is easy to use, but has many limitations. More sophisticated locking idioms are supported by the java.util.concurrent.locks package. We won't examine this package in detail, but instead will focus on its most basic interface, Lock.

Lock objects work very much like the implicit locks used by synchronized code. As with implicit locks, only one thread can own a Lock object at a time. Lock objects also support a wait/notify mechanism, through their associated Condition objects.

The biggest advantage of Lock objects over implicit locks is their ability to back out of an attempt to acquire a lock. The tryLock method backs out if the lock is not available immediately or before a timeout expires (if specified). The lockInterruptibly method backs out if another thread sends an interrupt before the lock is acquired.

Let's use Lock objects to solve the deadlock problem we saw in Liveness. Alphonse and Gaston have trained themselves to notice when a friend is about to bow. We model this improvement by requiring that our Friend objects must acquire locks for both participants before proceeding with the bow. Here is the source code for the improved model, Safelock. To demonstrate the versatility of this idiom, we assume that Alphonse and Gaston are so infatuated with their newfound ability to bow safely that they can't stop bowing to each other:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.Random;

public class Safelock {
    static class Friend {
        private final String name;
        private final Lock lock = new ReentrantLock();

        public Friend(String name) {
            this.name = name;
        }

        public String getName() {
            return this.name;
        }

        public boolean impendingBow(Friend bower) {
            Boolean myLock = false;
            Boolean yourLock = false;
            try {
                myLock = lock.tryLock();
                yourLock = bower.lock.tryLock();
            } finally {
                if (! (myLock && yourLock)) {
                    if (myLock) {
                        lock.unlock();
                    }
                    if (yourLock) {
                        bower.lock.unlock();
                    }
                }
            }
            return myLock && yourLock;
        }

        public void bow(Friend bower) {
            if (impendingBow(bower)) {
                try {
                    System.out.format("%s: %s has bowed to me!%n",
                            this.name, bower.getName());
                    bower.bowBack(this);
                } finally {
                    lock.unlock();
                    bower.lock.unlock();
                }
            } else {
                System.out.format("%s: %s started to bow to me, but" +
                        " saw that I was already bowing to him.%n",
                        this.name, bower.getName());
            }
        }

        public void bowBack(Friend bower) {
            System.out.format("%s: %s has bowed back to me!%n",
                    this.name, bower.getName());
        }
    }

    static class BowLoop implements Runnable {
        private Friend bower;
        private Friend bowee;

        public BowLoop(Friend bower, Friend bowee) {
            this.bower = bower;
            this.bowee = bowee;
        }

        public void run() {
            Random random = new Random();
            for (;;) {
                try {
                    Thread.sleep(random.nextInt(10));
                } catch (InterruptedException e) {}
                bowee.bow(bower);
            }
        }
    }

    public static void main(String[] args) {
        final Friend alphonse = new Friend("Alphonse");
        final Friend gaston = new Friend("Gaston");
        new Thread(new BowLoop(alphonse, gaston)).start();
        new Thread(new BowLoop(gaston, alphonse)).start();
    }
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: High Level Concurrency Objects
Next page: Executors


Executors (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: High Level Concurrency Objects
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Executors
In all of the previous examples, there's a close connection between the task being done by a new thread, as defined by its Runnable object, and the thread itself, as defined by a Thread object. This works well for small applications, but in large-scale applications, it makes sense to separate thread management and creation from the rest of the application. Objects that encapsulate these functions are known as executors. The following subsections describe executors in detail.
  • Executor Interfaces define the three executor object types.
  • Thread Pools are the most common kind of executor implementation.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Lock Objects
Next page: Executor Interfaces


Executor Interfaces (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: High Level Concurrency Objects
Subsection: Executors
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Executor Interfaces
The java.util.concurrent package defines three executor interfaces:
  • Executor, a simple interface that supports launching new tasks.
  • ExecutorService, a subinterface of Executor, which adds features that help manage the lifecycle, both of the individual tasks and of the executor itself.
  • ScheduledExecutorService, a subinterface of ExecutorService, supports future and/or periodic execution of tasks.
Typically, variables that refer to executor objects are declared as one of these three interface types, not with an executor class type.

The Executor Interface

The Executor interface provides a single method, execute, designed to be a drop-in replacement for a common thread-creation idiom. If r is a Runnable object, and e is an Executor object you can replace
(new Thread(r)).start();
with
e.execute(r);
However, the definition of execute is less specific. The low-level idiom creates a new thread and launches it immediately. Depending on the Executor implementation, execute may do the same thing, but is more likely to use an existing worker thread to run r, or to place r in a queue to wait for a worker thread to become available. (We'll describe worker threads in the section on Thread Pools.)

The executor implementations in java.util.concurrent are designed to make full use of the more advanced ExecutorService and ScheduledExecutorService interfaces, although they also work with the base Executor interface.

The ExecutorService Interface

The ExecutorService interface supplements execute with a similar, but more versatile submit method. Like execute, submit accepts Runnable objects, but also accepts Callable objects, which allow the task to return a value. The submit method returns a Future object, which is used to retrieve the Callable return value and to manage the status of both Callable and Runnable tasks.

ExecutorService also provides methods for submitting large collections of Callable objects. Finally, ExecutorService provides a number of methods for managing the shutdown of the executor. To support immediate shutdown, tasks should handle interrupts correctly.

The ScheduledExecutorService Interface

The ScheduledExecutorService interface supplements the methods of its parent ExecutorService with schedule, which executes a Runnable or Callable task after a specified delay. In addition, the interface defines scheduleAtFixedRate and scheduleWithFixedDelay, which executes specified tasks repeatedly, at defined intervals.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Executors
Next page: Thread Pools


Thread Pools (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: High Level Concurrency Objects
Subsection: Executors
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Thread Pools
Most of the executor implementations in java.util.concurrent use thread pools, which consist of worker threads. This kind of thread exists separately from the Runnable and Callable tasks it executes and is often used to execute multiple tasks.

Using worker threads minimizes the overhead due to thread creation. Thread objects use a significant amount of memory, and in a large-scale application, allocating and deallocating many thread objects creates a significant memory management overhead.

One common type of thread pool is the fixed thread pool. This type of pool always has a specified number of threads running; if a thread is somehow terminated while it is still in use, it is automatically replaced with a new thread. Tasks are submitted to the pool via an internal queue, which holds extra tasks whenever there are more active tasks than threads.

An important advantage of the fixed thread pool is that applications using it degrade gracefully. To understand this, consider a web server application where each HTTP request is handled by a separate thread. If the application simply creates a new thread for every new HTTP request, and the system receives more requests than it can handle immediately, the application will suddenly stop responding to all requests when the overhead of all those threads exceed the capacity of the system. With a limit on the number of the threads that can be created, the application will not be servicing HTTP requests as quickly as they come in, but it will be servicing them as quickly as the system can sustain.

A simple way to create an executor that uses a fixed thread pool is to invoke the newFixedThreadPool factory method in java.util.concurrent.Executors This class also provides the following factory methods:

  • The newCachedThreadPool method creates an executor with an expandable thread pool. This executor is suitable for applications that launch many short-lived tasks.
  • The newSingleThreadExecutor method creates an executor that executes a single task at a time.
  • Several factory methods are ScheduledExecutorService versions of the above executors.
If none of the executors provided by the above factory methods meet your needs, constructing instances of java.util.concurrent.ThreadPoolExecutor or java.util.concurrent.ScheduledThreadPoolExecutor will give you additional options.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Executor Interfaces
Next page: Concurrent Collections


Concurrent Collections (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: High Level Concurrency Objects
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Concurrent Collections
The java.util.concurrent package includes a number of additions to the Java Collections Framework. These are most easily categorized by the collection interfaces provided:
  • BlockingQueue defines a first-in-first-out data structure that blocks or times out when you attempt to add to a full queue, or retrieve from an empty queue.
  • ConcurrentMap is a subinterface of java.util.Map that defines useful atomic operations. These operations remove or replace a key-value pair only if the key is present, or add a key-value pair only if the key is absent. Making these operations atomic helps avoid synchronization. The standard general-purpose implementation of ConcurrentMap is ConcurrentHashMap, which is a concurrent analog of HashMap.
  • ConcurrentNavigableMap is a subinterface of ConcurrentMap that supports approximate matches. The standard general-purpose implementation of ConcurrentNavigableMap is ConcurrentSkipListMap, which is a concurrent analog of TreeMap.

All of these collections help avoid Memory Consistency Errors by defining a happens-before relationship between an operation that adds an object to the collection with subsequent operations that access or remove that object.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Thread Pools
Next page: Atomic Variables


Atomic Variables (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Section: High Level Concurrency Objects
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Atomic Variables
The java.util.concurrent.atomic package defines classes that support atomic operations on single variables. All classes have get and set methods that work like reads and writes on volatile variables. That is, a set has a happens-before relationship with any subsequent get on the same variable. The atomic compareAndSet method also has these memory consistency features, as do the simple atomic arithmetic methods that apply to integer atomic variables.

To see how this package might be used, let's return to the Counter class we originally used to demonstrate thread interference:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class Counter {
    private int c = 0;

    public void increment() {
        c++;
    }

    public void decrement() {
        c--;
    }

    public int value() {
        return c;
    }

}
One way to make Counter safe from thread interference is to make its methods synchronized, as in SynchronizedCounter:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class SynchronizedCounter {
    private int c = 0;

    public synchronized void increment() {
        c++;
    }

    public synchronized void decrement() {
        c--;
    }

    public synchronized int value() {
        return c;
    }

}
For this simple class, synchronization is an acceptable solution. But for a more complicated class, we might want to avoid the liveness impact of unnecessary synchronization. Replacing the int field with an AtomicInteger allows us to prevent thread interference without resorting to synchronization, as in AtomicCounter:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.concurrent.atomic.AtomicInteger;

class AtomicCounter {
    private AtomicInteger c = new AtomicInteger(0);

    public void increment() {
        c.incrementAndGet();
    }

    public void decrement() {
        c.decrementAndGet();
    }

    public int value() {
        return c.get();
    }

}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Concurrent Collections
Next page: For Further Reading


For Further Reading (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
For Further Reading
  • Concurrent Programming in Java: Design Principles and Pattern (2nd Edition) by Doug Lea. A comprehensive work by a leading expert, who's also the architect of the Java platform's concurrency framework.
  • Java Concurrency in Practice by Brian Goetz, Tim Peierls, Joshua Bloch, Joseph Bowbeer, David Holmes, and Doug Lea. A practical guide designed to be accessible to the novice.
  • Effective Java Programming Language Guide by Joshua Bloch. Though this is a general programming guide, its chapter on threads contains essential "best practices" for concurrent programming.
  • Concurrency: State Models & Java Programs (2nd Edition), by Jeff Magee and Jeff Kramer. An introduction to concurrent programming through a combination of modeling and practical examples.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Atomic Variables
Next page: Questions and Exercises: Concurrency


Questions and Exercises: Concurrency (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises
Home Page > Essential Classes > Concurrency
« Previous • Trail • Next »
Questions and Exercises: Concurrency

Questions

  1. Can you pass a Thread object to Executor.execute? Would such an invocation make sense?

Exercises

  1. Compile and run BadThreads.java:
    /*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class BadThreads {

    static String message;

    private static class CorrectorThread extends Thread {

        public void run() {
            try {
                sleep(1000);
            } catch (InterruptedException e) {}
            //Key statement 1:
            message = "Mares do eat oats.";
        }
    }

    public static void main(String args[]) throws InterruptedException {
        (new CorrectorThread()).start();
        message = "Mares do not eat oats.";
        Thread.sleep(2000);
        //Key statement 2:
        System.out.println(message);
    }
}

    The application should print out "Mares do eat oats." Is it guaranteed to always do this? If not, why not? Would it help to change the parameters of the two invocations of Sleep? Describe two ways to change the program to enforce such a guarantee.

  2. Modify the producer-consumer example in Guarded Blocks to use a standard library class instead of the Drop class.

Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: For Further Reading
Next page: The Platform Environment


Lesson: The Platform Environment (The Java™ Tutorials > Essential Classes)

The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises
Trail: Essential Classes
Home Page > Essential Classes
« Previous • Trail • Next »
Lesson: The Platform Environment
An application runs in a platform environment, defined by the underlying operating system, the Java virtual machine, the class libraries, and various configuration data supplied when the application is launched. This lesson describes some of the APIs an application uses to examine and configure its platform environment. The lesson consists of three sections:
  • Configuration Utilities describes APIs used to access configuration data supplied when the application is deployed, or by the application's user.
  • System Utilities describes miscellaneous APIs defined in the System and Runtime classes.
  • PATH and CLASSPATH describes environment variables used to configure JDK development tools and other applications.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Configuration Utilities


Configuration Utilities (The Java™ Tutorials > Essential Classes > The Platform Environment)

Trail: Essential Classes
Lesson: The Platform Environment
The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises
Home Page > Essential Classes > The Platform Environment
« Previous • Trail • Next »
Configuration Utilities
This section describes some of the configuration utilities that help an application access its startup context.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Platform Environment
Next page: Properties


Properties (The Java™ Tutorials > Essential Classes > The Platform Environment)

Trail: Essential Classes
Lesson: The Platform Environment
Section: Configuration Utilities
The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises
Home Page > Essential Classes > The Platform Environment
« Previous • Trail • Next »
Properties
Properties are configuration values managed as key/value pairs. In each pair, the key and value are both String values. The key identifies, and is used to retrieve, the value, much as a variable name is used to retrieve the variable's value. For example, an application capable of downloading files might use a property named "download.lastDirectory" to keep track of the directory used for the last download.

To manage properties, create instances of java.util.Properties. This class provides methods for the following:

  • loading key/value pairs into a Properties object from a stream,
  • retrieving a value from its key,
  • listing the keys and their values,
  • enumerating over the keys, and
  • saving the properties to a stream.

For an introduction to streams, refer to the section I/O Streams in the Basic I/O lesson.

Properties extends java.util.Hashtable. Some of the methods inherited from Hashtable support the following actions:

  • testing to see if a particular key or value is in the Properties object,
  • getting the current number of key/value pairs,
  • removing a key and its value,
  • adding a key/value pair to the Properties list,
  • enumerating over the values or the keys,
  • retrieving a value by its key, and
  • finding out if the Properties object is empty.

Security Considerations: Access to properties is subject to approval by the current security manager. The example code segments in this section are assumed to be in standalone applications, which, by default, have no security manager. The same code in an applet may not work depending on the browser or viewer in which it is running. See Getting System Properties in the Applets trail for information about security restrictions on applets.
The System class maintains a Properties object that defines the configuration of the current working environment. For more about these properties, see System Properties. The remainder of this section explains how to use properties to manage application configuration.

Properties in the Application Life Cycle

The following figure illustrates how a typical application might manage its configuration data with a Properties object over the course of its execution.

Starting Up
The actions given in the first three boxes occur when the application is starting up. First, the application loads the default properties from a well-known location into a Properties object. Normally, the default properties are stored in a file on disk along with the .class and other resource files for the application.

Next, the application creates another Properties object and loads the properties that were saved from the last time the application was run. Many applications store properties on a per-user basis, so the properties loaded in this step are usually in a specific file in a particular directory maintained by this application in the user's home directory. Finally, the application uses the default and remembered properties to initialize itself.

The key here is consistency. The application must always load and save properties to the same location so that it can find them the next time it's executed.

Running
During the execution of the application, the user may change some settings, perhaps in a Preferences window, and the Properties object is updated to reflect these changes. If the users changes are to be remembered in future sessions, they must be saved.
Exiting
Upon exiting, the application saves the properties to its well-known location, to be loaded again when the application is next started up.

Setting Up the Properties Object

The following Java code performs the first two steps described in the previous section: loading the default properties and loading the remembered properties:
. . .
// create and load default properties
Properties defaultProps = new Properties();
FileInputStream in = new FileInputStream("defaultProperties");
defaultProps.load(in);
in.close();

// create application properties with default
Properties applicationProps = new Properties(defaultProps);

// now load properties from last invocation
in = new FileInputStream("appProperties");
applicationProps.load(in);
in.close();
. . .
First, the application sets up a default Properties object. This object contains the set of properties to use if values are not explicitly set elsewhere. Then the load method reads the default values from a file on disk named defaultProperties.

Next, the application uses a different constructor to create a second Properties object, applicationProps, whose default values are contained in defaultProps. The defaults come into play when a property is being retrieved. If the property can't be found in applicationProps, then its default list is searched.

Finally, the code loads a set of properties into applicationProps from a file named appProperties. The properties in this file are those that were saved from the application the last time it was invoked, as explained in the next section.

Saving Properties

The following example writes out the application properties from the previous example using Properties.store. The default properties don't need to be saved each time because they never change.
FileOutputStream out = new FileOutputStream("appProperties");
applicationProps.store(out, "---No Comment---");
out.close();
The store method needs a stream to write to, as well as a string that it uses as a comment at the top of the output.

Getting Property Information

Once the application has set up its Properties object, the application can query the object for information about various keys and values that it contains. An application gets information from a Properties object after start up so that it can initialize itself based on choices made by the user. The Properties class has several methods for getting property information:
contains(Object value)
containsKey(Object key)
Returns true if the value or the key is in the Properties object. Properties inherits these methods from Hashtable. Thus they accept Object arguments, but only String values should be used.
getProperty(String key)
getProperty(String key, String default)
Returns the value for the specified property. The second version provides for a default value. If the key is not found, the default is returned.
list(PrintStream s)
list(PrintWriter w)
Writes all of the properties to the specified stream or writer. This is useful for debugging.
elements()
keys()
propertyNames()
Returns an Enumeration containing the keys or values (as indicated by the method name) contained in the Properties object. The keys method only returns the keys for the object itself; the propertyNames method returns the keys for default properties as well.
stringPropertyNames()
Like propertyNames, but returns a Set<String>, and only returns names of properties where both key and value are strings. Note that the Set object is not backed by the Properties object, so changes in one do not affect the other.
size()
Returns the current number of key/value pairs.

Setting Properties

A user's interaction with an application during its execution may impact property settings. These changes should be reflected in the Properties object so that they are saved when the application exits (and calls the store method). The following methods change the properties in a Properties object:
setProperty(String key, String value)
Puts the key/value pair in the Properties object.
remove(Object key)
Removes the key/value pair associated with key.
Note: Some of the methods described above are defined in Hashtable, and thus accept key and value argument types other than String. Always use Strings for keys and values, even if the method allows other types. Also do not invoke Hashtable.set or Hastable.setAll on Properties objects; always use Properties.setProperty.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Configuration Utilities
Next page: Command-Line Arguments


Command-Line Arguments (The Java™ Tutorials > Essential Classes > The Platform Environment)

Trail: Essential Classes
Lesson: The Platform Environment
Section: Configuration Utilities
The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises
Home Page > Essential Classes > The Platform Environment
« Previous • Trail • Next »
Command-Line Arguments
A Java application can accept any number of arguments from the command line. This allows the user to specify configuration information when the application is launched.

The user enters command-line arguments when invoking the application and specifies them after the name of the class to be run. For example, suppose a Java application called Sort sorts lines in a file. To sort the data in a file named friends.txt, a user would enter:

java Sort friends.txt
When an application is launched, the runtime system passes the command-line arguments to the application's main method via an array of Strings. In the previous example, the command-line arguments passed to the Sort application in an array that contains a single String: "friends.txt".

Echoing Command-Line Arguments

The Echo example displays each of its command-line arguments on a line by itself:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class Echo {
    public static void main (String[] args) {
        for (String s: args) {
            System.out.println(s);
        }
    }
}
The following example shows how a user might run Echo. User input is in italics.
java Echo Drink Hot Java
Drink
Hot
Java
Note that the application displays each word — Drink, Hot, and Java — on a line by itself. This is because the space character separates command-line arguments. To have Drink, Hot, and Java interpreted as a single argument, the user would join them by enclosing them within quotation marks.
java Echo "Drink Hot Java"
Drink Hot Java

Parsing Numeric Command-Line Arguments

If an application needs to support a numeric command-line argument, it must convert a String argument that represents a number, such as "34", to a numeric value. Here is a code snippet that converts a command-line argument to an int:
int firstArg;
if (args.length > 0) {
    try {
        firstArg = Integer.parseInt(args[0]);
    } catch (NumberFormatException e) {
        System.err.println("Argument must be an integer");
        System.exit(1);
    }
}
parseInt throws a NumberFormatException if the format of args[0] isn't valid. All of the Number classes — Integer, Float, Double, and so on — have parseXXX methods that convert a String representing a number to an object of their type.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Properties
Next page: Environment Variables


Environment Variables (The Java™ Tutorials > Essential Classes > The Platform Environment)

Trail: Essential Classes
Lesson: The Platform Environment
Section: Configuration Utilities
The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises
Home Page > Essential Classes > The Platform Environment
« Previous • Trail • Next »
Environment Variables
Many operating systems use environment variables to pass configuration information to applications. Like properties in the Java platform, environment variables are key/value pairs, where both the key and the value are strings. The conventions for setting and using environment variables vary between operating systems, and also between command line interpreters. To learn how to pass environment variables to applications on your system, refer to your system documentation.

Querying Environment Variables

On the Java platform, an application uses System.getEnv to retrieve environment variable values. Without an argument, getEnv returns a read-only instance of java.util.Map, where the map keys are the environment variable names, and the map values are the environment variable values. This is demonstrated in the EnvMap example:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.Map;

public class EnvMap {
    public static void main (String[] args) {
        Map<String, String> env = System.getenv();
        for (String envName : env.keySet()) {
            System.out.format("%s=%s%n", envName, env.get(envName));
        }
    }
}
With a String argument, getEnv returns the value of the specified variable. If the variable is not defined, getEnv returns null. The Env example uses getEnv this way to query specific environment variables, specified on the command line:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class Env {
    public static void main (String[] args) {
        for (String env: args) {
            String value = System.getenv(env);
            if (value != null) {
                System.out.format("%s=%s%n", env, value);
            } else {
                System.out.format("%s is not assigned.%n", env);
            }
        }
    }
}

Passing Environment Variables to New Processes

When a Java application uses a ProcessBuilder object to create a new process, the default set of environment variables passed to the new process is the same set provided to the application's virtual machine process. The application can change this set using ProcessBuilder.environment.

Platform Dependency Issues

There are many subtle differences between the way environment variables are implemented on different systems. For example, Windows ignores case in environment variable names, while UNIX does not. The way environment variables are used also varies. For example, Windows provides the user name in an environment variable called USERNAME, while UNIX implementations might provide the user name in USER, LOGNAME, or both.

To maximize portability, never refer to an environment variable when the same value is available in a system property. For example, if the operating system provides a user name, it will always be available in the system property user.name.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Command-Line Arguments
Next page: Other Configuration Utilities


Other Configuration Utilities (The Java™ Tutorials > Essential Classes > The Platform Environment)

Trail: Essential Classes
Lesson: The Platform Environment
Section: Configuration Utilities
The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises
Home Page > Essential Classes > The Platform Environment
« Previous • Trail • Next »
Other Configuration Utilities
Here is a summary of some other configuration utilities.

The Preferences API allows applications to store and retrieve configuration data in an implementation-dependent backing store. Asynchronous updates are supported, and the same set of preferences can be safely updated by multiple threads and even multiple applications. For more information, refer to the Preferences API Guide.

An application deployed in a JAR archive uses a manifest to describe the contents of the archive. For more information, refer to the Packaging Programs in JAR Files lesson.

The configuration of a Java Web Start application is contained in a JNLP file. For more information, refer to the Java Web Start lesson.

The configuration of a Java Plug-in applet is partially determined by the HTML tags used to embed the applet in the web page. Depending on the applet and the browser, these tags can include <applet>, <object>, <embed>, and <param>. For more information, refer to the Applets lesson.

The class java.util.ServiceLoader provides a simple service provider facility. A service provider is an implementation of a service — a well-known set of interfaces and (usually abstract) classes. The classes in a service provider typically implement the interfaces and subclass the classes defined in the service. Service providers can be installed as extensions (see The Extension Mechanism). Providers can also be made available by adding them to the class path or by some other platform-specific means.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Environment Variables
Next page: System Utilities


System Utilities (The Java™ Tutorials > Essential Classes > The Platform Environment)

Trail: Essential Classes
Lesson: The Platform Environment
The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises
Home Page > Essential Classes > The Platform Environment
« Previous • Trail • Next »
System Utilities
The System class implements a number of system utilities. Some of these have already been covered in the previous section on Configuration Utilities. This section covers some of the other system utilities.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Other Configuration Utilities
Next page: Command-Line I/O Objects


Command-Line I/O Objects (The Java™ Tutorials > Essential Classes > The Platform Environment)

Trail: Essential Classes
Lesson: The Platform Environment
Section: System Utilities
The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises
Home Page > Essential Classes > The Platform Environment
« Previous • Trail • Next »
Command-Line I/O Objects
System provides several predefined I/O objects that are useful in a Java application that is meant to be launched from the command line. These implement the Standard I/O streams provided by most operating systems, and also a console object that is useful for entering passwords. For more information, refer to I/O from the Command Line in the Basic I/O lesson.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: System Utilities
Next page: System Properties


System Properties (The Java™ Tutorials > Essential Classes > The Platform Environment)

Trail: Essential Classes
Lesson: The Platform Environment
Section: System Utilities
The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises
Home Page > Essential Classes > The Platform Environment
« Previous • Trail • Next »
System Properties
In Properties, we examined the way an application can use Properties objects to maintain its configuration. The Java platform itself uses a Properties object to maintain its own configuration. The System class maintains a Properties object that describes the configuration of the current working environment. System properties include information about the current user, the current version of the Java runtime, and the character used to separate components of a file path name.

The following table describes some of the most important system properties

Key | Meaning
"file.separator" | Character that separates components of a file path. This is "/" on UNIX and "\" on Windows.
"java.class.path" | Path used to find directories and JAR archives containing class files. Elements of the class path are separated by a platform-specific character specified in the path.separator property.
"java.home" | Installation directory for Java Runtime Environment (JRE)
"java.vendor" | JRE vendor name
"java.vendor.url" | JRE vender URL
"java.version" | JRE version number
"line.separator" | Sequence used by operating system to separate lines in text files
"os.arch" | Operating system architecture
"os.name" | Operating system name
"os.version" | Operating system version
"path.separator" | Path separator character used in java.class.path
"user.dir" | User working directory
"user.home" | User home directory
"user.name" | User account name

Security consideration: Access to system properties can be restricted by the Security Manager. This is most often an issue in applets, which are prevented from reading some system properties, and from writing any system properties. For more on accessing system properties in applets, refer to Getting System Properties in the Applets lesson.

Reading System Properties

The System class has two methods used to read system properties: getProperty and getProperties.

The System class has two different versions of getProperty. Both retrieve the value of the property named in the argument list. The simpler of the two getProperty methods takes a single argument, a property key For example, to get the value of path.separator, use the following statement:

System.getProperty("path.separator");
The getProperty method returns a string containing the value of the property. If the property does not exist, this version of getProperty returns null.

The other version of getProperty requires two String arguments: the first argument is the key to look up and the second argument is a default value to return if the key cannot be found or if it has no value. For example, the following invocation of getProperty looks up the System property called subliminal.message. This is not a valid system property, so instead of returning null, this method returns the default value provided as a second argument: "Buy StayPuft Marshmallows!"

System.getProperty("subliminal.message", "Buy StayPuft Marshmallows!");

The last method provided by the System class to access property values is the getProperties method, which returns a Properties object. This object contains a complete set of system property definitions.

Writing System Properties

To modify the existing set of system properties, use System.setProperties. This method takes a Properties object that has been initialized to contain the properties to be set. This method replaces the entire set of system properties with the new set represented by the Properties object.
Warning: Changing system properties is potentially dangerous and should be done with discretion. Many system properties are not reread after start-up and are there for informational purposes. Changing some properties may have unexpected side-effects.

The next example, PropertiesTest, creates a Properties object and initializes it from myProperties.txt.

subliminal.message=Buy StayPuft Marshmallows!
PropertiesTest then uses System.setProperties to install the new Properties objects as the current set of system properties.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.FileInputStream;
import java.util.Properties;

public class PropertiesTest {
    public static void main(String[] args) throws Exception {
        // set up new properties object
    // from file "myProperties.txt"
        FileInputStream propFile = new FileInputStream(
                                           "myProperties.txt");
        Properties p = new Properties(System.getProperties());
        p.load(propFile);

        // set the system properties
        System.setProperties(p);
    // display new properties
        System.getProperties().list(System.out);
    }
}
Note how PropertiesTest creates the Properties object, p, which is used as the argument to setProperties:
Properties p = new Properties(System.getProperties());
This statement initializes the new properties object, p, with the current set of system properties, which in the case of this small application, is the set of properties initialized by the runtime system. Then the application loads additional properties into p from the file myProperties.txt and sets the system properties to p. This has the effect of adding the properties listed in myProperties.txt to the set of properties created by the runtime system at startup. Note that an application can create p without any default Properties object, like this:
Properties p = new Properties();

Also note that the value of system properties can be overwritten! For example, if myProperties.txt contains the following line, the java.vendor system property will be overwritten:

java.vendor=Acme Software Company
In general, be careful not to overwrite system properties.

The setProperties method changes the set of system properties for the current running application. These changes are not persistent. That is, changing the system properties within an application will not affect future invocations of the Java interpreter for this or any other application. The runtime system re-initializes the system properties each time its starts up. If changes to system properties are to be persistent, then the application must write the values to some file before exiting and read them in again upon startup.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Command-Line I/O Objects
Next page: The Security Manager


The Security Manager (The Java™ Tutorials > Essential Classes > The Platform Environment)

Trail: Essential Classes
Lesson: The Platform Environment
Section: System Utilities
The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises
Home Page > Essential Classes > The Platform Environment
« Previous • Trail • Next »
The Security Manager
A security manager is an object that defines a security policy for an application. This policy specifies actions that are unsafe or sensitive. Any actions not allowed by the security policy cause a SecurityException to be thrown. An application can also query its security manager to discover which actions are allowed.

Typically, a web applet runs with a security manager provided by the browser or Java Web Start plugin. Other kinds of applications normally run without a security manager, unless the application itself defines one. If no security manager is present, the application has no security policy and acts without restrictions.

This section explains how an application interacts with an existing security manager. For more detailed information, including information on how to design a security manager, refer to the Security Guide.

Interacting with the Security Manager

The security manager is an object of type SecurityManager; to obtain a reference to this object, invoke System.getSecurityManager.
SecurityManager appsm = System.getSecurityManager();
If there is no security manager, this method returns null.

Once an application has a reference to the security manager object, it can request permission to do specific things. Many classes in the standard libraries do this. For example, System.exit, which terminates the Java virtual machine with an exit status, invokes SecurityManager.checkExit to ensure that the current thread has permission to shut down the application.

The SecurityManager class defines many other methods used to verify other kinds of operations. For example, SecurityManager.checkAccess verifies thread accesses, and SecurityManager.checkPropertyAccess verifies access to the specified property. Each operation or group of operations has its own checkXXX() method.

In addition, the set of checkXXX() methods represents the set of operations that are already subject to the protection of the security manager. Typically, an application does not have to directly invoke any checkXXX() methods.

Recognizing a Security Violation

Many actions that are routine without a security manager can throw a SecurityException when run with a security manager. This is true even when invoking a method that isn't documented as throwing SecurityException. For example, consider the following code used to read a file:
reader = new FileReader("xanadu.txt");
In the absence of a security manager, this statement executes without error, provided xanadu.txt exists and is readable. But suppose this statement is inserted in a web applet, which typically runs under a security manager that does not allow file input. The following error messages might result:
appletviewer fileApplet.html
Exception in thread "AWT-EventQueue-1" java.security.AccessControlException: access denied (java.io.FilePermission characteroutput.txt write)
    at java.security.AccessControlContext.checkPermission(AccessControlContext.java:323)
    at java.security.AccessController.checkPermission(AccessController.java:546)
    at java.lang.SecurityManager.checkPermission(SecurityManager.java:532)
    at java.lang.SecurityManager.checkWrite(SecurityManager.java:962)
    at java.io.FileOutputStream.(FileOutputStream.java:169)
    at java.io.FileOutputStream.(FileOutputStream.java:70)
    at java.io.FileWriter.(FileWriter.java:46)
...
Note that the specific exception thrown in this case, java.security.AccessControlException, is a subclass of SecurityException.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: System Properties
Next page: Miscellaneous Methods in System


Miscellaneous Methods in System (The Java™ Tutorials > Essential Classes > The Platform Environment)

Trail: Essential Classes
Lesson: The Platform Environment
Section: System Utilities
The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises
Home Page > Essential Classes > The Platform Environment
« Previous • Trail • Next »
Miscellaneous Methods in System
This section describes some of the methods in System that aren't covered in the previous sections.

The arrayCopy method efficiently copies data between arrays. For more information, refer to Arrays in the Language Basics lesson.

The currentTimeMillis and nanoTime methods are useful for measuring time intervals during execution of an application. To measure a time interval in milliseconds, invoke currentTimeMillis twice, at the beginning and end of the interval, and subtract the first value returned from the second. Similarly, invoking nanoTime twice measures an interval in nanoseconds.

NOTE: The accuracy of both currentTimeMillis and nanoTime is limited by the time services provided by the operating system. Do not assume that currentTimeMillis is accurate to the nearest millisecond or that nanoTime is accurate to the nearest nanosecond. Also, neither currentTimeMillis nor nanoTime should be used to determine the current time. Use a high-level method, such as java.util.Calendar.getInstance.

The exit method causes the Java virtual machine to shut down, with an integer exit status specified by the argument. The exit status is available to the process that launched the application. By convention, an exit status of 0 indicates normal termination of the application, while any other value is an error code.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Security Manager
Next page: PATH and CLASSPATH


PATH and CLASSPATH (The Java™ Tutorials > Essential Classes > The Platform Environment)

Trail: Essential Classes
Lesson: The Platform Environment
The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises
Home Page > Essential Classes > The Platform Environment
« Previous • Trail • Next »
PATH and CLASSPATH
This section explains how to use the PATH and CLASSPATH environment variables on Microsoft Windows, Solaris, and Linux. Consult the installation instructions included with your installation of the Java Development Kit (JDK) software bundle for current information.

After installing the software, the JDK directory will have the structure shown below.

The bin directory contains both the compiler and the launcher.

Update the PATH Variable (Microsoft Windows NT/2000/XP)

You can run Java applications just fine without setting the PATH variable. Or, you can optionally set it as a convenience.

Set the PATH variable if you want to be able to conveniently run the executables (javac.exe, java.exe, javadoc.exe, and so on) from any directory without having to type the full path of the command. If you do not set the PATH variable, you need to specify the full path to the executable every time you run it, such as:

C:\Program Files\Java\jdk1.6.0\bin\javac MyClass.java
Note: It is useful to set the PATH permanently so it will persist after rebooting. To set it permanently, add the full path of the jdk1.6.0 bin directory to the PATH variable. Set the PATH as follows.

To make a permanent change to the CLASSPATH variable, use the System icon in the Control Panel. The precise procedure varies depending on the version of Windows.

The PATH can be a series of directories separated by semicolons (;). Microsoft Windows looks for programs in the PATH directories in order, from left to right. You should have only one bin directory for the JDK in the path at a time (those following the first are ignored), so if one is already present, you can update that particular entry.

Update the PATH Variable (Solaris and Linux)

You can run the JDK just fine without setting the PATH variable, or you can optionally set it as a convenience. However, you should set the path variable if you want to be able to run the executables (javac, java, javadoc, and so on) from any directory without having to type the full path of the command. If you do not set the PATH variable, you need to specify the full path to the executable every time you run it, such as:
% /usr/local/jdk1.6.0/bin/javac MyClass.java
To find out if the path is properly set, execute:
% java -version
This will print the version of the java tool, if it can find it. If the version is old or you get the error java: Command not found, then the path is not properly set.

To set the path permanently, set the path in your startup file.

For C shell (csh), edit the startup file (~/.cshrc):

set path=(/usr/local/jdk1.6.0/bin )
For bash, edit the startup file (~/.bashrc):
PATH=/usr/local/jdk1.6.0/bin:
export PATH
For ksh, the startup file is named by the environment variable, ENV. To set the path:
PATH=/usr/local/jdk1.6.0/bin:
export PATH
For sh, edit the profile file (~/.profile):
PATH=/usr/local/jdk1.6.0/bin:
export PATH
Then load the startup file and verify that the path is set by repeating the java command:

For C shell (csh):

% source ~/.cshrc
% java -version
For ksh, bash, or sh:
% . /.profile
% java -version

Checking the CLASSPATH variable (All platforms)

The CLASSPATH variable is one way to tell applications, including the JDK tools, where to look for user classes. (Classes that are part of the JRE, JDK platform, and extensions should be defined through other means, such as the bootstrap class path or the extensions directory.)

The preferred way to specify the class path is by using the -cp command line switch. This allows the CLASSPATH to be set individually for each application without affecting other applications. Setting the CLASSPATH can be tricky and should be performed with care.

The default value of the class path is ".", meaning that only the current directory is searched. Specifying either the CLASSPATH variable or the -cp command line switch overrides this value.

To check whether CLASSPATH is set on Microsoft Windows NT/2000/XP, execute the following:

C:> echo %CLASSPATH%
On Solaris or Linux, execute the following:
% echo $CLASSPATH
If CLASSPATH is not set you will get a CLASSPATH: Undefined variable error (Solaris or Linux) or simply %CLASSPATH% (Microsoft Windows NT/2000/XP).

To modify the CLASSPATH, use the same procedure you used for the PATH variable.

Class path wildcards allow you to include an entire directory of .jar files in the class path without explicitly naming them individually. For more information, including an explanation of class path wildcards, and a detailed description on how to clean up the CLASSPATH environment variable, see the Setting the Class Path technical note.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Miscellaneous Methods in System
Next page: Questions and Exercises: The Platform Environment


Questions and Exercises: The Platform Environment (The Java™ Tutorials > Essential Classes > The Platform Environment)

Trail: Essential Classes
Lesson: The Platform Environment
The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises
Home Page > Essential Classes > The Platform Environment
« Previous • Trail • Next »
Questions and Exercises: The Platform Environment

Questions

1. A programmer installs a new library contained in a .jar file. In order to access the library from his code, he sets the CLASSPATH environment variable to point to the new .jar file. Now he finds that he gets an error message when he tries to launch simple applications:

java Hello
Exception in thread "main" java.lang.NoClassDefFoundError: Hello
In this case, the Hello class is compiled into a .class file in the current directory — yet the java command can't seem to find it. What's going wrong?

Exercises

1. Write an application, PersistentEcho, with the following features:

  • If PersistentEcho is run with command line arguments, it prints out those arguments. It also saves the string printed out to a property, and saves the property to a file called PersistentEcho.txt
  • If PersistentEcho is run with no command line arguments, it looks for an environment variable called PERSISTENTECHO. If that variable exists, PersistentEcho prints out its value, and also saves the value in the same way it does for command line arguments.
  • If PersistentEcho is run with no command line arguments, and the PERSISTENTECHO environment variable is not defined, it retrieves the property value from PersistentEcho.txt and prints that out.

Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: PATH and CLASSPATH
Next page: Regular Expressions


Lesson: Regular Expressions (The Java™ Tutorials > Essential Classes)

Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises
Trail: Essential Classes
Home Page > Essential Classes
« Previous • Trail • Next »
Lesson: Regular Expressions
This lesson explains how to use the java.util.regex API for pattern matching with regular expressions. Although the syntax accepted by this package is similar to the Perl programming language, knowledge of Perl is not a prerequisite. This lesson starts with the basics, and gradually builds to cover more advanced techniques.
Introduction
Provides a general overview of regular expressions. It also introduces the core classes that comprise this API.

Test Harness
Defines a simple application for testing pattern matching with regular expressions.

String Literals
Introduces basic pattern matching, metacharacters, and quoting.

Character Classes
Describes simple character classes, negation, ranges, unions, intersections, and subtraction.

Predefined Character Classes
Describes the basic predefined character classes for whitespace, word, and digit characters.

Quantifiers
Explains greedy, reluctant, and possessive quantifiers for matching a specified expression x number of times.

Capturing Groups
Explains how to treat multiple characters as a single unit.

Boundary Matchers
Describes line, word, and input boundaries.

Methods of the Pattern Class
Examines other useful methods of the Pattern class, and explores advanced features such as compiling with flags and using embedded flag expressions.

Methods of the Matcher Class
Describes the commonly-used methods of the Matcher class.

Methods of the PatternSyntaxException Class
Describes how to examine a PatternSyntaxException.

Additional Resources
To read more about regular expressions, consult this section for additional resources.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Introduction


Introduction (The Java™ Tutorials > Essential Classes > Regular Expressions)

Trail: Essential Classes
Lesson: Regular Expressions
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises
Home Page > Essential Classes > Regular Expressions
« Previous • Trail • Next »
Introduction

What Are Regular Expressions?

Regular expressions are a way to describe a set of strings based on common characteristics shared by each string in the set. They can be used to search, edit, or manipulate text and data. You must learn a specific syntax to create regular expressions — one that goes beyond the normal syntax of the Java programming language. Regular expressions vary in complexity, but once you understand the basics of how they're constructed, you'll be able to decipher (or create) any regular expression.

This trail teaches the regular expression syntax supported by the java.util.regex API and presents several working examples to illustrate how the various objects interact. In the world of regular expressions, there are many different flavors to choose from, such as grep, Perl, Tcl, Python, PHP, and awk. The regular expression syntax in the java.util.regex API is most similar to that found in Perl.

How Are Regular Expressions Represented in This Package?

The java.util.regex package primarily consists of three classes: Pattern, Matcher, and PatternSyntaxException.

  • A Pattern object is a compiled representation of a regular expression. The Pattern class provides no public constructors. To create a pattern, you must first invoke one of its public static compile methods, which will then return a Pattern object. These methods accept a regular expression as the first argument; the first few lessons of this trail will teach you the required syntax.

  • A Matcher object is the engine that interprets the pattern and performs match operations against an input string. Like the Pattern class, Matcher defines no public constructors. You obtain a Matcher object by invoking the matcher method on a Pattern object.

  • A PatternSyntaxException object is an unchecked exception that indicates a syntax error in a regular expression pattern.
The last few lessons of this trail explore each class in detail. But first, you must understand how regular expressions are actually constructed. Therefore, the next section introduces a simple test harness that will be used repeatedly to explore their syntax.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Regular Expressions
Next page: Test Harness


Test Harness (The Java™ Tutorials > Essential Classes > Regular Expressions)

Trail: Essential Classes
Lesson: Regular Expressions
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises
Home Page > Essential Classes > Regular Expressions
« Previous • Trail • Next »
Test Harness
This section defines a reusable test harness, RegexTestHarness.java , for exploring the regular expression constructs supported by this API. The command to run this code is java RegexTestHarness; no command-line arguments are accepted. The application loops repeatedly, prompting the user for a regular expression and input string. Using this test harness is optional, but you may find it convenient for exploring the test cases discussed in the following pages.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.Console;
import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexTestHarness {

    public static void main(String[] args){
        Console console = System.console();
        if (console == null) {
            System.err.println("No console.");
            System.exit(1);
        }
        while (true) {

            Pattern pattern =
            Pattern.compile(console.readLine("%nEnter your regex: "));

            Matcher matcher =
            pattern.matcher(console.readLine("Enter input string to search: "));

            boolean found = false;
            while (matcher.find()) {
                console.format("I found the text \"%s\" starting at " +
                   "index %d and ending at index %d.%n",
                    matcher.group(), matcher.start(), matcher.end());
                found = true;
            }
            if(!found){
                console.format("No match found.%n");
            }
        }
    }
}

Before continuing to the next section, save and compile this code to ensure that your development environment supports the required packages.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Introduction
Next page: String Literals


String Literals (The Java™ Tutorials > Essential Classes > Regular Expressions)

Trail: Essential Classes
Lesson: Regular Expressions
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises
Home Page > Essential Classes > Regular Expressions
« Previous • Trail • Next »
String Literals
The most basic form of pattern matching supported by this API is the match of a string literal. For example, if the regular expression is foo and the input string is foo, the match will succeed because the strings are identical. Try this out with the test harness:

Enter your regex: foo
Enter input string to search: foo
I found the text "foo" starting at index 0 and ending at index 3.
This match was a success. Note that while the input string is 3 characters long, the start index is 0 and the end index is 3. By convention, ranges are inclusive of the beginning index and exclusive of the end index, as shown in the following figure:

The string literal

The string literal "foo", with numbered cells and index values.

Each character in the string resides in its own cell, with the index positions pointing between each cell. The string "foo" starts at index 0 and ends at index 3, even though the characters themselves only occupy cells 0, 1, and 2.

With subsequent matches, you'll notice some overlap; the start index for the next match is the same as the end index of the previous match:

Enter your regex: foo
Enter input string to search: foofoofoo
I found the text "foo" starting at index 0 and ending at index 3.
I found the text "foo" starting at index 3 and ending at index 6.
I found the text "foo" starting at index 6 and ending at index 9.

Metacharacters

This API also supports a number of special characters that affect the way a pattern is matched. Change the regular expression to cat. and the input string to cats. The output will appear as follows:
Enter your regex: cat.
Enter input string to search: cats
I found the text "cats" starting at index 0 and ending at index 4.
The match still succeeds, even though the dot "." is not present in the input string. It succeeds because the dot is a metacharacter — a character with special meaning interpreted by the matcher. The metacharacter "." means "any character" which is why the match succeeds in this example.

The metacharacters supported by this API are: ([{\^-$|]})?*+.

Note: In certain situations the special characters listed above will not be treated as metacharacters. You'll encounter this as you learn more about how regular expressions are constructed. You can, however, use this list to check whether or not a specific character will ever be considered a metacharacter. For example, the characters ! @ and # never carry a special meaning.

There are two ways to force a metacharacter to be treated as an ordinary character:

  • precede the metacharacter with a backslash, or
  • enclose it within \Q (which starts the quote) and \E (which ends it).
When using this technique, the \Q and \E can be placed at any location within the expression, provided that the \Q comes first.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Test Harness
Next page: Character Classes


Character Classes (The Java™ Tutorials > Essential Classes > Regular Expressions)

Trail: Essential Classes
Lesson: Regular Expressions
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises
Home Page > Essential Classes > Regular Expressions
« Previous • Trail • Next »
Character Classes
If you browse through the Pattern class specification, you'll see tables summarizing the supported regular expression constructs. In the "Character Classes" section you'll find the following:
Character Classes
[abc] | a, b, or c (simple class)
[^abc] | Any character except a, b, or c (negation)
[a-zA-Z] | a through z, or A through Z, inclusive (range)
[a-d[m-p]] | a through d, or m through p: [a-dm-p] (union)
[a-z&&[def]] | d, e, or f (intersection)
[a-z&&[^bc]] | a through z, except for b and c: [ad-z] (subtraction)
[a-z&&[^m-p]] | a through z, and not m through p: [a-lq-z] (subtraction)
The left-hand column specifies the regular expression constructs, while the right-hand column describes the conditions under which each construct will match.
Note: The word "class" in the phrase "character class" does not refer to a .class file. In the context of regular expressions, a character class is a set of characters enclosed within square brackets. It specifies the characters that will successfully match a single character from a given input string.

Simple Classes

The most basic form of a character class is to simply place a set of characters side-by-side within square brackets. For example, the regular expression [bcr]at will match the words "bat", "cat", or "rat" because it defines a character class (accepting either "b", "c", or "r") as its first character.

Enter your regex: [bcr]at
Enter input string to search: bat
I found the text "bat" starting at index 0 and ending at index 3.

Enter your regex: [bcr]at
Enter input string to search: cat
I found the text "cat" starting at index 0 and ending at index 3.

Enter your regex: [bcr]at
Enter input string to search: rat
I found the text "rat" starting at index 0 and ending at index 3.

Enter your regex: [bcr]at
Enter input string to search: hat
No match found.
In the above examples, the overall match succeeds only when the first letter matches one of the characters defined by the character class.

Negation

To match all characters except those listed, insert the "^" metacharacter at the beginning of the character class. This technique is known as negation.

Enter your regex: [^bcr]at
Enter input string to search: bat
No match found.

Enter your regex: [^bcr]at
Enter input string to search: cat
No match found.

Enter your regex: [^bcr]at
Enter input string to search: rat
No match found.

Enter your regex: [^bcr]at
Enter input string to search: hat
I found the text "hat" starting at index 0 and ending at index 3.
The match is successful only if the first character of the input string does not contain any of the characters defined by the character class.

Ranges

Sometimes you'll want to define a character class that includes a range of values, such as the letters "a through h" or the numbers "1 through 5". To specify a range, simply insert the "-" metacharacter between the first and last character to be matched, such as [1-5] or [a-h]. You can also place different ranges beside each other within the class to further expand the match possibilities. For example, [a-zA-Z] will match any letter of the alphabet: a to z (lowercase) or A to Z (uppercase).

Here are some examples of ranges and negation:

Enter your regex: [a-c]
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.

Enter your regex: [a-c]
Enter input string to search: b
I found the text "b" starting at index 0 and ending at index 1.

Enter your regex: [a-c]
Enter input string to search: c
I found the text "c" starting at index 0 and ending at index 1.

Enter your regex: [a-c]
Enter input string to search: d
No match found.

Enter your regex: foo[1-5]
Enter input string to search: foo1
I found the text "foo1" starting at index 0 and ending at index 4.

Enter your regex: foo[1-5]
Enter input string to search: foo5
I found the text "foo5" starting at index 0 and ending at index 4.

Enter your regex: foo[1-5]
Enter input string to search: foo6
No match found.

Enter your regex: foo[^1-5]
Enter input string to search: foo1
No match found.

Enter your regex: foo[^1-5]
Enter input string to search: foo6
I found the text "foo6" starting at index 0 and ending at index 4.

Unions

You can also use unions to create a single character class comprised of two or more separate character classes. To create a union, simply nest one class inside the other, such as [0-4[6-8]]. This particular union creates a single character class that matches the numbers 0, 1, 2, 3, 4, 6, 7, and 8.
Enter your regex: [0-4[6-8]]
Enter input string to search: 0
I found the text "0" starting at index 0 and ending at index 1.

Enter your regex: [0-4[6-8]]
Enter input string to search: 5
No match found.

Enter your regex: [0-4[6-8]]
Enter input string to search: 6
I found the text "6" starting at index 0 and ending at index 1.

Enter your regex: [0-4[6-8]]
Enter input string to search: 8
I found the text "8" starting at index 0 and ending at index 1.

Enter your regex: [0-4[6-8]]
Enter input string to search: 9
No match found.

Intersections

To create a single character class matching only the characters common to all of its nested classes, use &&, as in [0-9&&[345]]. This particular intersection creates a single character class matching only the numbers common to both character classes: 3, 4, and 5.

Enter your regex: [0-9&&[345]]
Enter input string to search: 3
I found the text "3" starting at index 0 and ending at index 1.

Enter your regex: [0-9&&[345]]
Enter input string to search: 4
I found the text "4" starting at index 0 and ending at index 1.

Enter your regex: [0-9&&[345]]
Enter input string to search: 5
I found the text "5" starting at index 0 and ending at index 1.

Enter your regex: [0-9&&[345]]
Enter input string to search: 2
No match found.

Enter your regex: [0-9&&[345]]
Enter input string to search: 6
No match found.
And here's an example that shows the intersection of two ranges:

Enter your regex: [2-8&&[4-6]]
Enter input string to search: 3
No match found.

Enter your regex: [2-8&&[4-6]]
Enter input string to search: 4
I found the text "4" starting at index 0 and ending at index 1.

Enter your regex: [2-8&&[4-6]]
Enter input string to search: 5
I found the text "5" starting at index 0 and ending at index 1.

Enter your regex: [2-8&&[4-6]]
Enter input string to search: 6
I found the text "6" starting at index 0 and ending at index 1.

Enter your regex: [2-8&&[4-6]]
Enter input string to search: 7
No match found.

Subtraction

Finally, you can use subtraction to negate one or more nested character classes, such as [0-9&&[^345]]. This example creates a single character class that matches everything from 0 to 9, except the numbers 3, 4, and 5.

Enter your regex: [0-9&&[^345]]
Enter input string to search: 2
I found the text "2" starting at index 0 and ending at index 1.

Enter your regex: [0-9&&[^345]]
Enter input string to search: 3
No match found.

Enter your regex: [0-9&&[^345]]
Enter input string to search: 4
No match found.

Enter your regex: [0-9&&[^345]]
Enter input string to search: 5
No match found.

Enter your regex: [0-9&&[^345]]
Enter input string to search: 6
I found the text "6" starting at index 0 and ending at index 1.

Enter your regex: [0-9&&[^345]]
Enter input string to search: 9
I found the text "9" starting at index 0 and ending at index 1.
Now that we've covered how character classes are created, You may want to review the Character Classes table before continuing with the next section.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: String Literals
Next page: Predefined Character Classes


Predefined Character Classes (The Java™ Tutorials > Essential Classes > Regular Expressions)

Trail: Essential Classes
Lesson: Regular Expressions
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises
Home Page > Essential Classes > Regular Expressions
« Previous • Trail • Next »
Predefined Character Classes
The Pattern API contains a number of useful predefined character classes, which offer convenient shorthands for commonly used regular expressions:
Predefined Character Classes
. Any character (may or may not match line terminators)
\d | A digit: [0-9]
\D | A non-digit: [^0-9]
\s | A whitespace character: [ \t\n\x0B\f\r]
\S | A non-whitespace character: [^\s]
\w | A word character: [a-zA-Z_0-9]
\W | A non-word character: [^\w]
In the table above, each construct in the left-hand column is shorthand for the character class in the right-hand column. For example, \d means a range of digits (0-9), and \w means a word character (any lowercase letter, any uppercase letter, the underscore character, or any digit). Use the predefined classes whenever possible. They make your code easier to read and eliminate errors introduced by malformed character classes.

Constructs beginning with a backslash are called escaped constructs. We previewed escaped constructs in the String Literals section where we mentioned the use of backslash and \Q and \E for quotation. If you are using an escaped construct within a string literal, you must preceed the backslash with another backslash for the string to compile. For example:

private final String REGEX = "\\d"; // a single digit
In this example \d is the regular expression; the extra backslash is required for the code to compile. The test harness reads the expressions directly from the Console, however, so the extra backslash is unnecessary.

The following examples demonstrate the use of predefined character classes.

Enter your regex: .
Enter input string to search: @
I found the text "@" starting at index 0 and ending at index 1.

Enter your regex: .
Enter input string to search: 1
I found the text "1" starting at index 0 and ending at index 1.

Enter your regex: .
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.

Enter your regex: \d
Enter input string to search: 1
I found the text "1" starting at index 0 and ending at index 1.

Enter your regex: \d
Enter input string to search: a
No match found.

Enter your regex: \D
Enter input string to search: 1
No match found.

Enter your regex: \D
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.

Enter your regex: \s
Enter input string to search:
I found the text " " starting at index 0 and ending at index 1.

Enter your regex: \s
Enter input string to search: a
No match found.

Enter your regex: \S
Enter input string to search:
No match found.

Enter your regex: \S
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.

Enter your regex: \w
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.

Enter your regex: \w
Enter input string to search: !
No match found.

Enter your regex: \W
Enter input string to search: a
No match found.

Enter your regex: \W
Enter input string to search: !
I found the text "!" starting at index 0 and ending at index 1.
In the first three examples, the regular expression is simply . (the "dot" metacharacter) that indicates "any character." Therefore, the match is successful in all three cases (a randomly selected @ character, a digit, and a letter). The remaining examples each use a single regular expression construct from the Predefined Character Classes table. You can refer to this table to figure out the logic behind each match:
  • \d matches all digits
  • \s matches spaces
  • \w matches word characters
Alternatively, a capital letter means the opposite:
  • \D matches non-digits
  • \S matches non-spaces
  • \W matches non-word characters

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Character Classes
Next page: Quantifiers


Quantifiers (The Java™ Tutorials > Essential Classes > Regular Expressions)

Trail: Essential Classes
Lesson: Regular Expressions
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises
Home Page > Essential Classes > Regular Expressions
« Previous • Trail • Next »
Quantifiers
Quantifiers allow you to specify the number of occurrences to match against. For convenience, the three sections of the Pattern API specification describing greedy, reluctant, and possessive quantifiers are presented below. At first glance it may appear that the quantifiers X?, X?? and X?+ do exactly the same thing, since they all promise to match "X, once or not at all". There are subtle implementation differences which will be explained near the end of this section.

Quantifiers
 Meaning
Greedy | Reluctant | Possessive
X? | X?? | X?+ | X, once or not at all
X* | X*? | X*+ | X, zero or more times
X+ | X+? | X++ | X, one or more times
X{n} | X{n}? | X{n}+ | X, exactly n times
X{n,} | X{n,}? | X{n,}+ | X, at least n times
X{n,m} | X{n,m}? | X{n,m}+ | X, at least n but not more than m times

Let's start our look at greedy quantifiers by creating three different regular expressions: the letter "a" followed by either ?, *, or +. Let's see what happens when these expressions are tested against an empty input string "":

Enter your regex: a?
Enter input string to search:
I found the text "" starting at index 0 and ending at index 0.

Enter your regex: a*
Enter input string to search:
I found the text "" starting at index 0 and ending at index 0.

Enter your regex: a+
Enter input string to search:
No match found.

Zero-Length Matches

In the above example, the match is successful in the first two cases because the expressions a? and a* both allow for zero occurrences of the letter a. You'll also notice that the start and end indices are both zero, which is unlike any of the examples we've seen so far. The empty input string "" has no length, so the test simply matches nothing at index 0. Matches of this sort are known as a zero-length matches. A zero-length match can occur in several cases: in an empty input string, at the beginning of an input string, after the last character of an input string, or in between any two characters of an input string. Zero-length matches are easily identifiable because they always start and end at the same index position.

Let's explore zero-length matches with a few more examples. Change the input string to a single letter "a" and you'll notice something interesting:

Enter your regex: a?
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.

Enter your regex: a*
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.

Enter your regex: a+
Enter input string to search: a
I found the text "a" starting at index 0 and ending at index 1.
All three quantifiers found the letter "a", but the first two also found a zero-length match at index 1; that is, after the last character of the input string. Remember, the matcher sees the character "a" as sitting in the cell between index 0 and index 1, and our test harness loops until it can no longer find a match. Depending on the quantifier used, the presence of "nothing" at the index after the last character may or may not trigger a match.

Now change the input string to the letter "a" five times in a row and you'll get the following:

Enter your regex: a?
Enter input string to search: aaaaa
I found the text "a" starting at index 0 and ending at index 1.
I found the text "a" starting at index 1 and ending at index 2.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "a" starting at index 3 and ending at index 4.
I found the text "a" starting at index 4 and ending at index 5.
I found the text "" starting at index 5 and ending at index 5.

Enter your regex: a*
Enter input string to search: aaaaa
I found the text "aaaaa" starting at index 0 and ending at index 5.
I found the text "" starting at index 5 and ending at index 5.

Enter your regex: a+
Enter input string to search: aaaaa
I found the text "aaaaa" starting at index 0 and ending at index 5.
The expression a? finds an individual match for each character, since it matches when "a" appears zero or one times. The expression a* finds two separate matches: all of the letter "a"'s in the first match, then the zero-length match after the last character at index 5. And finally, a+ matches all occurrences of the letter "a", ignoring the presence of "nothing" at the last index.

At this point, you might be wondering what the results would be if the first two quantifiers encounter a letter other than "a". For example, what happens if it encounters the letter "b", as in "ababaaaab"?

Let's find out:

Enter your regex: a?
Enter input string to search: ababaaaab
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "" starting at index 3 and ending at index 3.
I found the text "a" starting at index 4 and ending at index 5.
I found the text "a" starting at index 5 and ending at index 6.
I found the text "a" starting at index 6 and ending at index 7.
I found the text "a" starting at index 7 and ending at index 8.
I found the text "" starting at index 8 and ending at index 8.
I found the text "" starting at index 9 and ending at index 9.

Enter your regex: a*
Enter input string to search: ababaaaab
I found the text "a" starting at index 0 and ending at index 1.
I found the text "" starting at index 1 and ending at index 1.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "" starting at index 3 and ending at index 3.
I found the text "aaaa" starting at index 4 and ending at index 8.
I found the text "" starting at index 8 and ending at index 8.
I found the text "" starting at index 9 and ending at index 9.

Enter your regex: a+
Enter input string to search: ababaaaab
I found the text "a" starting at index 0 and ending at index 1.
I found the text "a" starting at index 2 and ending at index 3.
I found the text "aaaa" starting at index 4 and ending at index 8.
Even though the letter "b" appears in cells 1, 3, and 8, the output reports a zero-length match at those locations. The regular expression a? is not specifically looking for the letter "b"; it's merely looking for the presence (or lack thereof) of the letter "a". If the quantifier allows for a match of "a" zero times, anything in the input string that's not an "a" will show up as a zero-length match. The remaining a's are matched according to the rules discussed in the previous examples.

To match a pattern exactly n number of times, simply specify the number inside a set of braces:

Enter your regex: a{3}
Enter input string to search: aa
No match found.

Enter your regex: a{3}
Enter input string to search: aaa
I found the text "aaa" starting at index 0 and ending at index 3.

Enter your regex: a{3}
Enter input string to search: aaaa
I found the text "aaa" starting at index 0 and ending at index 3.
Here, the regular expression a{3} is searching for three occurrences of the letter "a" in a row. The first test fails because the input string does not have enough a's to match against. The second test contains exactly 3 a's in the input string, which triggers a match. The third test also triggers a match because there are exactly 3 a's at the beginning of the input string. Anything following that is irrelevant to the first match. If the pattern should appear again after that point, it would trigger subsequent matches:

Enter your regex: a{3}
Enter input string to search: aaaaaaaaa
I found the text "aaa" starting at index 0 and ending at index 3.
I found the text "aaa" starting at index 3 and ending at index 6.
I found the text "aaa" starting at index 6 and ending at index 9.
To require a pattern to appear at least n times, add a comma after the number:

Enter your regex: a{3,}
Enter input string to search: aaaaaaaaa
I found the text "aaaaaaaaa" starting at index 0 and ending at index 9.
With the same input string, this test finds only one match, because the 9 a's in a row satisfy the need for "at least" 3 a's.

Finally, to specify an upper limit on the number of occurances, add a second number inside the braces:

Enter your regex: a{3,6} // find at least 3 (but no more than 6) a's in a row
Enter input string to search: aaaaaaaaa
I found the text "aaaaaa" starting at index 0 and ending at index 6.
I found the text "aaa" starting at index 6 and ending at index 9.
Here the first match is forced to stop at the upper limit of 6 characters. The second match includes whatever is left over, which happens to be three a's — the mimimum number of characters allowed for this match. If the input string were one character shorter, there would not be a second match since only two a's would remain.

Capturing Groups and Character Classes with Quantifiers

Until now, we've only tested quantifiers on input strings containing one character. In fact, quantifiers can only attach to one character at a time, so the regular expression "abc+" would mean "a, followed by b, followed by c one or more times". It would not mean "abc" one or more times. However, quantifiers can also attach to Character Classes and Capturing Groups, such as [abc]+ (a or b or c, one or more times) or (abc)+ (the group "abc", one or more times).

Let's illustrate by specifying the group (dog), three times in a row.

Enter your regex: (dog){3}
Enter input string to search: dogdogdogdogdogdog
I found the text "dogdogdog" starting at index 0 and ending at index 9.
I found the text "dogdogdog" starting at index 9 and ending at index 18.

Enter your regex: dog{3}
Enter input string to search: dogdogdogdogdogdog
No match found.
Here the first example finds three matches, since the quantifier applies to the entire capturing group. Remove the parentheses, however, and the match fails because the quantifier {3} now applies only to the letter "g".

Similarly, we can apply a quantifier to an entire character class:

Enter your regex: [abc]{3}
Enter input string to search: abccabaaaccbbbc
I found the text "abc" starting at index 0 and ending at index 3.
I found the text "cab" starting at index 3 and ending at index 6.
I found the text "aaa" starting at index 6 and ending at index 9.
I found the text "ccb" starting at index 9 and ending at index 12.
I found the text "bbc" starting at index 12 and ending at index 15.

Enter your regex: abc{3}
Enter input string to search: abccabaaaccbbbc
No match found.
Here the quantifier {3} applies to the entire character class in the first example, but only to the letter "c" in the second.

Differences Among Greedy, Reluctant, and Possessive Quantifiers

There are subtle differences among greedy, reluctant, and possessive quantifiers.

Greedy quantifiers are considered "greedy" because they force the matcher to read in, or eat, the entire input string prior to attempting the first match. If the first match attempt (the entire input string) fails, the matcher backs off the input string by one character and tries again, repeating the process until a match is found or there are no more characters left to back off from. Depending on the quantifier used in the expression, the last thing it will try matching against is 1 or 0 characters.

The reluctant quantifiers, however, take the opposite approach: They start at the beginning of the input string, then reluctantly eat one character at a time looking for a match. The last thing they try is the entire input string.

Finally, the possessive quantifiers always eat the entire input string, trying once (and only once) for a match. Unlike the greedy quantifiers, possessive quantifiers never back off, even if doing so would allow the overall match to succeed.

To illustrate, consider the input string xfooxxxxxxfoo.

Enter your regex: .*foo  // greedy quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfooxxxxxxfoo" starting at index 0 and ending at index 13.

Enter your regex: .*?foo  // reluctant quantifier
Enter input string to search: xfooxxxxxxfoo
I found the text "xfoo" starting at index 0 and ending at index 4.
I found the text "xxxxxxfoo" starting at index 4 and ending at index 13.

Enter your regex: .*+foo // possessive quantifier
Enter input string to search: xfooxxxxxxfoo
No match found.
The first example uses the greedy quantifier .* to find "anything", zero or more times, followed by the letters "f" "o" "o". Because the quantifier is greedy, the .* portion of the expression first eats the entire input string. At this point, the overall expression cannot succeed, because the last three letters ("f" "o" "o") have already been consumed. So the matcher slowly backs off one letter at a time until the rightmost occurrence of "foo" has been regurgitated, at which point the match succeeds and the search ends.

The second example, however, is reluctant, so it starts by first consuming "nothing". Because "foo" doesn't appear at the beginning of the string, it's forced to swallow the first letter (an "x"), which triggers the first match at 0 and 4. Our test harness continues the process until the input string is exhausted. It finds another match at 4 and 13.

The third example fails to find a match because the quantifier is possessive. In this case, the entire input string is consumed by .*+, leaving nothing left over to satisfy the "foo" at the end of the expression. Use a possessive quantifier for situations where you want to seize all of something without ever backing off; it will outperform the equivalent greedy quantifier in cases where the match is not immediately found.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Predefined Character Classes
Next page: Capturing Groups


Capturing Groups (The Java™ Tutorials > Essential Classes > Regular Expressions)

Trail: Essential Classes
Lesson: Regular Expressions
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises
Home Page > Essential Classes > Regular Expressions
« Previous • Trail • Next »
Capturing Groups
In the previous section, we saw how quantifiers attach to one character, character class, or capturing group at a time. But until now, we have not discussed the notion of capturing groups in any detail.

Capturing groups are a way to treat multiple characters as a single unit. They are created by placing the characters to be grouped inside a set of parentheses. For example, the regular expression (dog) creates a single group containing the letters "d" "o" and "g". The portion of the input string that matches the capturing group will be saved in memory for later recall via backreferences (as discussed below in the section, Backreferences).

Numbering

As described in the Pattern API, capturing groups are numbered by counting their opening parentheses from left to right. In the expression ((A)(B(C))), for example, there are four such groups:
  1. ((A)(B(C)))
  2. (A)
  3. (B(C))
  4. (C)
To find out how many groups are present in the expression, call the groupCount method on a matcher object. The groupCount method returns an int showing the number of capturing groups present in the matcher's pattern. In this example, groupCount would return the number 4, showing that the pattern contains 4 capturing groups.

There is also a special group, group 0, which always represents the entire expression. This group is not included in the total reported by groupCount. Groups beginning with (? are pure, non-capturing groups that do not capture text and do not count towards the group total. (You'll see examples of non-capturing groups later in the section Methods of the Pattern Class.)

It's important to understand how groups are numbered because some Matcher methods accept an int specifying a particular group number as a parameter:

  • public int start(int group): Returns the start index of the subsequence captured by the given group during the previous match operation.

  • public int end (int group): Returns the index of the last character, plus one, of the subsequence captured by the given group during the previous match operation.

  • public String group (int group): Returns the input subsequence captured by the given group during the previous match operation.

Backreferences

The section of the input string matching the capturing group(s) is saved in memory for later recall via backreference. A backreference is specified in the regular expression as a backslash (\) followed by a digit indicating the number of the group to be recalled. For example, the expression (\d\d) defines one capturing group matching two digits in a row, which can be recalled later in the expression via the backreference \1.

To match any 2 digits, followed by the exact same two digits, you would use (\d\d)\1 as the regular expression:

Enter your regex: (\d\d)\1
Enter input string to search: 1212
I found the text "1212" starting at index 0 and ending at index 4.
If you change the last two digits the match will fail:

Enter your regex: (\d\d)\1
Enter input string to search: 1234
No match found.
For nested capturing groups, backreferencing works in exactly the same way: Specify a backslash followed by the number of the group to be recalled.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Quantifiers
Next page: Boundary Matchers


Boundary Matchers (The Java™ Tutorials > Essential Classes > Regular Expressions)

Trail: Essential Classes
Lesson: Regular Expressions
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises
Home Page > Essential Classes > Regular Expressions
« Previous • Trail • Next »
Boundary Matchers
Until now, we've only been interested in whether or not a match is found at some location within a particular input string. We never cared about where in the string the match was taking place.

You can make your pattern matches more precise by specifying such information with boundary matchers. For example, maybe you're interested in finding a particular word, but only if it appears at the beginning or end of a line. Or maybe you want to know if the match is taking place on a word boundary, or at the end of the previous match.

The following table lists and explains all the boundary matchers.

Boundary Matchers
^ The beginning of a line
$ The end of a line
\b | A word boundary
\B | A non-word boundary
\A | The beginning of the input
\G | The end of the previous match
\Z | The end of the input but for the final terminator, if any
\z | The end of the input
The following examples demonstrate the use of boundary matchers ^ and $. As noted above, ^ matches the beginning of a line, and $ matches the end.

Enter your regex: ^dog$
Enter input string to search: dog
I found the text "dog" starting at index 0 and ending at index 3.

Enter your regex: ^dog$
Enter input string to search:       dog
No match found.

Enter your regex: \s*dog$
Enter input string to search:             dog
I found the text "            dog" starting at index 0 and ending at index 15.

Enter your regex: ^dog\w*
Enter input string to search: dogblahblah
I found the text "dogblahblah" starting at index 0 and ending at index 11.
The first example is successful because the pattern occupies the entire input string. The second example fails because the input string contains extra whitespace at the beginning. The third example specifies an expression that allows for unlimited white space, followed by "dog" on the end of the line. The fourth example requires "dog" to be present at the beginning of a line followed by an unlimited number of word characters.

To check if a pattern begins and ends on a word boundary (as opposed to a substring within a longer string), just use \b on either side; for example, \bdog\b

Enter your regex: \bdog\b
Enter input string to search: The dog plays in the yard.
I found the text "dog" starting at index 4 and ending at index 7.

Enter your regex: \bdog\b
Enter input string to search: The doggie plays in the yard.
No match found.
To match the expression on a non-word boundary, use \B instead:

Enter your regex: \bdog\B
Enter input string to search: The dog plays in the yard.
No match found.

Enter your regex: \bdog\B
Enter input string to search: The doggie plays in the yard.
I found the text "dog" starting at index 4 and ending at index 7.
To require the match to occur only at the end of the previous match, use \G:

Enter your regex: dog
Enter input string to search: dog dog
I found the text "dog" starting at index 0 and ending at index 3.
I found the text "dog" starting at index 4 and ending at index 7.

Enter your regex: \Gdog
Enter input string to search: dog dog
I found the text "dog" starting at index 0 and ending at index 3.
Here the second example finds only one match, because the second occurrence of "dog" does not start at the end of the previous match.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Capturing Groups
Next page: Methods of the Pattern Class


Methods of the Pattern Class (The Java™ Tutorials > Essential Classes > Regular Expressions)

Trail: Essential Classes
Lesson: Regular Expressions
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises
Home Page > Essential Classes > Regular Expressions
« Previous • Trail • Next »
Methods of the Pattern Class
Until now, we've only used the test harness to create Pattern objects in their most basic form. This section explores advanced techniques such as creating patterns with flags and using embedded flag expressions. It also explores some additional useful methods that we haven't yet discussed.

Creating a Pattern with Flags

The Pattern class defines an alternate compile method that accepts a set of flags affecting the way the pattern is matched. The flags parameter is a bit mask that may include any of the following public static fields:
  • Pattern.CANON_EQ Enables canonical equivalence. When this flag is specified, two characters will be considered to match if, and only if, their full canonical decompositions match. The expression "a\u030A", for example, will match the string "\u00E5" when this flag is specified. By default, matching does not take canonical equivalence into account. Specifying this flag may impose a performance penalty.

  • Pattern.CASE_INSENSITIVE Enables case-insensitive matching. By default, case-insensitive matching assumes that only characters in the US-ASCII charset are being matched. Unicode-aware case-insensitive matching can be enabled by specifying the UNICODE_CASE flag in conjunction with this flag. Case-insensitive matching can also be enabled via the embedded flag expression (?i). Specifying this flag may impose a slight performance penalty.

  • Pattern.COMMENTS Permits whitespace and comments in the pattern. In this mode, whitespace is ignored, and embedded comments starting with # are ignored until the end of a line. Comments mode can also be enabled via the embedded flag expression (?x).

  • Pattern.DOTALL Enables dotall mode. In dotall mode, the expression . matches any character, including a line terminator. By default this expression does not match line terminators. Dotall mode can also be enabled via the embedded flag expression (?s). (The s is a mnemonic for "single-line" mode, which is what this is called in Perl.)

  • Pattern.LITERAL Enables literal parsing of the pattern. When this flag is specified then the input string that specifies the pattern is treated as a sequence of literal characters. Metacharacters or escape sequences in the input sequence will be given no special meaning. The flags CASE_INSENSITIVE and UNICODE_CASE retain their impact on matching when used in conjunction with this flag. The other flags become superfluous. There is no embedded flag character for enabling literal parsing.

  • Pattern.MULTILINE Enables multiline mode. In multiline mode the expressions ^ and $ match just after or just before, respectively, a line terminator or the end of the input sequence. By default these expressions only match at the beginning and the end of the entire input sequence. Multiline mode can also be enabled via the embedded flag expression (?m).

  • Pattern.UNICODE_CASE Enables Unicode-aware case folding. When this flag is specified then case-insensitive matching, when enabled by the CASE_INSENSITIVE flag, is done in a manner consistent with the Unicode Standard. By default, case-insensitive matching assumes that only characters in the US-ASCII charset are being matched. Unicode-aware case folding can also be enabled via the embedded flag expression (?u). Specifying this flag may impose a performance penalty.

  • Pattern.UNIX_LINES Enables Unix lines mode. In this mode, only the '\n' line terminator is recognized in the behavior of ., ^, and $. Unix lines mode can also be enabled via the embedded flag expression (?d).
In the following steps we will modify the test harness, RegexTestHarness.java to create a pattern with case-insensitive matching.

First, modify the code to invoke the alternate version of compile:

Pattern pattern =
Pattern.compile(console.readLine("%nEnter your regex: "),
Pattern.CASE_INSENSITIVE);
Then compile and run the test harness to get the following results:

Enter your regex: dog
Enter input string to search: DoGDOg
I found the text "DoG" starting at index 0 and ending at index 3.
I found the text "DOg" starting at index 3 and ending at index 6.
As you can see, the string literal "dog" matches both occurences, regardless of case. To compile a pattern with multiple flags, separate the flags to be included using the bitwise OR operator "|". For clarity, the following code samples hardcode the regular expression instead of reading it from the Console:

pattern = Pattern.compile("[az]$", Pattern.MULTILINE | Pattern.UNIX_LINES);
You could also specify an int variable instead:

final int flags = Pattern.CASE_INSENSITIVE | Pattern.UNICODE_CASE;
Pattern pattern = Pattern.compile("aa", flags);

Embedded Flag Expressions

It's also possible to enable various flags using embedded flag expressions. Embedded flag expressions are an alternative to the two-argument version of compile, and are specified in the regular expression itself. The following example uses the original test harness, RegexTestHarness.java with the embedded flag expression (?i) to enable case-insensitive matching.

Enter your regex: (?i)foo
Enter input string to search: FOOfooFoOfoO
I found the text "FOO" starting at index 0 and ending at index 3.
I found the text "foo" starting at index 3 and ending at index 6.
I found the text "FoO" starting at index 6 and ending at index 9.
I found the text "foO" starting at index 9 and ending at index 12.
Once again, all matches succeed regardless of case.

The embedded flag expressions that correspond to Pattern's publicly accessible fields are presented in the following table:

Constant | Equivalent Embedded Flag Expression
Pattern.CANON_EQ | None
Pattern.CASE_INSENSITIVE | (?i)
Pattern.COMMENTS | (?x)
Pattern.MULTILINE | (?m)
Pattern.DOTALL | (?s)
Pattern.LITERAL | None
Pattern.UNICODE_CASE | (?u)
Pattern.UNIX_LINES | (?d)

Using the matches(String,CharSequence) Method

The Pattern class defines a convenient matches method that allows you to quickly check if a pattern is present in a given input string. As with all public static methods, you should invoke matches by its class name, such as Pattern.matches("\\d","1");. In this example, the method returns true, because the digit "1" matches the regular expression \d.

Using the split(String) Method

The split method is a great tool for gathering the text that lies on either side of the pattern that's been matched. As shown below in SplitDemo.java, the split method could extract the words "one two three four five" from the string "one:two:three:four:five":
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class SplitDemo {

    private static final String REGEX = ":";
    private static final String INPUT = "one:two:three:four:five";

    public static void main(String[] args) {
        Pattern p = Pattern.compile(REGEX);
        String[] items = p.split(INPUT);
        for(String s : items) {
            System.out.println(s);
        }
    }
}

OUTPUT:

one
two
three
four
five
For simplicity, we've matched a string literal, the colon (:) instead of a complex regular expression. Since we're still using Pattern and Matcher objects, you can use split to get the text that falls on either side of any regular expression. Here's the same example, SplitDemo2.java, modified to split on digits instead:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class SplitDemo2 {

    private static final String REGEX = "\\d";
    private static final String INPUT = "one9two4three7four1five";

    public static void main(String[] args) {
        Pattern p = Pattern.compile(REGEX);
        String[] items = p.split(INPUT);
        for(String s : items) {
            System.out.println(s);
        }
    }
}

OUTPUT:

one
two
three
four
five

Other Utility Methods

You may find the following methods to be of some use as well:
  • public static String quote(String s) Returns a literal pattern String for the specified String. This method produces a String that can be used to create a Pattern that would match String s as if it were a literal pattern. Metacharacters or escape sequences in the input sequence will be given no special meaning.

  • public String toString() Returns the String representation of this pattern. This is the regular expression from which this pattern was compiled.

Pattern Method Equivalents in java.lang.String

Regular expression support also exists in java.lang.String through several methods that mimic the behavior of java.util.regex.Pattern. For convenience, key excerpts from their API are presented below.
  • public boolean matches(String regex): Tells whether or not this string matches the given regular expression. An invocation of this method of the form str.matches(regex) yields exactly the same result as the expression Pattern.matches(regex, str).

  • public String[] split(String regex, int limit): Splits this string around matches of the given regular expression. An invocation of this method of the form str.split(regex, n) yields the same result as the expression Pattern.compile(regex).split(str, n)

  • public String[] split(String regex): Splits this string around matches of the given regular expression. This method works the same as if you invoked the two-argument split method with the given expression and a limit argument of zero. Trailing empty strings are not included in the resulting array.
There is also a replace method, that replaces one CharSequence with another:
  • public String replace(CharSequence target,CharSequence replacement): Replaces each substring of this string that matches the literal target sequence with the specified literal replacement sequence. The replacement proceeds from the beginning of the string to the end, for example, replacing "aa" with "b" in the string "aaa" will result in "ba" rather than "ab".

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Boundary Matchers
Next page: Methods of the Matcher Class


Methods of the Matcher Class (The Java™ Tutorials > Essential Classes > Regular Expressions)

Trail: Essential Classes
Lesson: Regular Expressions
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises
Home Page > Essential Classes > Regular Expressions
« Previous • Trail • Next »
Methods of the Matcher Class
This section describes some additional useful methods of the Matcher class. For convenience, the methods listed below are grouped according to functionality.

Index Methods

Index methods provide useful index values that show precisely where the match was found in the input string:
  • public int start(): Returns the start index of the previous match.
  • public int start(int group): Returns the start index of the subsequence captured by the given group during the previous match operation.
  • public int end(): Returns the offset after the last character matched.
  • public int end(int group): Returns the offset after the last character of the subsequence captured by the given group during the previous match operation.

Study Methods

Study methods review the input string and return a boolean indicating whether or not the pattern is found.
  • public boolean lookingAt(): Attempts to match the input sequence, starting at the beginning of the region, against the pattern.
  • public boolean find(): Attempts to find the next subsequence of the input sequence that matches the pattern.
  • public boolean find(int start): Resets this matcher and then attempts to find the next subsequence of the input sequence that matches the pattern, starting at the specified index.
  • public boolean matches(): Attempts to match the entire region against the pattern.

Replacement Methods

Replacement methods are useful methods for replacing text in an input string.
  • public Matcher appendReplacement(StringBuffer sb, String replacement): Implements a non-terminal append-and-replace step.
  • public StringBuffer appendTail(StringBuffer sb): Implements a terminal append-and-replace step.
  • public String replaceAll(String replacement): Replaces every subsequence of the input sequence that matches the pattern with the given replacement string.
  • public String replaceFirst(String replacement): Replaces the first subsequence of the input sequence that matches the pattern with the given replacement string.
  • public static String quoteReplacement(String s): Returns a literal replacement String for the specified String. This method produces a String that will work as a literal replacement s in the appendReplacement method of the Matcher class. The String produced will match the sequence of characters in s treated as a literal sequence. Slashes ('\') and dollar signs ('$') will be given no special meaning.

Using the start and end Methods

Here's an example, MatcherDemo.java, that counts the number of times the word "dog" appears in the input string.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class MatcherDemo {

    private static final String REGEX = "\\bdog\\b";
    private static final String INPUT = "dog dog dog doggie dogg";

    public static void main(String[] args) {
       Pattern p = Pattern.compile(REGEX);
       Matcher m = p.matcher(INPUT); // get a matcher object
       int count = 0;
       while(m.find()) {
           count++;
           System.out.println("Match number "+count);
           System.out.println("start(): "+m.start());
           System.out.println("end(): "+m.end());
       }
    }
}

OUTPUT:

Match number 1
start(): 0
end(): 3
Match number 2
start(): 4
end(): 7
Match number 3
start(): 8
end(): 11
You can see that this example uses word boundaries to ensure that the letters "d" "o" "g" are not merely a substring in a longer word. It also gives some useful information about where in the input string the match has occurred. The start method returns the start index of the subsequence captured by the given group during the previous match operation, and end returns the index of the last character matched, plus one.

Using the matches and lookingAt Methods

The matches and lookingAt methods both attempt to match an input sequence against a pattern. The difference, however, is that matches requires the entire input sequence to be matched, while lookingAt does not. Both methods always start at the beginning of the input string. Here's the full code, MatchesLooking.java:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class MatchesLooking {

    private static final String REGEX = "foo";
    private static final String INPUT = "fooooooooooooooooo";
    private static Pattern pattern;
    private static Matcher matcher;

    public static void main(String[] args) {

      // Initialize
        pattern = Pattern.compile(REGEX);
        matcher = pattern.matcher(INPUT);

        System.out.println("Current REGEX is: "+REGEX);
        System.out.println("Current INPUT is: "+INPUT);

        System.out.println("lookingAt(): "+matcher.lookingAt());
        System.out.println("matches(): "+matcher.matches());

    }
}

Current REGEX is: foo
Current INPUT is: fooooooooooooooooo
lookingAt(): true
matches(): false

Using replaceFirst(String) and replaceAll(String)

The replaceFirst and replaceAll methods replace text that matches a given regular expression. As their names indicate, replaceFirst replaces the first occurrence, and replaceAll replaces all occurences. Here's the ReplaceDemo.java code:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class ReplaceDemo {

    private static String REGEX = "dog";
    private static String INPUT = "The dog says meow. All dogs say meow.";
    private static String REPLACE = "cat";

    public static void main(String[] args) {
        Pattern p = Pattern.compile(REGEX);
        Matcher m = p.matcher(INPUT); // get a matcher object
        INPUT = m.replaceAll(REPLACE);
        System.out.println(INPUT);
    }
}

OUTPUT: The cat says meow. All cats say meow.
In this first version, all occurrences of dog are replaced with cat. But why stop here? Rather than replace a simple literal like dog, you can replace text that matches any regular expression. The API for this method states that "given the regular expression a*b, the input aabfooaabfooabfoob, and the replacement string -, an invocation of this method on a matcher for that expression would yield the string -foo-foo-foo-."

Here's the ReplaceDemo2.java code:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class ReplaceDemo2 {

    private static String REGEX = "a*b";
    private static String INPUT = "aabfooaabfooabfoob";
    private static String REPLACE = "-";

    public static void main(String[] args) {
        Pattern p = Pattern.compile(REGEX);
        Matcher m = p.matcher(INPUT); // get a matcher object
        INPUT = m.replaceAll(REPLACE);
        System.out.println(INPUT);
    }
}

OUTPUT: -foo-foo-foo-
To replace only the first occurrence of the pattern, simply call replaceFirst instead of replaceAll. It accepts the same parameter.

Using appendReplacement(StringBuffer,String) and appendTail(StringBuffer)

The Matcher class also provides appendReplacement and appendTail methods for text replacement. The following example, RegexDemo.java, uses these two methods to achieve the same effect as replaceAll.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.regex.Pattern;
import java.util.regex.Matcher;

public class RegexDemo {

    private static String REGEX = "a*b";
    private static String INPUT = "aabfooaabfooabfoob";
    private static String REPLACE = "-";

    public static void main(String[] args) {
        Pattern p = Pattern.compile(REGEX);
        Matcher m = p.matcher(INPUT); // get a matcher object
        StringBuffer sb = new StringBuffer();
        while(m.find()){
            m.appendReplacement(sb,REPLACE);
        }
        m.appendTail(sb);
        System.out.println(sb.toString());
    }
}

OUTPUT: -foo-foo-foo-

Matcher Method Equivalents in java.lang.String

For convenience, the String class mimics a couple of Matcher methods as well:
  • public String replaceFirst(String regex, String replacement): Replaces the first substring of this string that matches the given regular expression with the given replacement. An invocation of this method of the form str.replaceFirst(regex, repl) yields exactly the same result as the expression Pattern.compile(regex).matcher(str).replaceFirst(repl)

  • public String replaceAll(String regex, String replacement): Replaces each substring of this string that matches the given regular expression with the given replacement. An invocation of this method of the form str.replaceAll(regex, repl) yields exactly the same result as the expression Pattern.compile(regex).matcher(str).replaceAll(repl)

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Methods of the Pattern Class
Next page: Methods of the PatternSyntaxException Class


Methods of the PatternSyntaxException Class (The Java™ Tutorials > Essential Classes > Regular Expressions)

Trail: Essential Classes
Lesson: Regular Expressions
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises
Home Page > Essential Classes > Regular Expressions
« Previous • Trail • Next »
Methods of the PatternSyntaxException Class
A PatternSyntaxException is an unchecked exception that indicates a syntax error in a regular expression pattern. The PatternSyntaxException class provides the following methods to help you determine what went wrong:
  • public String getDescription(): Retrieves the description of the error.
  • public int getIndex(): Retrieves the error index.
  • public String getPattern(): Retrieves the erroneous regular expression pattern.
  • public String getMessage(): Returns a multi-line string containing the description of the syntax error and its index, the erroneous regular-expression pattern, and a visual indication of the error index within the pattern.
The following source code, RegexTestHarness2.java, updates our test harness to check for malformed regular expressions:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.Console;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.regex.PatternSyntaxException;

public class RegexTestHarness2 {

    public static void main(String[] args){
        Pattern pattern = null;
        Matcher matcher = null;

        Console console = System.console();
        if (console == null) {
            System.err.println("No console.");
            System.exit(1);
        }
        while (true) {
            try{
                pattern =
                Pattern.compile(console.readLine("%nEnter your regex: "));

                matcher =
                pattern.matcher(console.readLine("Enter input string to search: "));
            }
            catch(PatternSyntaxException pse){
                console.format("There is a problem with the regular expression!%n");
                console.format("The pattern in question is: %s%n",pse.getPattern());
                console.format("The description is: %s%n",pse.getDescription());
                console.format("The message is: %s%n",pse.getMessage());
                console.format("The index is: %s%n",pse.getIndex());
                System.exit(0);
            }
            boolean found = false;
            while (matcher.find()) {
                console.format("I found the text \"%s\" starting at " +
                   "index %d and ending at index %d.%n",
                    matcher.group(), matcher.start(), matcher.end());
                found = true;
            }
            if(!found){
                console.format("No match found.%n");
            }
        }
    }
}
To run this test, enter ?i)foo as the regular expression. This mistake is a common scenario in which the programmer has forgotten the opening parenthesis in the embedded flag expression (?i). Doing so will produce the following results:
Enter your regex: ?i)
There is a problem with the regular expression!
The pattern in question is: ?i)
The description is: Dangling meta character '?'
The message is: Dangling meta character '?' near index 0
?i)
^
The index is: 0
From this output, we can see that the syntax error is a dangling metacharacter (the question mark) at index 0. A missing opening parenthesis is the culprit.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Methods of the Matcher Class
Next page: Additional Resources


Additional Resources (The Java™ Tutorials > Essential Classes > Regular Expressions)

Trail: Essential Classes
Lesson: Regular Expressions
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises
Home Page > Essential Classes > Regular Expressions
« Previous • Trail • Next »
Additional Resources
Now that you've completed this lesson on regular expressions, you'll probably find that your main references will be the API documentation for the following classes: Pattern, Matcher, and PatternSyntaxException.

For a more precise description of the behavior of regular expression constructs, we recommend reading the book Mastering Regular Expressions by Jeffrey E. F. Friedl.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Methods of the PatternSyntaxException Class
Next page: Questions and Exercises: Regular Expressions


Questions and Exercises: Regular Expressions (The Java™ Tutorials > Essential Classes > Regular Expressions)

Trail: Essential Classes
Lesson: Regular Expressions
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises
Home Page > Essential Classes > Regular Expressions
« Previous • Trail • Next »
Questions and Exercises: Regular Expressions

Questions

  1. What are the three public classes in the java.util.regex package? Describe the purpose of each.
  2. Consider the string literal "foo". What is the start index? What is the end index? Explain what these numbers mean.
  3. What is the difference between an ordinary character and a metacharacter? Give an example of each.
  4. How do you force a metacharacter to act like an ordinary character?
  5. What do you call a set of characters enclosed in square brackets? What is it for?
  6. Here are three predefined character classes: \d, \s, and \w. Describe each one, and rewrite it using square brackets.
  7. For each of \d, \s, and \w, write two simple expressions that match the opposite set of characters.
  8. Consider the regular expression (dog){3}. Identify the two subexpressions. What string does the expression match?

Exercises

  1. Use a backreference to write an expression that will match a person's name only if that person's first name and last name are the same.

Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Additional Resources
Next page: End of Trail


Trail: Deployment (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Deployment

This trail discusses deploying your Java applications and applets.

Java versions 1.4.2, 1.5.0 and 1.6.0 bundle two deployment technologies:

  • Java Web Start, for deploying Java applications
  • Java Plug-in, for deploying Java applets

We recommend using Java Plug-in to deploy applets when you want your application to run within a browser, or when the application is tightly integrated with web page content.

We recommend using Java Web Start when you want your application to run stand-alone, on your users' desktops.

Java Web Start requires that applications be packed in JAR files, which is why the JAR lesson is included in this trail.

Packaging Programs in JAR Files

Deploying Applications with Java Web Start

Creating and Deploying Applets with Java Plug-in

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Packaging Programs in JAR Files


Lesson: Packaging Programs in JAR Files (The Java™ Tutorials > Deployment)

Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Trail: Deployment
Home Page > Deployment
« Previous • Trail • Next »
Lesson: Packaging Programs in JAR Files
The JavaTM Archive (JAR) file format enables you to bundle multiple files into a single archive file. Typically a JAR file contains the class files and auxiliary resources associated with applets and applications.

The JAR file format provides many benefits:

  • Security: You can digitally sign the contents of a JAR file. Users who recognize your signature can then optionally grant your software security privileges it wouldn't otherwise have.
  • Decreased download time: If your applet is bundled in a JAR file, the applet's class files and associated resources can be downloaded to a browser in a single HTTP transaction without the need for opening a new connection for each file.
  • Compression: The JAR format allows you to compress your files for efficient storage.
  • Packaging for extensions: The extensions framework provides a means by which you can add functionality to the Java core platform, and the JAR file format defines the packaging for extensions. Java 3D™ and JavaMail™ are examples of extensions developed by SunTM. By using the JAR file format, you can turn your software into extensions as well.
  • Package Sealing: Packages stored in JAR files can be optionally sealed so that the package can enforce version consistency. Sealing a package within a JAR file means that all classes defined in that package must be found in the same JAR file.
  • Package Versioning: A JAR file can hold data about the files it contains, such as vendor and version information.
  • Portability: The mechanism for handling JAR files is a standard part of the Java platform's core API.

This lesson has four sections:

Using JAR Files: The Basics

This section shows you how to perform basic JAR-file operations, and how to run software that is bundled in JAR files.

Working with Manifest Files: The Basics

This section explains manifest files and how to customize them so you can do such things as seal packages and set an application's entry point.

Signing and Verifying JAR Files

This section shows you how to digitally sign JAR files and verify the signatures of signed JAR files.

Using JAR-related APIs

This section introduces you to some of the JAR-handling features of the Java platform. The JAR file format is an important part of the Java platform's extension mechanism. You can learn more about that aspect of JAR files in the The Extension Mechanism trail of this tutorial.

Questions and Exercises: JAR

Test what you've learned about JAR.

Additional References

The documentation for the Java Development Kit includes information about the Jar tool:
  • Java Archive (JAR) Files Guide
  • JAR File Specification
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: Using JAR Files: The Basics


Using JAR Files: The Basics (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Using JAR Files: The Basics
JAR files are packaged with the ZIP file format, so you can use them for tasks such as lossless data compression, archiving, decompression, and archive unpacking. These tasks are among the most common uses of JAR files, and you can realize many JAR file benefits using only these basic features.

Even if you want to take advantage of advanced functionality provided by the JAR file format such as electronic signing, you'll first need to become familiar with the fundamental operations.

To perform basic tasks with JAR files, you use the JavaTM Archive Tool provided as part of the Java Development Kit. Because the Java Archive tool is invoked by using the jar command, this tutorial refers to it as 'the Jar tool'.

As a synopsis and preview of some of the topics to be covered in this section, the following table summarizes common JAR file operations:

Common JAR file operations
Operation | Command
To create a JAR file | jar cf jar-file input-file(s)
To view the contents of a JAR file | jar tf jar-file
To extract the contents of a JAR file | jar xf jar-file
To extract specific files from a JAR file | jar xf jar-file archived-file(s)
To run an application packaged as a JAR file (requires the Main-class manifest header)
java -jar app.jar
To invoke an applet packaged as a JAR file
<applet code=AppletClassName.class
        archive="JarFileName.jar"
        width=width height=height>
</applet>

This section shows you how to perform the most common JAR-file operations, with examples for each of the basic features:

Creating a JAR File

This section shows you how to use the Jar tool to package files and directories into a JAR file.

Viewing the Contents of a JAR File

You can display a JAR file's table of contents to see what it contains without actually unpacking the JAR file.

Extracting the Contents of a JAR File

You can use the Jar tool to unpack a JAR file. When extracting files, the Jar tool makes copies of the desired files and writes them to the current directory, reproducing the directory structure that the files have in the archive.

Updating a JAR File

This section shows you how to update the contents of an existing JAR file by modifying its manifest or by adding files.

Running JAR-Packaged Software

This section shows you how to invoke and run applets and applications that are packaged in JAR files.

Additional References

The documentation for the Java Development Kit includes reference pages for the Jar tool:
  • Jar tool reference for Windows platform
  • Jar tool reference for Solaris platform

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Packaging Programs in JAR Files
Next page: Creating a JAR File


Creating a JAR File (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Using JAR Files: The Basics
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Creating a JAR File
The basic format of the command for creating a JAR file is:
jar cf jar-file input-file(s)
The options and arguments used in this command are:
  • The c option indicates that you want to create a JAR file.
  • The f option indicates that you want the output to go to a file rather than to stdout.
  • jar-file is the name that you want the resulting JAR file to have. You can use any filename for a JAR file. By convention, JAR filenames are given a .jar extension, though this is not required.
  • The input-file(s) argument is a space-separated list of one or more files that you want to include in your JAR file. The input-file(s) argument can contain the wildcard * symbol. If any of the "input-files" are directories, the contents of those directories are added to the JAR archive recursively.

The c and f options can appear in either order, but there must not be any space between them.

This command will generate a compressed JAR file and place it in the current directory. The command will also generate a default manifest file for the JAR archive.

Note: The metadata in the JAR file, such as the entry names, comments, and contents of the manifest, must be encoded in UTF8.

You can add any of these additional options to the cf options of the basic command:
jar command options
Option | Description
v | Produces verbose output on stdout while the JAR file is being built. The verbose output tells you the name of each file as it's added to the JAR file.
0 (zero) | Indicates that you don't want the JAR file to be compressed.
M | Indicates that the default manifest file should not be produced.
m Used to include manifest information from an existing manifest file. The format for using this option is:
jar cmf existing-manifest jar-file input-file(s)
See Modifying a Manifest File for more information about his option.
Warning: The manifest must end with a new line or carriage return. The last line will not be parsed properly if it does not end with a new line or carriage return.
-C | To change directories during execution of the command. See below for an example.

Note: When you create a JAR file, the time of creation is stored in the JAR file. Therefore, even if the contents of the JAR file do not change, when you create a JAR file multiple times, the resulting files are not exactly identical. You should be aware of this when you are using JAR files in a build environment. It is recommended that you use versioning information in the manifest file, rather than creation time, to control versions of a JAR file. See the Setting Package Version Information section.

An Example

Let us look at an example. A simple TicTacToe applet. You can see the source code of this Applet at TicTacToe.java. This demo contains a bytecode class file, audio files, and images having this structure:

TicTacToe folder Hierarchy

TicTacToe folder Hierarchy

The audio and images subdirectories contain sound files and GIF images used by the applet.

You can obtain all these files from jar/examples directory when you download the entire Tutorial online. To package this demo into a single JAR file named TicTacToe.jar, you would run this command from inside the TicTacToe directory:

jar cvf TicTacToe.jar TicTacToe.class audio images
The audio and images arguments represent directories, so the Jar tool will recursively place them and their contents in the JAR file. The generated JAR file TicTacToe.jar will be placed in the current directory. Because the command used the v option for verbose output, you would see something similar to this output when you run the command:
adding: TicTacToe.class (in=3825) (out=2222) (deflated 41%)
adding: audio/ (in=0) (out=0) (stored 0%)
adding: audio/beep.au (in=4032) (out=3572) (deflated 11%)
adding: audio/ding.au (in=2566) (out=2055) (deflated 19%)
adding: audio/return.au (in=6558) (out=4401) (deflated 32%)
adding: audio/yahoo1.au (in=7834) (out=6985) (deflated 10%)
adding: audio/yahoo2.au (in=7463) (out=4607) (deflated 38%)
adding: images/ (in=0) (out=0) (stored 0%)
adding: images/cross.gif (in=157) (out=160) (deflated -1%)
adding: images/not.gif (in=158) (out=161) (deflated -1%)

You can see from this output that the JAR file TicTacToe.jar is compressed. The Jar tool compresses files by default. You can turn off the compression feature by using the 0 (zero) option, so that the command would look like:

jar cvf0 TicTacToe.jar TicTacToe.class audio images

You might want to avoid compression, for example, to increase the speed with which a JAR file could be loaded by a browser. Uncompressed JAR files can generally be loaded more quickly than compressed files because the need to decompress the files during loading is eliminated. However, there is a tradeoff in that download time over a network may be longer for larger, uncompressed files.

The Jar tool will accept arguments that use the wildcard * symbol. As long as there weren't any unwanted files in the TicTacToe directory, you could have used this alternative command to construct the JAR file:

jar cvf TicTacToe.jar *

Though the verbose output doesn't indicate it, the Jar tool automatically adds a manifest file to the JAR archive with path name META-INF/MANIFEST.MF. See the Working with Manifest Files: The Basics section for information about manifest files.

In the above example, the files in the archive retained their relative path names and directory structure. The Jar tool provides the -C option that you can use to create a JAR file in which the relative paths of the archived files are not preserved. It's modeled after TAR's -C option.

As an example, suppose you wanted to put audio files and gif images used by the TicTacToe demo into a JAR file, and that you wanted all the files to be on the top level, with no directory hierarchy. You could accomplish that by issuing this command from the parent directory of the images and audio directories:

jar cf ImageAudio.jar -C images . -C audio .
The -C images part of this command directs the Jar tool to go to the images directory, and the . following -C images directs the Jar tool to archive all the contents of that directory. The -C audio . part of the command then does the same with the audio directory. The resulting JAR file would have this table of contents:
META-INF/MANIFEST.MF
cross.gif
not.gif
beep.au
ding.au
return.au
yahoo1.au
yahoo2.au
By contrast, suppose that you used a command that did not employ the -C option:
jar cf ImageAudio.jar images audio
The resulting JAR file would have this table of contents:
META-INF/MANIFEST.MF
images/cross.gif
images/not.gif
audio/beep.au
audio/ding.au
audio/return.au
audio/yahoo1.au
audio/yahoo2.au

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using JAR Files: The Basics
Next page: Viewing the Contents of a JAR File


Viewing the Contents of a JAR File (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Using JAR Files: The Basics
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Viewing the Contents of a JAR File
The basic format of the command for viewing the contents of a JAR file is:
jar tf jar-file
Let's look at the options and argument used in this command:
  • The t option indicates that you want to view the table of contents of the JAR file.
  • The f option indicates that the JAR file whose contents are to be viewed is specified on the command line.
  • The jar-file argument is the path and name of the JAR file whose contents you want to view.

The t and f options can appear in either order, but there must not be any space between them.

This command will display the JAR file's table of contents to stdout.

You can optionally add the verbose option, v, to produce additional information about file sizes and last-modified dates in the output.

An Example

Let's use the Jar tool to list the contents of the TicTacToe.jar file we created in the previous section:
jar tf TicTacToe.jar

This command displays the contents of the JAR file to stdout:

META-INF/MANIFEST.MF
TicTacToe.class
audio/
audio/beep.au
audio/ding.au
audio/return.au
audio/yahoo1.au
audio/yahoo2.au
images/
images/cross.gif
images/not.gif

The JAR file contains the TicTacToe class file and the audio and images directory, as expected. The output also shows that JAR file contains a default manifest file, META-INF/MANIFEST.MF, which was automatically placed in the archive by the JAR tool. For more information, see the Understanding the Default Manifest section.

All pathnames are displayed with forward slashes, regardless of the platform or operating system you're using. Paths in JAR files are always relative; you'll never see a path beginning with C:, for example.

The JAR tool will display additional information if you use the v option:

jar tvf TicTacToe.jar

For example, the verbose output for the TicTacToe JAR file would look similar to this:

 256 Mon Apr 18 10:50:28 PDT 2005 META-INF/MANIFEST.MF
3885 Mon Apr 18 10:49:50 PDT 2005 TicTacToe.class
   0 Wed Apr 20 16:39:32 PDT 2005 audio/
4032 Wed Apr 20 16:39:32 PDT 2005 audio/beep.au
2566 Wed Apr 20 16:39:32 PDT 2005 audio/ding.au
6558 Wed Apr 20 16:39:32 PDT 2005 audio/return.au
7834 Wed Apr 20 16:39:32 PDT 2005 audio/yahoo1.au
7463 Wed Apr 20 16:39:32 PDT 2005 audio/yahoo2.au
   0 Wed Apr 20 16:39:44 PDT 2005 images/
 157 Wed Apr 20 16:39:44 PDT 2005 images/cross.gif
 158 Wed Apr 20 16:39:44 PDT 2005 images/not.gif
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating a JAR File
Next page: Extracting the Contents of a JAR File


Extracting the Contents of a JAR File (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Using JAR Files: The Basics
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Extracting the Contents of a JAR File
The basic command to use for extracting the contents of a JAR file is:
jar xf jar-file [archived-file(s)]

Let's look at the options and arguments in this command:

  • The x option indicates that you want to extract files from the JAR archive.
  • The f options indicates that the JAR file from which files are to be extracted is specified on the command line, rather than through stdin.
  • The jar-file argument is the filename (or path and filename) of the JAR file from which to extract files.
  • archived-file(s) is an optional argument consisting of a space-separated list of the files to be extracted from the archive. If this argument is not present, the Jar tool will extract all the files in the archive.

As usual, the order in which the x and f options appear in the command doesn't matter, but there must not be a space between them.

When extracting files, the Jar tool makes copies of the desired files and writes them to the current directory, reproducing the directory structure that the files have in the archive. The original JAR file remains unchanged.

Caution: When it extracts files, the Jar tool will overwrite any existing files having the same pathname as the extracted files.

An Example

Let's extract some files from the TicTacToe JAR file we've been using in previous sections. Recall that the contents of TicTacToe.jar are:
META-INF/MANIFEST.MF
TicTacToe.class
audio/
audio/beep.au
audio/ding.au
audio/return.au
audio/yahoo1.au
audio/yahoo2.au
images/
images/cross.gif
images/not.gif

Suppose you want to extract the TicTacToe class file and the cross.gif image file. To do so, you can use this command:

jar xf TicTacToe.jar TicTacToe.class images/cross.gif

This command does two things:

  • It places a copy of TicTacToe.class in the current directory.
  • It creates the directory images, if it doesn't already exist, and places a copy of cross.gif within it.

The original TicTacToe JAR file remains unchanged.

As many files as desired can be extracted from the JAR file in the same way. When the command doesn't specify which files to extract, the Jar tool extracts all files in the archive. For example, you can extract all the files in the TicTacToe archive by using this command:

jar xf TicTacToe.jar

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Viewing the Contents of a JAR File
Next page: Updating a JAR File


Updating a JAR File (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Using JAR Files: The Basics
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Updating a JAR File
The Jar tool provides a u option which you can use to update the contents of an existing JAR file by modifying its manifest or by adding files.

The basic command for adding files has this format:

jar uf jar-file input-file(s)

In this command:

  • The u option indicates that you want to update an existing JAR file.
  • The f option indicates that the JAR file to update is specified on the command line.
  • jar-file is the existing JAR file that's to be updated.
  • input-file(s) is a space-deliminated list of one or more files that you want to add to the Jar file.

Any files already in the archive having the same pathname as a file being added will be overwritten.

When creating a new JAR file, you can optionally use the -C option to indicate a change of directory. For more information, see the Creating a JAR File section.

Examples

Recall that TicTacToe.jar has these contents:
META-INF/MANIFEST.MF
TicTacToe.class
audio/
audio/beep.au
audio/ding.au
audio/return.au
audio/yahoo1.au
audio/yahoo2.au
images/
images/cross.gif
images/not.gif

Suppose that you want to add the file images/new.gif to the JAR file. You could accomplish that by issuing this command from the parent directory of the images directory:

jar uf TicTacToe.jar images/new.gif

The revised JAR file would have this table of contents:

META-INF/MANIFEST.MF
TicTacToe.class
audio/
audio/beep.au
audio/ding.au
audio/return.au
audio/yahoo1.au
audio/yahoo2.au
images/
images/cross.gif
images/not.gif
images/new.gif

You can use the -C option to "change directories" during execution of the command. For example:

jar uf TicTacToe.jar -C images new.gif
This command would change to the images directory before adding new.gif to the JAR file. The images directory would not be included in the pathname of new.gif when it's added to the archive, resulting in a table of contents that looks like this:
META-INF/MANIFEST.MF
TicTacToe.class
audio/
audio/beep.au
audio/ding.au
audio/return.au
audio/yahoo1.au
audio/yahoo2.au
images/
images/cross.gif
images/not.gif
new.gif
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Extracting the Contents of a JAR File
Next page: Running JAR-Packaged Software


Running JAR-Packaged Software (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Using JAR Files: The Basics
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Running JAR-Packaged Software
Now that you've learned how to create JAR files, how do you actually run the code that you've packaged? Consider these three scenarios:
  • Your JAR file contains an applet that is to be run inside a browser.
  • Your JAR file contains an application that is to be invoked from the command line.
  • Your JAR file contains code that you want to use as an extension.

This section will cover the first two situations. A separate trail in the tutorial on the extension mechanism covers the use of JAR files as extensions.

Applets Packaged in JAR Files

To invoke any applet from an HTML file for running inside a browser, you need to use the APPLET tag. For more information, see the Applets lesson. If the applet is bundled as a JAR file, the only thing you need to do differently is to use the ARCHIVE parameter to specify the relative path to the JAR file.

As an example, let's use (again!) the TicTacToe demo applet that ships with the JavaTM Development Kit. The APPLET tag in the HTML file that calls the demo looks like this:

<applet code=TicTacToe.class
        width=120 height=120>
</applet>
If the TicTacToe demo were packaged in a JAR file named TicTacToe.jar, you could modify the APPLET tag with the simple addition of an ARCHIVE parameter:
<applet code=TicTacToe.class
        archive="TicTacToe.jar"
        width=120 height=120>
</applet>
The ARCHIVE parameter specifies the relative path to the JAR file that contains TicTacToe.class. This example assumes that the JAR file and the HTML file are in the same directory. If they're not, you would need to include the JAR file's relative path in the ARCHIVE parameter's value. For example, if the JAR file was one directory below the HTML file in a directory called applets, the APPLET tag would look like this:
<applet code=TicTacToe.class
        archive="applets/TicTacToe.jar"
        width=120 height=120>
</applet>

JAR Files as Applications

You can run JAR-packaged applications with the Java interpreter. The basic command is:
java -jar jar-file
The -jar flag tells the interpreter that the application is packaged in the JAR file format. You can only specify one JAR file, which must contain all the application-specific code.

Before you execute this command make sure the runtime environment has an information of which class within the JAR file is the application's entry point.

To indicate which class is the application's entry point, you must add a Main-Class header to the JAR file's manifest. The header takes the form:

Main-Class: classname
The header's value, classname, is the name of the class that's the application's entry point.

For more information, see the Setting an Application's Entry Point section.

When the Main-Class is set in the manifest file, you can run the application from the command line:

java -jar app.jar
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Updating a JAR File
Next page: Working with Manifest Files: The Basics


Working with Manifest Files: The Basics (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Working with Manifest Files: The Basics
JAR files support a wide range of functionality, including electronic signing, version control, package sealing, and others. What gives a JAR file this versatility? The answer is the JAR file's manifest.

The manifest is a special file that can contain information about the files packaged in a JAR file. By tailoring this "meta" information that the manifest contains, you enable the JAR file to serve a variety of purposes.

This lesson will explain the contents of the manifest file and show you how to work with it, with examples for the basic features:

Understanding the Default Manifest

When you create a JAR file, a default manifest is created automatically. This section describes the default manifest.

Modifying a Manifest File

This section shows you the basic method of modifying a manifest file. The later sections demonstrate specific modifications you may want to make.

Setting an Application's Entry Point

This section describes how to use the Main-Class header in the manifest file to set an application's entry point.

Adding Classes to the JAR File's Classpath

This section describes how to use the Class-Path header in the manifest file to add classes in other JAR files to the classpath when running an applet or application.

Setting Package Version Information

This section describes how to use the package version headers in the manifest file.

Sealing Packages within a JAR File

This section describes how to seal packages within a JAR file by modifying the manifest file.

Additional Information

A specification of the manifest format is part of the on-line JDK documentation.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Running JAR-Packaged Software
Next page: Understanding the Default Manifest


Understanding the Default Manifest (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Working with Manifest Files: The Basics
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Understanding the Default Manifest
When you create a JAR file, it automatically receives a default manifest file. There can be only one manifest file in an archive, and it always has the pathname
META-INF/MANIFEST.MF

When you create a JAR file, the default manifest file simply contains the following:

Manifest-Version: 1.0
Created-By: 1.6.0 (Sun Microsystems Inc.)

These lines show that a manifest's entries take the form of "header: value" pairs. The name of a header is separated from its value by a colon. The default manifest conforms to version 1.0 of the manifest specification and was created by the 1.6.0 version of the JDK.

The manifest can also contain information about the other files that are packaged in the archive. Exactly what file information should be recorded in the manifest depends on how you intend to use the JAR file. The default manifest makes no assumptions about what information it should record about other files.

Digest information is not included in the default manifest. To learn more about digests and signing, see the Signing and Verifying JAR Files lesson.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Working with Manifest Files: The Basics
Next page: Modifying a Manifest File


Modifying a Manifest File (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Working with Manifest Files: The Basics
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Modifying a Manifest File
You use the m command-line option to add custom information to the manifest during creation of a JAR file. This section describes the m option.

The Jar tool automatically puts a default manifest with the pathname META-INF/MANIFEST.MF into any JAR file you create. You can enable special JAR file functionality, such as package sealing, by modifying the default manifest. Typically, modifying the default manifest involves adding special-purpose headers to the manifest that allow the JAR file to perform a particular desired function.

To modify the manifest, you must first prepare a text file containing the information you wish to add to the manifest. You then use the Jar tool's m option to add the information in your file to the manifest.

Warning : The text file from which you are creating the manifest must end with a new line or carriage return. The last line will not be parsed properly if it does not end with a new line or carriage return.

The basic command has this format:

jar cfm jar-file manifest-addition input-file(s)

Let's look at the options and arguments used in this command:
  • The c option indicates that you want to create a JAR file.
  • The m option indicates that you want to merge information from an existing file into the manifest file of the JAR file you're creating.
  • The f option indicates that you want the output to go to a file (the JAR file you're creating) rather than to standard output.
  • manifest-addition is the name (or path and name) of the existing text file whose contents you want to add to the contents of JAR file's manifest.
  • jar-file is the name that you want the resulting JAR file to have.
  • The input-file(s) argument is a space-separated list of one or more files that you want to be placed in your JAR file.

The m and f options must be in the same order as the corresponding arguments.

Note : The contents of the manifest must be encoded in UTF8.

The remaining sections of this lesson demonstrate specific modifications you may want to make to the manifest file.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Understanding the Default Manifest
Next page: Setting an Application's Entry Point


Setting an Application's Entry Point (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Working with Manifest Files: The Basics
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Setting an Application's Entry Point
If you have an application bundled in a JAR file, you need some way to indicate which class within the JAR file is your application's entry point. You provide this information with the Main-Class header in the manifest, which has the general form:
Main-Class: classname
The value classname is the name of the class that is your application's entry point.

Recall that the entry point is a class having a method with signature public static void main(String[] args).

After you have set the Main-Class header in the manifest, you then run the JAR file using the following form of the java command:

java -jar JAR-name
The main method of the class specified in the Main-Class header is executed.

An Example

We want to execute the main method in the class MyClass in the package MyPackage when we run the JAR file.

We first create a text file named Manifest.txt with the following contents:

Main-Class: MyPackage.MyClass

Warning: The text file must end with a new line or carriage return. The last line will not be parsed properly if it does not end with a new line or carriage return.
We then create a JAR file named MyJar.jar by entering the following command:
jar cfm MyJar.jar Manifest.txt MyPackage/*.class
This creates the JAR file with a manifest with the following contents:
Manifest-Version: 1.0
Created-By: 1.6.0 (Sun Microsystems Inc.)
Main-Class: MyPackage.MyClass
When you run the JAR file with the following command, the main method of MyClass executes:
java -jar MyJar.jar

Setting an Entry Point with the JAR Tool

The 'e' flag (for 'entrypoint'), introduced in JDK 6, creates or overrides the manifest's Main-Class attribute. It can be used while creating or updating a jar file. Use it to specify the application entry point without editing or creating the manifest file.
For example, this command creates app.jar where the Main-Class attribute value in the manifest is set to MyApp:
jar cfe app.jar MyApp MyApp.class

You can directly invoke this application by running the following command:

java -jar app.jar

If the entrypoint class name is in a package it may use a '.' (dot) character as the delimiter. For example, if Main.class is in a package called foo the entry point can be specified in the following ways:

jar cfe Main.jar foo.Main foo/Main.class

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Modifying a Manifest File
Next page: Adding Classes to the JAR File's Classpath


Adding Classes to the JAR File's Classpath (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Working with Manifest Files: The Basics
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Adding Classes to the JAR File's Classpath
You may need to reference classes in other JAR files from within a JAR file.

For example, in a typical situation an applet is bundled in a JAR file whose manifest references a different JAR file (or several different JAR files) that serves as utilities for the purposes of that applet.

You specify classes to include in the Class-Path header field in the manifest file of an applet or application. The Class-Path header takes the following form:

Class-Path: jar1-name jar2-name directory-name/jar3-name
By using the Class-Path header in the manifest, you can avoid having to specify a long -classpath flag when invoking Java to run the your application.

Note : The Class-Path header points to classes or JAR files on the local network, not JAR files within the JAR file or classes accessible over internet protocols. To load classes in JAR files within a JAR file into the class path, you must write custom code to load those classes. For example, if MyJar.jar contains another JAR file called MyUtils.jar, you cannot use the Class-Path header in MyJar.jar's manifest to load classes in MyUtils.jar into the class path.

An Example

We want to load classes in MyUtils.jar into the class path for use in MyJar.jar. These two JAR files are in the same directory.

We first create a text file named Manifest.txt with the following contents:

Class-Path: MyUtils.jar

Warning : The text file must end with a new line or carriage return. The last line will not be parsed properly if it does not end with a new line or carriage return.

We then create a JAR file named MyJar.jar by entering the following command:

jar cfm MyJar.jar Manifest.txt MyPackage/*.class
This creates the JAR file with a manifest with the following contents:
Manifest-Version: 1.0
Class-Path: MyUtils.jar
Created-By: 1.6.0 (Sun Microsystems Inc.)
The classes in MyUtils.jar are now loaded into the class path when you run MyJar.jar.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Setting an Application's Entry Point
Next page: Setting Package Version Information


Setting Package Version Information (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Working with Manifest Files: The Basics
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Setting Package Version Information
You may need to include package version information in a JAR file's manifest. You provide this information with the following headers in the manifest:

Headers in a manifest
Header | Definition
Name | The name of the specification.
Specification-Title | The title of the specification.
Specification-Version | The version of the specification.
Specification-Vendor | The vendor of the specification.
Implementation-Title | The title of the implementation.
Implementation-Version | The build number of the implementation.
Implementation-Vendor | The vendor of the implementation.

One set of such headers can be assigned to each package. The versioning headers should appear directly beneath the Name header for the package. This example shows all the versioning headers:

Name: java/util/
Specification-Title: Java Utility Classes
Specification-Version: 1.2
Specification-Vendor: Sun Microsystems, Inc.
Implementation-Title: java.util
Implementation-Version: build57
Implementation-Vendor: Sun Microsystems, Inc.

For more information about package version headers, see the Package Versioning specification .

An Example

We want to include the headers in the example above in the manifest of MyJar.jar.

We first create a text file named Manifest.txt with the following contents:

Name: java/util/
Specification-Title: Java Utility Classes
Specification-Version: 1.2
Specification-Vendor: Sun Microsystems, Inc.
Implementation-Title: java.util
Implementation-Version: build57
Implementation-Vendor: Sun Microsystems, Inc.
Warning : The text file must end with a new line or carriage return. The last line will not be parsed properly if it does not end with a new line or carriage return.
We then create a JAR file named MyJar.jar by entering the following command:
jar cfm MyJar.jar Manifest.txt MyPackage/*.class
This creates the JAR file with a manifest with the following contents:
Manifest-Version: 1.0
Created-By: 1.6.0 (Sun Microsystems Inc.)
Name: java/util/
Specification-Title: Java Utility Classes
Specification-Version: 1.2
Specification-Vendor: Sun Microsystems, Inc.
Implementation-Title: java.util
Implementation-Version: build57
Implementation-Vendor: Sun Microsystems, Inc.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Adding Classes to the JAR File's Classpath
Next page: Sealing Packages within a JAR File


Sealing Packages within a JAR File (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Working with Manifest Files: The Basics
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Sealing Packages within a JAR File
Packages within JAR files can be optionally sealed, which means that all classes defined in that package must be archived in the same JAR file. You might want to seal a package, for example, to ensure version consistency among the classes in your software.

You seal a package in a JAR file by adding the Sealed header in the manifest, which has the general form:

Name: myCompany/myPackage/
Sealed: true
The value myCompany/myPackage/ is the name of the package to seal.

Note that the package name must end with a "/".

An Example

We want to seal two packages firstPackage and secondPackage in the JAR file MyJar.jar.

We first create a text file named Manifest.txt with the following contents:

Name: myCompany/firstPackage/
Sealed: true

Name: myCompany/secondPackage/
Sealed: true
Warning :

The text file must end with a new line or carriage return. The last line will not be parsed properly if it does not end with a new line or carriage return.
We then create a JAR file named MyJar.jar by entering the following command:
jar cmf MyJar.jar Manifest.txt MyPackage/*.class
This creates the JAR file with a manifest with the following contents:
Manifest-Version: 1.0
Created-By: 1.6.0 (Sun Microsystems Inc.)
Name: myCompany/firstPackage/
Sealed: true
Name: myCompany/secondPackage/
Sealed: true

Sealing JAR Files

If you want to guarantee that all classes in a package come from the same code source, use JAR sealing. A sealed JAR specifies that all packages defined by that JAR are sealed unless overridden on a per-package basis.

To seal a jar file, use the Sealed manifest header with the value true. For example,

Sealed: true
specifies that all packages in this archive are sealed unless explicitly overridden for particular packages with the Sealed attribute in a manifest entry.

For further information on how to seal jar files, see JDC TechTips

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Setting Package Version Information
Next page: Signing and Verifying JAR Files


Signing and Verifying JAR Files (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Signing and Verifying JAR Files
You can optionally sign a JAR file with your electronic "signature." Users who verify your signature can grant your JAR-bundled software security privileges that it wouldn't ordinarily have. Conversely, you can verify the signatures of signed JAR files that you want to use.

This lesson shows you how to use the tools provided in the JavaTM Development Kit to sign and verify JAR files:

Understanding Signing and Verification

If you're not familiar with the concepts of signing and verification, this section will help to bring you up to speed. It contains definitions of the relevant terms, explanations of some of the benefits provided by signing, and an outline of the signing mechanism used by the Java platform as it relates to JAR files.

Signing JAR Files

In this section, you'll learn how to use the JDKTM tools to digitally sign your JAR files.

Verifying Signed JAR Files

This section shows you how to use the JDK tool set to verify signed JAR files.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Sealing Packages within a JAR File
Next page: Understanding Signing and Verification


Understanding Signing and Verification (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Signing and Verifying JAR Files
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Understanding Signing and Verification
The JavaTM platform enables you to digitally sign JAR files. You digitally sign a file for the same reason you might sign a paper document with pen and ink -- to let readers know that you wrote the document, or at least that the document has your approval.

When you sign a letter, for example, everyone who recognizes your signature can confirm that you wrote the letter. Similarly when you digitally sign a file, anyone who "recognizes" your digital signature knows that the file came from you. The process of "recognizing" electronic signatures is called verification.

The ability to sign and verify files is an important part of the Java platform's security architecture. Security is controlled by the security policy that's in force at runtime. You can configure the policy to grant security privileges to applets and to applications. For example, you could grant permission to an applet to perform normally forbidden operations such as reading and writing local files or running local executable programs. If you have downloaded some code that's signed by a trusted entity, you can use that fact as a criterion in deciding which security permissions to assign to the code.

Once you (or your browser) have verified that an applet is from a trusted source, you can have the platform relax security restrictions to let the applet perform operations that would ordinarily be forbidden. A trusted applet can have freedoms as specified by the policy file in force.

The Java platform enables signing and verification by using special numbers called public and private keys. Public keys and private keys come in pairs, and they play complementary roles.

The private key is the electronic "pen" with which you can sign a file. As its name implies, your private key is known only to you so that no one else can "forge" your signature. A file signed with your private key can be verified only by the corresponding public key.

Public and private keys alone, however, aren't enough to truly verify a signature. Even if you've verified that a signed file contains a matching key pair, you still need some way to confirm that the public key actually comes from the signer that it purports to come from.

One more element, therefore, is required to make signing and verification work. That additional element is the certificate that the signer includes in a signed JAR file. A certificate is a digitally signed statement from a recognized certification authority that indicates who owns a particular public key. A certification authority are entities (typically firms specializing in digital security) that are trusted throughout the industry to sign and issue certificates for keys and their owners. In the case of signed JAR files, the certificate indicates who owns the public key contained in the JAR file.

When you sign a JAR file your public key is placed inside the archive along with an associated certificate so that it's easily available for use by anyone wanting to verify your signature.

To summarize digital signing:

  • The signer signs the JAR file using a private key.
  • The corresponding public key is placed in the JAR file, together with its certificate, so that it is available for use by anyone who wants to verify the signature.

Digests and the Signature File

When you sign a JAR file, each file in the archive is given a digest entry in the archive's manifest. Here's an example of what such an entry might look like:
Name: test/classes/ClassOne.class
SHA1-Digest: TD1GZt8G11dXY2p4olSZPc5Rj64=
The digest values are hashes or encoded representations of the contents of the files as they were at the time of signing. A file's digest will change if and only if the file itself changes.

When a JAR file is signed, a signature file is automatically generated and placed in the JAR file's META-INF directory, the same directory that contains the archive's manifest. Signature files have filenames with an .SF extension. Here is an example of the contents of a signature file:

Signature-Version: 1.0
SHA1-Digest-Manifest: h1yS+K9T7DyHtZrtI+LxvgqaMYM=
Created-By: 1.6.0 (Sun Microsystems Inc.)

Name: test/classes/ClassOne.class
SHA1-Digest: fcav7ShIG6i86xPepmitOVo4vWY=

Name: test/classes/ClassTwo.class
SHA1-Digest: xrQem9snnPhLySDiZyclMlsFdtM=

Name: test/images/ImageOne.gif
SHA1-Digest: kdHbE7kL9ZHLgK7akHttYV4XIa0=

Name: test/images/ImageTwo.gif
SHA1-Digest: mF0D5zpk68R4oaxEqoS9Q7nhm60=

As you can see, the signature file contains digest entries for the archive's files that look similar to the digest-value entries in the manifest. However, while the digest values in the manifest are computed from the files themselves, the digest values in the signature file are computed from the corresponding entries in the manifest. Signature files also contain a digest value for the entire manifest (see the SHA1-Digest-Manifest header in the above example).

When a signed JAR file is being verified, the digests of each of its files are re-computed and compared with the digests recorded in the manifest to ensure that the contents of the JAR file haven't changed since it was signed. As an additional check, digest values for the manifest file itself are re-computed and compared against the values recorded in the signature file.

You can read additional information about signature files on the Manifest Format page of the JDKTM documentation.

The Signature Block File

In addition to the signature file, a signature block file is automatically placed in the META-INF directory when a JAR file is signed. Unlike the manifest file or the signature file, signature block files are not human-readable.

The signature block file contains two elements essential for verification:

  • The digital signature for the JAR file that was generated with the signer's private key
  • The certificate containing the signer's public key, to be used by anyone wanting to verify the signed JAR file

Signature block filenames typically will have a .DSA extension indicating that they were created by the default Digital Signature Algorithm. Other filename extensions are possible if keys associated with some other standard algorithm are used for signing.

Related Documentation

For additional information about keys, certificates, and certification authorities, see
  • The JDK Security Tools
  • X.509 Certificates

For more information about the Java platform's security architecture, see this related documentation:

  • Security Features in Java SE
  • The Java Cryptography Extension web site
  • JDK Security Documentation
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Signing and Verifying JAR Files
Next page: Signing JAR Files


Signing JAR Files (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Signing and Verifying JAR Files
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Signing JAR Files
You use the JAR Signing and Verification Tool to sign JAR files. You invoke the JAR Signing and Verification Tool by using the jarsigner command, so we'll refer to it as "Jarsigner" for short.

To sign a JAR file, you must first have a private key. Private keys and their associated public-key certificates are stored in password-protected databases called keystores. A keystore can hold the keys of many potential signers. Each key in the keystore can be identified by an alias which is typically the name of the signer who owns the key. The key belonging to Rita Jones might have the alias "rita", for example.

The basic form of the command for signing a JAR file is

jarsigner jar-file alias
In this command:
  • jar-file is the pathname of the JAR file that's to be signed.
  • alias is the alias identifying the private key that's to be used to sign the JAR file, and the key's associated certificate.

The Jarsigner tool will prompt you for the passwords for the keystore and alias.

This basic form of the command assumes that the keystore to be used is in a file named .keystore in your home directory. It will create signature and signature block files with names x.SF and x.DSA respectively, where x is the first eight letters of the alias, all converted to upper case. This basic command will overwrite the original JAR file with the signed JAR file.

In practice, you may want to use this command in conjunction with one or more of these options, which must precede the jar-file pathname:

Jarsigner Command Options
Option | Description
-keystore url | Specifies a keystore to be used if you don't want to use the .keystore default database.
-storepass password | Allows you to enter the keystore's password on the command line rather than be prompted for it.
-keypass password | Allows you to enter your alias's password on the command line rather than be prompted for it.
-sigfile file | Specifies the base name for the .SF and .DSA files if you don't want the base name to be taken from your alias. file must be composed only of upper case letters (A-Z), numerals (0-9), hyphen (-), and underscore (_).
-signedjar file | Specifies the name of the signed JAR file to be generated if you don't want the original unsigned file to be overwritten with the signed file.

Example

Let's look at a couple of examples of signing a JAR file with the Jarsigner tool. In these examples we will assume:
  • your alias is "johndoe".
  • the keystore you want to use is in a file named "mykeys" in the current working directory.
  • the keystore's password is "abc123".
  • the password for your alias is "mypass".
Under these assumptions, you could use this command to sign a JAR file named app.jar:
jarsigner -keystore mykeys -storepass abc123
          -keypass mypass app.jar johndoe

Because this command doesn't make use of the -sigfile option, the .SF and .DSA files it creates would be named JOHNDOE.SF and JOHNDOE.DSA. Because the command doesn't use the -signedjar option, the resulting signed file will overwrite the original version of app.jar.

Let's look at what would happen if you used a different combination of options:

jarsigner -keystore mykeys -sigfile SIG
          -signedjar SignedApp.jar app.jar johndoe

This time, you would be prompted to enter the passwords for both the keystore and your alias because the passwords aren't specified on the command line. The signature and signature block files would be named SIG.SF and SIG.DSA, respectively, and the signed JAR file SignedApp.jar would be placed in the current directory. The original unsigned JAR file would remain unchanged.

Additional Information

Complete reference pages for the JAR Signing and Verification Tool are on-line: Summary of Security Tools
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Understanding Signing and Verification
Next page: Verifying Signed JAR Files


Verifying Signed JAR Files (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Signing and Verifying JAR Files
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Verifying Signed JAR Files
Typically, verification of signed JAR files will be the responsibility of your JavaTM Runtime Environment. Your browser will verify signed applets that it downloads. Signed applications invoked with the -jar option of the interpreter will be verified by the runtime environment.

However, you can verify signed JAR files yourself by using the Jarsigner tool. You might want to do this, for example, to test a signed JAR file that you've prepared.

The basic command to use for verifying a signed JAR file is:

jarsigner -verify jar-file

This command will verify the JAR file's signature and ensure that the files in the archive haven't changed since it was signed. You'll see the following message if the verification is successful:

jar verified.

If you try to verify an unsigned JAR file, the following message results:

jar is unsigned. (signatures missing or not parsable)

If the verification fails, an appropriate message is displayed. For example, if the contents of a JAR file have changed since the JAR file was signed, a message similar to the following will result if you try to verify the file:

jarsigner: java.lang.SecurityException: invalid SHA1
signature file digest for test/classes/Manifest.class
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Signing JAR Files
Next page: Using JAR-related APIs


Using JAR-related APIs (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
Using JAR-related APIs
The JavaTM platform contains several classes for use with JAR files. Some of these APIs are:
  • The java.util.jar package
  • The java.net.JarURLConnection class
  • The java.net.URLClassLoader class

To give you an idea of the possibilities that are opened up by these new APIs, this lesson guides you through the inner workings of a sample application called JarRunner.

An Example - The JarRunner Application

JarRunner enables you to run an application that's bundled in a JAR file by specifying the JAR file's URL on the command line. For example, if an application called TargetApp were bundled in a JAR file at http://www.xxx.yyy/TargetApp.jar, you could run the application using this command:
java JarRunner http://www.xxx.yyy/TargetApp.jar
In order for JarRunner to work, it must be able to perform the following tasks, all of which are accomplished by using the new APIs:
  • Access the remote JAR file and establish a communications link with it.
  • Inspect the JAR file's manifest to see which of the classes in the archive is the main class.
  • Load the classes in the JAR file.

The JarRunner application consists of two classes, JarRunner and JarClassLoader. JarRunner delegates most of the JAR-handling tasks to the JarClassLoader class. JarClassLoader extends the java.net.URLClassLoader class. You can browse the source code for the JarRunner and JarClassLoader classes before proceeding with the lesson:

  • JarRunner.java
  • JarClassLoader.java

This lesson has two parts:

The JarClassLoader Class

This section shows you how JarClassLoader uses some of the new APIs to perform tasks required for the JarRunner application to work.

The JarRunner Class

This section summarizes the JarRunner class that comprises the JarRunner application.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Verifying Signed JAR Files
Next page: The JarClassLoader Class


The JarClassLoader Class (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Using JAR-related APIs
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
The JarClassLoader Class
The JarClassLoader class extends java.net.URLClassLoader. As its name implies, URLClassLoader is designed to be used for loading classes and resources that are accessed by searching a set of URLs. The URLs can refer either to directories or to JAR files.

In addition to subclassing URLClassLoader, JarClassLoader also makes use of features in two other new JAR-related APIs, the java.util.jar package and the java.net.JarURLConnection class. In this section, we'll look in detail at the constructor and two methods of JarClassLoader.

The JarClassLoader Constructor

The constructor takes an instance of java.net.URL as an argument. The URL passed to this constructor will be used elsewhere in JarClassLoader to find the JAR file from which classes are to be loaded.
public JarClassLoader(URL url) {
    super(new URL[] { url });
    this.url = url;
}
The URL object is passed to the constructor of the superclass, URLClassLoader, which takes a URL[] array, rather than a single URL instance, as an argument.

The getMainClassName Method

Once a JarClassLoader object is constructed with the URL of a JAR-bundled application, it's going to need a way to determine which class in the JAR file is the application's entry point. That's the job of the getMainClassName method:
public String getMainClassName() throws IOException {
    URL u = new URL("jar", "", url + "!/");
    JarURLConnection uc = (JarURLConnection)u.openConnection();
    Attributes attr = uc.getMainAttributes();
    return attr != null
                   ? attr.getValue(Attributes.Name.MAIN_CLASS)
                   : null;
}
You may recall from a previous lesson that a JAR-bundled application's entry point is specified by the Main-Class header of the JAR file's manifest. To understand how getMainClassName accesses the Main-Class header value, let's look at the method in detail, paying special attention to the new JAR-handling features that it uses:

The JarURLConnection class and JAR URLs

The getMainClassName method uses the JAR URL format specified by the java.net.JarURLConnection class. The syntax for the URL of a JAR file is as in this example:
jar:http://www.xxx.yyy/jarfile.jar!/
The terminating !/ separator indicates that the URL refers to an entire JAR file. Anything following the separator refers to specific JAR-file contents, as in this example:
jar:http://www.xxx.yyy/jarfile.jar!/mypackage/myclass.class

The first line in the getMainClassName method is:

URL u = new URL("jar", "", url + "!/");
This statement constructs a new URL object representing a JAR URL, appending the !/ separator to the URL that was used in creating the JarClassLoader instance.

The java.net.JarURLConnection class

This class represents a communications link between an application and a JAR file. It has methods for accessing the JAR file's manifest. The second line of getMainClassName is:
JarURLConnection uc = (JarURLConnection)u.openConnection();
In this statement, URL instance created in the first line opens a URLConnection. The URLConnection instance is then cast to JarURLConnection so it can take advantage of JarURLConnection's JAR-handling features.

Fetching Manifest Attributes: java.util.jar.Attributes

With a JarURLConnection open to a JAR file, you can access the header information in the JAR file's manifest by using the getMainAttributes method of JarURLConnection. This method returns an instance of java.util.jar.Attributes, a class that maps header names in JAR-file manifests with their associated string values. The third line in getMainClassName creates an Attributes object:
Attributes attr = uc.getMainAttributes();

To get the value of the manifest's Main-Class header, the fourth line of getMainClassName invokes the Attributes.getValue method:

return attr != null
               ? attr.getValue(Attributes.Name.MAIN_CLASS)
               : null;

The method's argument, Attributes.Name.MAIN_CLASS, specifies that it's the value of the Main-Class header that you want. (The Attributes.Name class also provides static fields such as MANIFEST_VERSION, CLASS_PATH, and SEALED for specifying other standard manifest headers.)

The invokeClass Method

We've seen how JarURLClassLoader can identify the main class in a JAR-bundled application. The last method to consider, JarURLClassLoader.invokeClass, enables that main class to be invoked to launch the JAR-bundled application:
public void invokeClass(String name, String[] args)
    throws ClassNotFoundException,
           NoSuchMethodException,
           InvocationTargetException
{
    Class c = loadClass(name);
    Method m = c.getMethod("main", new Class[] { args.getClass() });
    m.setAccessible(true);
    int mods = m.getModifiers();
    if (m.getReturnType() != void.class || !Modifier.isStatic(mods) ||
        !Modifier.isPublic(mods)) {
        throw new NoSuchMethodException("main");
    }
    try {
        m.invoke(null, new Object[] { args });
    } catch (IllegalAccessException e) {
        // This should not happen, as we have disabled access checks
    }
}

The invokeClass method takes two arguments: the name of the application's entry-point class and an array of string arguments to pass to the entry-point class's main method. First, the main class is loaded:

Class c = loadClass(name);
The loadClass method is inherited from java.lang.ClassLoader.

Once the main class is loaded, the reflection API of the java.lang.reflect package is used to pass the arguments to the class and launch it. You can refer to the tutorial on The Reflection API for a review of reflection.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using JAR-related APIs
Next page: The JarRunner Class


The JarRunner Class (The Java™ Tutorials > Deployment > Packaging Programs in JAR Files)

Trail: Deployment
Lesson: Packaging Programs in JAR Files
Section: Using JAR-related APIs
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Home Page > Deployment > Packaging Programs in JAR Files
« Previous • Trail • Next »
The JarRunner Class
The JarRunner application is launched with a command of this form:
java JarRunner url [arguments]
In the previous section, we've seen how JarClassLoader is able to identify and load the main class of a JAR-bundled application from a given URL. To complete the JarRunner application, therefore, we need to be able to take a URL and any arguments from the command line, and pass them to an instance of JarClassLoader. These tasks belong to the JarRunner class, the entry point of the JarRunner application.

It begins by creating a java.net.URL object from the URL specified on the command line:

public static void main(String[] args) {
    if (args.length < 1) {
        usage();
    }
    URL url = null;
    try {
        url = new URL(args[0]);
    } catch (MalformedURLException e) {
        fatal("Invalid URL: " + args[0]);
    }
    ...
If args.length < 1< /tt="/tt">, that means no URL was specified on the command line, so a usage message is printed. If the first command-line argument is a good URL, a new URL object is created to represent it.

Next, JarRunner creates a new instance of JarClassLoader, passing to the constructor the URL that was specified on the command-line:

JarClassLoader cl = new JarClassLoader(url);
As we saw in the previous section, it's through JarClassLoader that JarRunner taps into the JAR-handling APIs.

The URL that's passed to the JarClassLoader constructor is the URL of the JAR-bundled application that you want to run. JarRunner next calls the class loader's getMainClassName method to identify the entry-point class for the application:

String name = null;
try {
    name = cl.getMainClassName();
} catch (IOException e) {
    System.err.println("I/O error while loading JAR file:");
    e.printStackTrace();
    System.exit(1);
}
if (name == null) {
    fatal("Specified jar file does not contain a 'Main-Class'" +
          " manifest attribute");
}
The key statement is highlighted in bold. The other statements are for error handling.

Once JarRunner has identified the application's entry-point class, only two steps remain: passing any arguments to the application and actually launching the application. JarRunner performs these steps with this code:

// Get arguments for the application
String[] newArgs = new String[args.length - 1];
System.arraycopy(args, 1, newArgs, 0, newArgs.length);
// Invoke application's main class
try {
    cl.invokeClass(name, newArgs);
} catch (ClassNotFoundException e) {
    fatal("Class not found: " + name);
} catch (NoSuchMethodException e) {
    fatal("Class does not define a 'main' method: " + name);
} catch (InvocationTargetException e) {
    e.getTargetException().printStackTrace();
    System.exit(1);
}
Recall that the first command-line argument was the URL of the JAR-bundled application. Any arguments to be passed to that application are therefore in element 1 and beyond in the args array. JarRunner takes those elements, and creates a new array called newArgs to pass to the application (bold line above). JarRunner then passes the entry-point's class name and the new argument list to the invokeClass method of JarClassLoader. As we saw in the previous section, invokeClass will load the application's entry-point class, pass it any arguments, and launch the application.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The JarClassLoader Class
Next page: Java Web Start


Lesson: Java Web Start (The Java™ Tutorials > Deployment)

Java Web Start
Running Java Web Start Applications
Deploying Java Web Start Applications
Developing Java Web Start Applications
The JNLP API
Java Web Start and Security
Common Java Web Start Problems
Questions and Exercises
Trail: Deployment
Home Page > Deployment
« Previous • Trail • Next »
Lesson: Java Web Start
Java Web Start provides the power to launch full-featured applications with a single click. Users can download and launch applications, such as a complete spreadsheet program or an Internet chat client, without going through complicated installation procedures.

With Java Web Start, the user can launch a Java application by clicking a link in a Web page. The link points to a JNLP file, which instructs Java Web Start to download, cache and run the application.

Java Web Start provides Java developers and users with many deployment advantages:

  • With Java Web Start, you can place a single Java application on a Web server for deployment to a wide variety of platforms, including Windows 2003/Vista/2000/XP, Linux, and SolarisTM
  • Java Web Start supports multiple, simultaneous versions of the Java Standard Edition platform. Specific applications can request specific Java versions without conflicting with the different needs of other applications. Java Web Start automatically downloads and installs the correct version of the Java platform as necessary based on the application's needs and the user's environment.
  • Users can launch a Java Web Start application independently of a Web browser. The user can be off-line, or unable to access the browser. Desktop shortcuts can also launch the application, providing the user with the same experience as a native application.
  • Java Web Start takes advantage of the inherent security of the Java platform. By default, applications have restricted access to local disk and network resources. Users can safely run applications from sources that are not trusted.
  • Applications launched with Java Web Start are cached locally, for improved performance.
  • Java Web Start provides limited support for applets through its built-in applet viewer. However, this is not intended to be a full- scale applet environment, such as the one provided by Java Plug-in. Java Web Start's applet viewer has certain limitations; for example, you cannot specify class files as resources, and it does not accept policy files.
In Java Version 1.4.2 and beyond, Java Web Start is installed as part of the JRE. Users do not have to install it separately or perform additional tasks to use Java Web Start applications.

This lesson contains the following sections:

Running Java Web Start Applications

You can run an application with Java Web Start in three different ways.

Deploying Java Web Start Applications

You deploy an application for Java Web Start in four simple steps.

Developing Java Web Start Applications

You develop an application for use through Java Web Start just as you would any Java application, with a few special considerations.

The JNLP API

You can use the JNLP API to access additional information in applications run through Java Web Start.

Java Web Start and Security

Java Web Start applications run in a sandbox by default. You can provide digital signatures and permissions in the JNLP file to enable functionality beyond the sandbox.

Common Java Web Start Problems

Gives solutions to some problems you might encounter while learning Java Web Start.

Questions and Exercises: Java Web Start

Test what you've learned about Java Web Start.

Additional References

This lesson is intended to get you started with Java Web Start and does not include all available documentation. For more information about Java Web Start, see the following:
  • Java Web Start Guide
  • Java Web Start FAQ
  • JNLP Specification
  • javax.jnlp API Documentation
  • Java Web Start Developers Site
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Running Java Web Start Applications


Running Java Web Start Applications (The Java™ Tutorials > Deployment > Java Web Start)

Trail: Deployment
Lesson: Java Web Start
Java Web Start
Running Java Web Start Applications
Deploying Java Web Start Applications
Developing Java Web Start Applications
The JNLP API
Java Web Start and Security
Common Java Web Start Problems
Questions and Exercises
Home Page > Deployment > Java Web Start
« Previous • Trail • Next »
Running Java Web Start Applications
Users can run Java Web Start applications in the following ways:
  • Running a Java Web Start Application from a Browser
  • Running an Application from the Java Cache Viewer
  • Running a Java Web Start Application from the Desktop
Note: Users of applications deployed with Java Web Start must have a compatible version of the Java Runtime Environment (JRE). The complete JDK is not required.

Running a Java Web Start Application from a Browser

You run an application with Java Web Start from a browser simply by clicking a link to the application's JNLP file, such as:
<a href="Notepad.jnlp">Launch Notepad Application</a>
Java Web Start then loads and runs the application based on instructions in the JNLP file.

Try it now: Run Notepad

Running an Application from the Java Cache Viewer

If you are using Java Version 1.6.0, you can run a Java Web Start application through the Java Cache Viewer.

When Java Web Start first loads an application, information from the application's JNLP file is stored in the local Java Cache Viewer. To launch the application again, you do not need to return to the Web page where you first launched it; you can simply open the Java Cache Viewer.

To open the Java Cache Viewer:

  1. Open the Control Panel.
  2. Double click on the Java icon. The Java Control Panel opens.
  3. Select the General tab.
  4. Click View. The Java Cache Viewer opens.

The application is listed in the viewer:

A screen shot of the Java Cache Viewer application

Java Cache Viewer application

To run the application, select it and click the Run button, The Run button, or double click the application. The application starts just as it did from the Web page.

Running a Java Web Start Application from the Desktop

Through the Java Cache Viewer, you can add a shortcut to the application to your desktop. Simply select the application, right-click and select Install Shortcuts, or Click the Install button, The Install button. A shortcut is then added to the desktop:

You can then launch the Java Web Start application just as you would any native application.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Java Web Start
Next page: Deploying Java Web Start Applications


Deploying Java Web Start Applications (The Java™ Tutorials > Deployment > Java Web Start)

Trail: Deployment
Lesson: Java Web Start
Java Web Start
Running Java Web Start Applications
Deploying Java Web Start Applications
Developing Java Web Start Applications
The JNLP API
Java Web Start and Security
Common Java Web Start Problems
Questions and Exercises
Home Page > Deployment > Java Web Start
« Previous • Trail • Next »
Deploying Java Web Start Applications
This section describes the basics of deploying an application using Java Web Start. Deploying an application involves the following steps:
  1. Setting up the Web Server
  2. Creating the JNLP File
  3. Placing the Application on the Web Server
  4. Creating the Web Page
This section uses the Notepad example application to demonstrate Java Web Start technology. You can find all the source files for the Notepad application example in the \demo\plugin\jfc\Notepad directory within the JDK installation directory.

Setting up the Web Server

Before you can deploy an application with Java Web Start over the Web, you must ensure that the Web server you are using can handle JNLP files.

Configure the Web server so that files with the .jnlp extension are set to the application/x-java-jnlp-file MIME type.

How you set the JNLP MIME type depends on the Web server you are using. For example, for the Apache Web server, you simply add the line

application/x-java-jnlp-file JNLP
to the mime.types file.

For other Web servers, check the documentation for instructions on setting MIME types.

Creating the JNLP File

The key to running an application with Java Web Start is the Java Network Launching Protocol, or JNLP, file. The JNLP file is an XML file that contains elements and attributes that tell Java Web Start how to run the application.

An Example JNLP File

Following is the JNLP file for the Notepad demo:
<?xml version="1.0" encoding="utf-8"?>
<!-- JNLP File for Notepad -->

<jnlp spec="1.0+"
      codebase="http://java.sun.com/docs/books/tutorialJWS/deployment/webstart/examples/"
      href="Notepad.jnlp">
   <information>
      <title>Notepad Demo</title>
      <vendor>The Java(tm) Tutorial: Sun Microsystems, Inc.</vendor>
      <description>Notepad Demo</description>
      <homepage href="http://java.sun.com/docs/books/tutorial/deployment/webstart/running.html"/>
      <description kind="short">ClickMeApp uses 3 custom classes plus several
       standard ones</description>
      <offline-allowed/>
   </information>
   <resources>
       <jar href="Notepad.jar"/>
    <j2se version="1.6+"
          href="http://java.sun.com/products/autodl/j2se"/>
   </resources>
   <application-desc main-class="Notepad"/>
</jnlp>
If you click this link to the Notepad.jnlp file, you open and run the Notepad application.

JNLP File Contents

The following table describes the elements and attributes in the sample JNLP file.
Note: This table does not include all possible contents of the JNLP file. For more information, see the Java Network Launching Protocol & API Specification (JSR-56).

Elements and Attributes of a JNLP file

Element

Attributes

Description

Since

Required

jnlp

This is the main xml element for a jnlp file. Everything is contained within the jnlp element.

1.0

yes

spec

The spec attribute can be 1.0, 1.5.0, or 1.6.0 or can use the wildcards such as 1.0+. It denoted the minimum version of the JNLP Specification that this jnlp file can work with.

1.0

codebase

The codebase attribute specifies the base location for all relative URLs specified in href attributes in the JNLP file.

1.0

href

The href specifies the URL of the JNLP file itself.

1.0

version

The version of the application being launched, as well as the version of the JNLP file itself.

1.0

information

The information element contains other elements that describe the application and it's source.

1.0

yes

os

Specifies the operating system for which this information element should be considered.

1.5.0

arch

Specifies the architecture for which this information element should be considered

1.5.0

platform

Specifies the platform for which this information element should be considered.

1.5.0

locale

Specifies the locale for which this information element should be considered.

1.5.0

title

The title element specifies the title of the application.

1.0

yes

vendor

The vendor element specifies the provider of the application.

1.0

yes

homepage

The homepage of the application.

1.0

href

A URL pointing to where more information on this application can be found.

1.0

yes

description

A short statement describing the application.

1.0

kind

An indicator as to what type of description this is, legal values are one-line, short, and tooltip.

1.0

icon

Describes an icon that can be used to identify the application to the user.

1.0

href

A URL pointing to the icon file, may be in one of the following formats: gif, jpg, png, ico.

1.0

yes

kind

Indicates the suggested use of the icon, can be: default, selected, disabled, rollover, splash, or shortcut.

1.0

width

Can be used to indicate the resolution of the image.

1.0

height

Can be used to indicate the resolution of the image.

1.0

depth

Can be used to indicate the resolution of the image.

1.0

offline-allowed

Indicates that this application can operate when the client system is disconnected from the network.

1.0

shortcut

The shortcut element can be used to indicate an application's preferences for desktop integration.

1.5.0

online

Can be used to describe the application's preference for creating a shortcut to run online or offline.

1.5.0

desktop

Can be used to indicate an application's preference for putting a shortcut on the users desktop.

1.5.0

menu

Can be used to indicate an application's preference for putting a menu item in the users start menus.

1.5.0

sub-menu

Can be used to indicate an application's preference for where to place the menu item.

1.5.0

association

Can be used to hint to the JNLP client that it wishes to be registered with the operating system as the primary handler of certain extensions and a certain mime-type.

1.5.0

extensions

Contains a list of file extensions (separated by spaces) that the application requests it be registered to handle.

1.5.0

mime-type

Contains the mime-type that the application requests it be registered to handle.

1.5.0

related-content

Describes an additional piece of related content that may be integrated with the application.

1.5.0

href

A URL pointing to the related content.

1.5.0

yes

update

The update element is used to indicate the preferences for how application updates should be handled by the JNLP Client.

1.6.0

check

Indicates the preference for when the JNLP Client should check for updates. It can be always, timeout, or background..

1.6.0

policy

Indicates the preference for how the JNLP Client should handle an application update when it is known an update is available before the application is launched. It can be always, prompt-update, or prompt-run.

1.6.0

1.0

security

This element can be used to request enhanced permissions.

1.0

all-permissions

Requests that the application be run with all permissions.

1.0

j2ee-application-client-permissions

Requests that the application be run with a permission set that meets the security specifications of the J2EE Application Client environment.

1.0

1.0

resources

Describes all the resources that are needed for an application.

1.0

yes

os

Specifies the operating system for which the resources element should be considered.

1.0

arch

Specifies the architecture for which the resources element should be considered.

1.0

locale

Specifies that the locales for which the resources element should be considered.

java (or java se)

Specifies what version(s) of Java to run the application with.

1.6.0 (java)

version

Describes an ordered list of version ranges to use.

1.0

yes

href

The URL denoting the supplier of this version of java, and where it may be downloaded from.

1.0

java-vm-args

Indicates an additional set of standard and non-standard virtual machine arguments that the application would prefer the JNLP Client to use when launching Java.

1.0

initial-heap-size

Indicates the initial size of the Java heap.

1.0

max-heap-size

Indicates the maximum size of the Java heap.

1.0

jar

Specifies a JAR file that is part of the application's classpath.

1.0

yes

href

The URL of the jar file.

1.0

yes

version

The requested version of the jar file. Requires using the version-based download protocol

1.0

main

Indicates if this jar contains the class containing the main method of the application.

1.0

download

Can be used to indicate this jar may be downloaded lazily, or when needed.

1.0

size

Indicates the downloadable size of the jar file in bytes.

1.0

part

Can be used to group resources together so they will be downloaded at the same time.

1.0

nativelib

Specifies a JAR file that contains native libraries in it's root directory.

1.0

href

The URL of the jar file.

1.0

yes

version

The requested version of the jar file. Requires using the version-based download protocol

1.0

download

Can be used to indicate this jar may be downloaded lazily.

1.0

size

Indicates the downloadable size of the jar file in bytes.

1.0

part

Can be used to group resources together so they will be downloaded at the same time.

1.0

extension

Contains pointer to an additional component-desc or installer-desc to be used with this application.

1.0

href

The URL to the additional extension jnlp file.

1.0

yes

version

The version of the additional extension jnlp file.

1.0

name

The name of the additional extension jnlp file

1.0

ext-download

Can be used in an extension element to denote the parts contained in a component-extension.

1.0

ext-part

Describes the name of a part that can be expected to be found in the extension.

1.0

yes

download

Can be used to indicate this extension may be downloaded eagerly or lazily.

1.0

part

Denotes the name of a part in this jnlp file to include the extension in.

1.0

package

Can be used to indicate to the JNLP Client which packages are implemented in which JAR files.

1.0

name

Package name contained in the jar files of the given part.

1.0

yes

part

Part name containing the jar files that include the given package name.

1.0

yes

recursive

Can be used to indicated that all package names beginning with the given name, can be found in the given part.

1.0

property

Defines a system property that will be available through the System.getProperty and System.getProperties methods.

1.0

name

Name of the system property.

1.0

yes

value

Value it will be set to.

1.0

yes

1.0

Note: A jnlp file must contain one of application-desc, applet-desc, component-desc, or installer-desc

1.0

yes

applicaation-desc

Denotes this is the jnlp file for an application.

1.0

main-class

The name of the class containing the public static void main(String[]) method of the application.

1.0

yes

argument

Each argument contains (in order) an additional argument to be passed to main.

1.0

applet-desc

Denotes this is the jnlp file for an applet.

1.0

main-class

This is the name of the main Applet class.

1.0

yes

documentbase

The document base for the Applet as a URL.

1.0

name

Name of the Applet.

1.0

yes

width

The width of the applet in pixels.

1.0

yes

height

The height of the applet in pixels

1.0

yes

param

A set of parameters that can be passed into the applet.

1.0

name

The name of this parameter

1.0

yes

value

The value of this parameter

1.0

yes

component-desc

Denotes this is the jnlp file for a component extension.

1.0

installer-desc

Denotes this is the jnlp file for an installed extension.

1.0

main-class

The name of the class containing the public static void main(String[]) method of the installer.

1.0

yes

Encoding JNLP Files

Java Web Start supports encoding of JNLP files in any character encoding supported by the Java platform. For more information on character encoding in Java, see the Supported Encodings Guide. To encode a JNLP file, specify an encoding in the XML prolog of that file. For example, the following line indicates that the JNLP file is encoded in UTF-16.
<?xml version="1.0" encoding="utf-16"?>
Note: The XML prolog itself must be UTF-8-encoded.

Placing the Application on the Web Server

The next step in deploying your application with Java Web Start is as simple as placing all the application's JAR files and the JNLP file on the Web server. You must ensure the JAR files are in the locations specified by the href attribute of the jar element in the JNLP file.

Creating the Web Page

Once you've completed to preceding steps, you are ready to write a Web page that gives users access to your application. Adding a link to your application in a Web page for users with Java Web Start already installed is simple; however, you must also design your Web page for users that might not have Java Web Start installed.

Adding the Basic Link to the JNLP File

In order to enable your users to launch the application from a Web page, you must include a link to the application's JNLP file from that Web page. To add this link, you use the standard HTML link syntax, with the href attribute specifying the location of the JNLP file:
<a href="Notepad.jnlp">Launch Notepad Application</a>
Assuming Java Web Start is installed on the client computer, when the user clicks this link, Java Web Start executes the application based on the instructions in the JNLP file.

Adding the Link when Java Web Start is not Installed

For users who might not have Java Web Start installed, you must write scripts in your Web page to:
  1. Detect which browser the user has.
  2. Detect whether Java Web Start is installed.
  3. If Java Web Start is not installed, either auto-install it, or direct the user to a download page.
For more information and sample scripts to use for these steps, see the Java Web Start Guide.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Running Java Web Start Applications
Next page: Developing Java Web Start Applications


Developing Java Web Start Applications (The Java™ Tutorials > Deployment > Java Web Start)

Trail: Deployment
Lesson: Java Web Start
Java Web Start
Running Java Web Start Applications
Deploying Java Web Start Applications
Developing Java Web Start Applications
The JNLP API
Java Web Start and Security
Common Java Web Start Problems
Questions and Exercises
Home Page > Deployment > Java Web Start
« Previous • Trail • Next »
Developing Java Web Start Applications
For the most part, you develop applications to be deployed through Java Web Start just as you would develop stand-alone Java applications. However, there are some packaging considerations, which are described in the following sections:
  • Packaging the Application in JAR Files
  • Reading Resources in a JAR File
  • Untrusted Applications

Packaging the Application in JAR Files

To deploy an application with Java Web Start, you must package the application as one or more JAR files. In particular, you must package the application's files into one or more JAR files.
Note : Other resources such as images and property files can, if necessary, be outside of JAR files and retrieved using HTTP requests. However, storing resources in JAR files is preferred, because JAR files are cached on the local computer by Java Web Start.
If the application needs unrestricted access to the local system, all JAR files and entries must be signed. For more information, see the Java Web Start and Security section.

Reading Resources in a JAR File

Use the getResource method to read resources from a JAR file. For example, the following code example retrieves images from a JAR file:
// Get current classloader
ClassLoader cl = this.getClass().getClassLoader();
// Create icons
Icon saveIcon  = new ImageIcon(cl.getResource("images/save.gif"));
Icon cutIcon   = new ImageIcon(cl.getResource("images/cut.gif"));
The example assumes that the following entries exist in the JAR files for the application:
  • images/save.gif
  • images/cut.gif

Untrusted Applications

Unless you sign your application's JAR files, which requires users to accept your certificate, your application deployed through Java Web Start is untrusted. Untrusted applications have the following restrictions:
  • The application can not access the local disk.
  • All JAR files for the application must be downloaded from the same server.
  • The application can only make network connections to the server from which the JAR files were downloaded.
  • A security manager can not be removed or replaced.
  • The application cannot use native libraries.
  • The application has limited access to system properties. The application has read/write access to a set of system properties known to be secure, and read-only access to the same set of properties as an applet.

For more information, see the Java Web Start and Security section.

Also see The JNLP API section for information on using the special Java Web Start packages in your applications.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Deploying Java Web Start Applications
Next page: The JNLP API


The JNLP API (The Java™ Tutorials > Deployment > Java Web Start)

Trail: Deployment
Lesson: Java Web Start
Java Web Start
Running Java Web Start Applications
Deploying Java Web Start Applications
Developing Java Web Start Applications
The JNLP API
Java Web Start and Security
Common Java Web Start Problems
Questions and Exercises
Home Page > Deployment > Java Web Start
« Previous • Trail • Next »
The JNLP API
The Java platform includes the JNLP API to enable you to provide additional information to applications deployed through Java Web Start.

The JNLP API is included in the javax.jnlp package, which is delivered in the jnlp.jar as part of te Java Development Kit version 6, in the sample/jnlp/servlet directory. The javax.jnlp package is also delivered in the javaws.jar, which is located in the JRE's lib directory.

The following table provides an overview of the main interfaces and classes in the javax.jnlp package. For more information, see the API documentation and the Java Web Start Guide .

Warning : Java Web Start warns users of the following Interfaces and Classes about the potential security risk of allowing an untrusted application to access the file system, use the system printer, use the system clipboard, or increase the disk space used by the PersistenceService.
Interfaces and Classes in the javax.jnlp Package
Interface or Class | Description
BasicService Provides methods for:
  • Determining the codebase of the application
  • Determining whether the application is online or not
  • Determining whether a Web browser is supported on the current platform and by the JNLP client.
  • Opening a specific URL in the browser
ClipboardService | Provides methods for copying contents to and from the client system's clipboard. The ClipboardService interface works for applications running in a sandbox.
DownloadService | Provides the ability to control how the application's resources are cached.
ExtendedService | Provides additional support to the current JNLP API. It allows applications to open specific file(s) in the client's file system.
FileContents | Encapsulates the name and contents of a file. An object of this class is used by the FileOpenService, FileSaveService and PersistenceService interfaces.
FileOpenService | Provides the ability for applications to open files on the local file system.
FileSaveService Provides methods for exporting files to the local disk, even for applications that are running in the restricted execution environment.

Note: This interface provides the same level of disk access to potentially untrusted Web-deployed applications that a Web browser provides for content it displays through its Save As . . . dialog box.

JNLPRandomAccessFile | Supports reading from and writing to a random access file. A random access file behaves like a large array of bytes stored in the file system.
PersistenceService Provides methods for storing data locally on the client system, even for applications that are running in a sandbox.

Note: This service is similar to the cookie mechanism for HTML-based applications. Cookies allow a small amount of data to be stored locally on the client system. That data can be securely managed by the browser and can only be retrieved by HTML pages which originate from the same URL as the page that stored the data.

PrintService Provides methods for access to printing, even for applications that are running in the restricted execution environment.

Note: Starting with Java Web Start 5.0, you can use the Java Printing APIs, so there is no need to use this interface. If the application is running in a sandbox, Java Web Start opens a security dialog box asking the user for permission to print.

SingleInstanceService | Provides a set of methods for applications to register themselves as singletons, and to register listener(s) for handling arguments passed in from different instances of applications.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Developing Java Web Start Applications
Next page: Java Web Start and Security


Java Web Start and Security (The Java™ Tutorials > Deployment > Java Web Start)

Trail: Deployment
Lesson: Java Web Start
Java Web Start
Running Java Web Start Applications
Deploying Java Web Start Applications
Developing Java Web Start Applications
The JNLP API
Java Web Start and Security
Common Java Web Start Problems
Questions and Exercises
Home Page > Deployment > Java Web Start
« Previous • Trail • Next »
Java Web Start and Security
This section describes the basics of security for applications deployed through Java Web Start and includes:
  • Java Web Start Security Basics
  • Signing JAR Files for Java Web Start Deployment
  • Security and JNLP Files
  • Dynamic Downloading of HTTPS Certificates

Java Web Start Security Basics

Applications launched with Java Web Start are, by default, run in a restricted environment, known as a sandbox. In this sandbox, Java Web Start:
  • Protects users against malicious code that could affect local files
  • Protects enterprises against code that could attempt to access or destroy data on networks
Unsigned JAR files launched by Java Web Start remain in this sandbox, meaning they cannot access local files or the network.

Signing JAR Files for Java Web Start Deployment

Java Web Start supports signed JAR files so that your application can work outside of the sandbox described above, so that the application can access local files and the network.

Java Web Start verifies that the contents of the JAR file have not changed since it was signed. If verification of a digital signature fails, Java Web Start does not run the application.

When the user first runs an application as a signed JAR file, Java Web Start opens a dialog box displaying the application's origin based on the signer's certificate. The user can then make an informed decision regarding running the application.

For more information, see the Signing and Verifying JAR Files section.

Security and JNLP Files

For a signed JAR file to have access to the local file system and network, you must specify security settings in the JNLP file. The security element contains security settings for the application.

The following example provides the application with complete access to the client system if all its JAR files are signed:

<security>
   <all-permissions/>
</security>

Dynamic Downloading of HTTPS Certificates

Java Web Start dynamically imports certificates as browsers typically do. To do this, Java Web Start sets its own https handler, using the java.protocol.handler.pkgs system properties, to initialize defaults for the SSLSocketFactory and HostnameVerifier . It sets the defaults with the methods HttpsURLConnection.setDefaultSSLSocketFactory and HttpsURLConnection.setDefaultHostnameVerifier .

If your application uses these two methods, ensure that they are invoked after the Java Web Start initializes the https handler, otherwise your custom handler will be replaced by the Java Web Start default handler.

You can ensure that your own customized SSLSocketFactory and HostnameVerifiter are used by doing one of the following:

  • Install your own https handler, to replace the Java Web Start https handler. For more information, see the document A New Era for Java Protocol Handlers .
  • In your application, invoke HttpsURLConnection.setDefaultSSLSocketFactory or HttpsURLConnection.setDefaultHostnameVerifier only after the first https URL object is created, which executes the Java Web Start https handler initialization code first.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The JNLP API
Next page: Common Java Web Start Problems


Common Java Web Start Problems (The Java™ Tutorials > Deployment > Java Web Start)

Trail: Deployment
Lesson: Java Web Start
Java Web Start
Running Java Web Start Applications
Deploying Java Web Start Applications
Developing Java Web Start Applications
The JNLP API
Java Web Start and Security
Common Java Web Start Problems
Questions and Exercises
Home Page > Deployment > Java Web Start
« Previous • Trail • Next »
Common Java Web Start Problems
Problem: My browser shows the JNLP file for my application as plain text.
Most likely, your Web server is not aware of the proper MIME type for JNLP files. See the Setting up the Web server section for more information.

Furthermore, if you are using a proxy server, ensure that the update versions of the files are returned, by updating the time stamp of the resources on the Web server such that the proxies will update their caches.

Problem: When I click on a link to a JNLP file with Internet Explorer and Java Web Start launches, I get the message "Could not load file/URL specified: C:\Documents and Settings\...\application[1].jnlp".

This problem only occurs with Internet Explorer. It is usually caused by a no-cache directive from the Web or proxy server, which causes Internet Explorer to not write the JNLP file to the local disk.

This frequently happens when you upgrade a Tomcat-based server, as later versions set the no-cache directive by default for any resource that is within a security-constraint in the web.xml file. Try removing the relevant URI from the security constraint.

This problem can also occur because of a full cache, or if the cache is turned off in Internet Explorer.

The most likely cause is that your browser and Java Web Start have different proxy settings. To modify Java Web Start proxy settings:
  1. Open the Java Application Cache Viewer.
  2. From the Edit menu, select Preferences. The Java Control Panel opens.
  3. Click Network Settings. The Network Settings dialog box opens.
  4. Select Use proxy server, enter the proxy server name, and port number (typically 8080).
  5. Click OK.

Problem: When I try to launch my JNLP file, I get the following error:

MissingFieldException[ The following required field is missing from the
launch file: (|||)]
    at com.sun.javaws.jnl.XMLFormat.parse(Unknown Source)
    at com.sun.javaws.jnl.LaunchDescFactory.buildDescriptor(Unknown Source)
    at com.sun.javaws.jnl.LaunchDescFactory.buildDescriptor(Unknown Source)
    at com.sun.javaws.jnl.LaunchDescFactory.buildDescriptor(Unknown Source)
    at com.sun.javaws.Main.launchApp(Unknown Source)
    at com.sun.javaws.Main.continueInSecureThread(Unknown Source)
    at com.sun.javaws.Main.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
Often this error occurs when your XML is malformed. You can stare at the code until you figure it out but it is easier to run an XML syntax checker over the file. (NetBeans IDE and jEdit both provide XML syntax checkers.)

However, this error can occur in a other situations and the above was caused by the following line in an otherwise well-formed XML file:

<description kind="short">Demonstrates choosing the drop location in the target <code>TransferHandler</code></description>
The error was caused by the illegal embedded code tags.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Java Web Start and Security
Next page: Questions and Exercises: Java Web Start


Questions and Exercises: Java Web Start (The Java™ Tutorials > Deployment > Java Web Start)

Trail: Deployment
Lesson: Java Web Start
Java Web Start
Running Java Web Start Applications
Deploying Java Web Start Applications
Developing Java Web Start Applications
The JNLP API
Java Web Start and Security
Common Java Web Start Problems
Questions and Exercises
Home Page > Deployment > Java Web Start
« Previous • Trail • Next »
Questions and Exercises: Java Web Start

Questions

  1. In a link that is to run a Java Web Start application, which file is specified as the a tag's href attribute?

  2. Which MIME type must a Web server recognize in order for it to host Java Web Start applications?

  3. In an application's JNLP file, which two elements must be specified within the resources element?

  4. Which interface provides the ability to control how the Java Web Start application's resources are cached?

    1. BasicService
    2. DownloadService
    3. PersistenceService
    4. ExtendedService

  5. True or False: Java Web Start applications run in a secure sandbox by default.

  6. True or False: If a Java Web Start application is running in a secure sandbox, JAR files for the application can reside on different servers.

  7. For a Java Web Start application to support operations outside of the secure sandbox, what must you do with its JAR files?

Exercises

  1. Write the XML code you would add to a JNLP file in order to request that the application have complete access to the client system.

  2. For a Java Web Start application, you have two icons, one.gif and two.gif, in the images directory in a JAR file. Write the application code you would use to access these images.
Check your answers.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Common Java Web Start Problems
Next page: Applets


Lesson: Applets (The Java™ Tutorials > Deployment)

Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Trail: Deployment
Home Page > Deployment
« Previous • Trail • Next »
Lesson: Applets
This lesson talks about the basics of applets, advantages of applets over applications, how to load applets in a web page, how to convert applications to applets and how applets work. You should thoroughly understand this lesson before going further in this trail.

An applet is a special kind of Java program that a browser enabled with Java technology can download from the internet and run. An applet is typically embedded inside a web-page and runs in the context of the browser. An applet must be a subclass of the java.applet.Applet class, which provides the standard interface between the applet and the browser environment.

Swing provides a special subclass of Applet, called javax.swing.JApplet, which should be used for all applets that use Swing components to construct their GUIs.

By calling certain methods, a browser manages an applet life cycle, if an applet is loaded in a web page.

Life Cycle of an Applet: Basically, there are four methods in the Applet class on which any applet is built.

  • init: This method is intended for whatever initialization is needed for your applet. It is called after the param attributes of the applet tag.
  • start: This method is automatically called after init method. It is also called whenever user returns to the page containing the applet after visiting other pages.
  • stop: This method is automatically called whenever the user moves away from the page containing applets. You can use this method to stop an animation.
  • destroy: This method is only called when the browser shuts down normally.

    Thus, the applet can be initialized once and only once, started and stopped one or more times in its life, and destroyed once and only once.

    For more information on Life Cylce of an Applet, please refer to The Life Cycle of an Applet section.

    When to write Applets vs. Applications

    In the early days of Java, one of the critical advantages that Java applets had over Java applications was that applets could be easily deployed over the web while Java applications required a more cumbersome installation process. Additionally, since applets are downloaded from the internet, by default they have to run in a restricted security environment, called the "sandbox", to ensure they don't perform any destructive operations on the user's computer, such as reading/writing to the filesystem.

    However, the introduction of Java Web Starthas made it possible for Java applications to also be easily deployed over the web, as well as run in a secure environment. This means that the predominant difference between a Java applet and a Java application is that an applet runs in the context of a web browser, being typically embedded within an html page, while a Java application runs standalone, outside the browser. Thus, applets are particularly well suited for providing functions in a web page which require more interactivity or animation than HTML can provide, such as a graphical game, complex editing, or interactive data visualization. The end user is able to access the functionality without leaving the browser.

    Loading Applets in a Web Page

    In order to load an applet in a web page, you must specify the applet class with appropriate applet tags. A simple example is below:
        <applet code=AppletWorld.class width="200" height="200">
    </applet>

    For development and testing purposes, you can run your applet using the lightweight appletviewer application that comes with the JDK. For example, if AppletWorld.html is the html file name, then you run the command as

        appletviewer AppletWorld.html

    Once you know your applet runs within the appletviewer, it is important to test your applet running in a web browser by loading the applet's web page into the browser window. The browser can retrieve the class files either from the internet or from the local working directory used during development. If you make changes to your applet's code while it is loaded in the browser, then you must recompile the applet and press the "Shift + Reload" button in the browser to load the new version.

    Getting Started with Applets

    This section tells you how applets work. When you want a program to run directly in a browser window, you want an applet.

    Taking Advantage of the Applet API

    This section describes how to use the API to which only applets have access. It covers sound, applet parameters, the <APPLET> tag, interapplet communication, and making requests to the browser.

    Practical Considerations When Writing Applets

    This section discusses topics that are covered elsewhere in this tutorial but that are affected by the applet environment. For example, it mentions some factors you should consider when writing the graphical user interface (GUI) for your applet. It also talks about security restrictions on applets and how a server-side application can help you get around those restrictions.

    Finishing an Applet

    This section describes the characteristics of a high-quality applet. It includes Before You Ship That Applet, a checklist of some annoying behaviors you should avoid in your applet.

    Deploying Applets

    This section explains to HTML authors how and when to use the applet, object, and embed tags to add Java applets to Web pages.

    Common Problems (and Their Solutions)

    This section explains the solutions to some problems you might run into while writing your applet.

    Questions and Exercises: Applets

    Test what you've learned about applets.

    Additional References

    This lesson is intended to get you started with applets and Java Plug-in and does not include all available documentation. For more information about applets, see the following:
    • Java Plug-in Developer Guide
    • « Previous • Trail • Next »
    Problems with the examples? Try Compiling and Running the Examples: FAQs.
    Complaints? Compliments? Suggestions? Give us your feedback.

    Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

             About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
    Copyright 1995-2008 Sun Microsystems, Inc.
    Previous page: Previous Lesson
    Next page: Getting Started with Applets


Getting Started with Applets (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Getting Started with Applets

Below is the HelloWorld applet, which is a simple Java class that prints the string "Hello World" in small rectangle.

Note: If you don't see the applet running above, you need to install Java Plug-in, which happens automatically when you install the Java(TM) SE JRE or JDK. This applet requires JDK 1.4 or later. You can find more information on the Java Plug-in home page.

We strongly recommend that you install the latest version; release 1.4 or later is required for all our applets. You can find more information in Troubleshooting Applet Problems

Following is the source code for the HelloWorld applet:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import javax.swing.JApplet;
import java.awt.Graphics;

public class HelloWorld extends JApplet {
    public void paint(Graphics g) {
    g.drawRect(0, 0,
           getSize().width - 1,
           getSize().height - 1);
        g.drawString("Hello world!", 5, 15);
    }
}

An applet such as this is typically managed and run by Java Plug-in. Java Plug-in, which is automatically included when you download the Java(TM) SE Runtime Environment (JRE), extends the functionality of a web browser, allowing applets to be run under Sun's Java(TM) SE Runtime Environment (JRE) rather than the Java Runtime Environment that comes with the web browser. It works with the Mozilla family of browsers and with Internet Explorer.

Converting Applications to Applets

An application is a standalone program consisting of at least one class with a main method. Applets differ significantly from applications. First, applets do not have a main method that is automatically called to begin the program. Instead, several methods are called at different points in the execution of an applet. The difference between Java applets and applications lies in how they are run. Applications are usually run by loading the application's main class file with a Java interpreter, such as the java tool in the JDK(TM) 6.

Basic steps to follow to convert an application program into an applet program:

  • You need to create a subclass of java.applet.Applet in which you override the init method to initialize your applet's resources the same way the main method initializes the application's resources.
  • init might be called more than once and should be designed accordingly. Moreover, the top-level Panel needs to be added to the applet in init; usually it was added to a Frame in main. That's it!

    You may understand clearly as to how you can convert an application program into an applet, by going through a sample application program SwingUI.java here and its corresponding applet program ApptoAppl.java

    When you compare these two programs, you may come up with the following major differences between the two:

  • The applet class is declared public so appletviewer can access it.
  • The applet class descends from Applet/JApplet and the application class descends from Frame/JFrame.
  • The applet version has no main method.
  • The application constructor is replaced in the applet by start and init methods.
  • GUI components are added directly to the Applet; whereas, in the case of an application, GUI components are added to the content pane of its JFrame object.

    The rest of this section contains the following to help you get started with applets:

    • Extending Applet or JApplet

    Every applet must define a subclass of the Applet or JApplet class. In the "Hello World" applet, this subclass is called HelloWorld. Applets inherit a great deal of functionality from the Applet or JApplet class, including abilities to communicate with the browser and present a graphical user interface (GUI) to the user.

    The Life Cycle of an Applet

    The HelloWorld applet implements just one method, the paint method. Every applet must implement at least one of the following methods: init, start, or paint. This section introduces a new applet, Simple, that uses all of these methods. Unlike Java applications, applets do not need to implement a main method.

    Methods for Milestones

    The JApplet class provides a framework for applet execution, defining methods that the system calls when milestones — major events in an applet's life cycle — occur. Most applets override some or all of these methods to respond appropriately to milestones.

    Methods for Drawing and Event Handling

    Applets inherit the drawing and event handling methods of the AWT Component class. Drawing refers to anything related to representing an applet on-screen — drawing images, presenting user interface components such as buttons, or using graphics primitives. Event handling refers to detecting and processing user input such as mouse clicks and key presses, as well as more abstract events such as saving files and iconifying windows.

    Methods for Adding UI Components

    Applets inherit from the AWT Container class. This means that they are designed to hold Components — user interface objects such as buttons, labels, pop-up lists, and scrollbars. Like other Containers, applets use layout managers to control the positioning of Components.

    What Applets Can and Can't Do

    For security reasons, applets that are loaded over the network have several restrictions. One is that an applet can't ordinarily read or write files on the computer that it's executing on. Another is that an applet can't make network connections except to the host that it came from. Despite these restrictions, applets can do some things that you might not expect. For example, applets can invoke the public methods of other applets on the same page.
    « Previous • Trail • Next »
    Problems with the examples? Try Compiling and Running the Examples: FAQs.
    Complaints? Compliments? Suggestions? Give us your feedback.

    Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

             About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
    Copyright 1995-2008 Sun Microsystems, Inc.
    Previous page: Applets
    Next page: Importing Classes and Packages for Applets


Importing Classes and Packages for Applets (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Getting Started with Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Importing Classes and Packages for Applets

The first two lines of the HelloWorld applet import two classes: JApplet and Graphics.

import javax.swing.JApplet;
import java.awt.Graphics;

public class HelloWorld extends JApplet {
    public void paint(Graphics g) {
    g.drawRect(0, 0,
           getSize().width - 1,
           getSize().height - 1);
        g.drawString("Hello world!", 5, 15);
    }
}

If you removed the first two lines, the applet could still compile and run, but only if you changed the rest of the code like this:

public class HelloWorld extends javax.swing.JApplet {
    public void paint(java.awt.Graphics g) {
        g.drawString("Hello world!", 5, 15);
    }
}

As you can see, importing the JApplet and Graphics classes lets the program refer to them later without any prefixes. The javax.swing. and java.awt. prefixes tell the compiler which packages it should search for the JApplet and Graphics classes.

Both the javax.swing and java.awt packages are part of the core Java API always included in the Java environment.

The javax.swing package contains classes for building Java graphical user interfaces (GUIs), including applets.

The java.awt package contains the most frequently used classes in the Abstract Window Toolkit (AWT).

Besides importing individual classes, you can also import entire packages. Here's an example:

import javax.swing.*;
import java.awt.*;

public class HelloWorld extends JApplet {
    public void paint(Graphics g) {
    g.drawRect(0, 0,
           getSize().width - 1,
           getSize().height - 1);
        g.drawString("Hello world!", 5, 15);
    }
}

In the Java language, every class is in a package. If the source code for a class doesn't have a package statement at the top, declaring the package the class is in, then the class is in the default package. Almost all of the example classes in this tutorial are in the default package. See Creating and Using Packages for information on using the package statement.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Getting Started with Applets
Next page: Defining an Applet Subclass


Defining an Applet Subclass (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Getting Started with Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Defining an Applet Subclass
The first bold line of the following listing begins a block that defines the HelloWorld class.
import javax.swing.JApplet;
import java.awt.Graphics;

public class HelloWorld extends JApplet {
    public void paint(Graphics g) {
    g.drawRect(0, 0,
           getSize().width - 1,
           getSize().height - 1);
        g.drawString("Hello world!", 5, 15);
    }
}

Applets inherit a great deal of functionality from the Applet or JApplet class, including abilities to communicate with the browser and present a graphical user interface (GUI) to the user.

An applet which will be using GUI components from Swing (Java's GUI toolkit) should extend the javax.swing.JApplet base class, which provides the best integration with Swing's GUI facilities.

JApplet provides the same "RootPane" top-level component structure as Swing's JFrame and JDialog components, whereas Applet provides just a simple panel. See How to Use Root Panesfor more details on how to utilize this feature.

An applet may extend java.applet.Applet when it makes no use of Swing's GUI components. This may be the case if the applet does all its own rendering using the Java graphics libraries (such as with graphing or gaming) and/or uses only AWT components.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Importing Classes and Packages for Applets
Next page: The Life Cycle of an Applet


The Life Cycle of an Applet (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Getting Started with Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
The Life Cycle of an Applet

Here is the Simple applet.

The following is the source code for the Simple. The Simple applet displays a descriptive string whenever it encounters a major milestone in its life, such as when the user first visits the page the applet's on. The pages that follow use the Simple applet and build upon it to illustrate concepts that are common to many applets. If you find yourself baffled by the Java source code, you might want to go to Learning the Java Language to learn about the language.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Java(TM) SE 6 Version
 */

import java.applet.Applet;
import java.awt.Graphics;

//No need to extend JApplet, since we don't add any components;
//we just paint.
public class Simple extends Applet {

    StringBuffer buffer;

    public void init() {
        buffer = new StringBuffer();
        addItem("initializing... ");
    }

    public void start() {
        addItem("starting... ");
    }

    public void stop() {
        addItem("stopping... ");
    }

    public void destroy() {
        addItem("preparing for unloading...");
    }

    private void addItem(String newWord) {
        System.out.println(newWord);
        buffer.append(newWord);
        repaint();
    }

    public void paint(Graphics g) {
    //Draw a Rectangle around the applet's display area.
        g.drawRect(0, 0,
           getWidth() - 1,
           getHeight() - 1);

    //Draw the current string inside the rectangle.
        g.drawString(buffer.toString(), 5, 15);
    }
}
Note: In this example, we extend the Applet class, not the Swing JApplet class, as we do not need to add Swing components to this applet.

Loading the Applet
You should see "initializing... starting..." above, as the result of the applet being loaded. When an applet is loaded, here's what happens:
  • An instance of the applet's controlling class (an Applet subclass)is created.
  • The applet initializes itself.
  • The applet starts running.

Leaving and Returning to the Applet's Page
When the user leaves the page — for example, to go to another page — the browser stops the applet. When the user returns to the page, the browser starts the applet.

Browser note: Some browsers reload the applet when you return to its page. In at least one browser, a bug exists where an applet can initialize itself more than once without being reloaded.

Reloading the Applet
Some browsers let the user reload applets, which consists of unloading the applet and then loading it again. Before an applet is unloaded, it's given the chance to stop itself and then to perform a final cleanup, so that the applet can release any resources it holds. After that, the applet is unloaded and then loaded again, as described in Loading the Applet, above.

Try this: If your browser or other applet viewer lets you easily reload applets, reload the applet. Look at the standard output to see what happens when you reload the applet. (See Displaying Short Status Strings for information about the standard output.) You should see "stopping..." and "preparing for unloading..." when the applet is unloaded. You can't see this in the applet GUI because the applet is unloaded before the text can be displayed. When the applet is reloaded, you should see "initializing..." and "starting...", just like when you loaded the applet for the first time.

Quitting the Browser
When the user quits the browser (or whatever application is displaying the applet), the applet has the chance to stop itself and do final cleanup before the browser exits.

Summary

An applet can react to major events in the following ways:
  • It can initialize itself.
  • It can start running.
  • It can stop running.
  • It can perform a final cleanup, in preparation for being unloaded.
The next page describes the four applet methods that correspond to these four types of reactions.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Defining an Applet Subclass
Next page: Methods for Milestones


Methods for Milestones (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Getting Started with Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Methods for Milestones

The Simple applet, like every other applet, features a subclass of the Applet class. The Simple class overrides four Applet methods so that it can respond to major events:

init
To initialize the applet each time it's loaded (or reloaded).
start
To start the applet's execution, such as when the applet is loaded or when the user revisits a page that contains the applet.
stop
To stop the applet's execution, such as when the user leaves the applet's page or quits the browser.
destroy
To perform a final cleanup in preparation for unloading.

Following is the interface for these methods:

public class Simple extends JApplet {
    . . .
    public void init() { . . . }
    public void start() { . . . }
    public void stop() { . . . }
    public void destroy() { . . . }
    . . .
}

The init, start, stop, and destroy methods are discussed and used throughout this tutorial. For more information, you can also refer to the JApplet API Specification.

Overriding These Methods

Not every applet needs to override every one of these methods. Some very simple applets override none of them. For example, the HelloWorld applet at the beginning of this section doesn't override any of these methods, since it doesn't do anything except draw itself.

The "Hello World" applet just displays a string once, using its paint method. (The paint method is described on the following page.) Most applets, however, do more.

The init Method

The init method is useful for one-time initialization that doesn't take very long. In general, the init method should contain the code that you would normally put into a constructor. The reason applets shouldn't usually have constructors is that an applet isn't guaranteed to have a full environment until its init method is called. For example, the Applet image loading methods simply don't work inside of an applet constructor. The init method, on the other hand, is a great place to call the image loading methods, since the methods return quickly.

Browser note: Some browsers sometimes call the init method more than once after the applet has been loaded. See the previous page for more details.

The start Method

Every applet that does something after initialization (except in direct response to user actions) must override the start method. The start method either performs the applet's work or (more likely) starts up one or more threads to perform the work. You'll learn more about threads later in this trail, in the Threads in Applets section. You'll learn more about handling the events that represent user actions on the next page.

The stop Method

Most applets that override start should also override the stop method. The stop method should suspend the applet's execution, so that it doesn't take up system resources when the user isn't viewing the applet's page. For example, an applet that displays animation should stop trying to draw the animation when the user isn't looking at it.

The destroy Method

Many applets don't need to override the destroy method, since their stop method (which is called before destroy) does everything necessary to shut down the applet's execution. However, destroy is available for applets that need to release additional resources.

Note: You should keep implementations of the destroy method as short as possible, because there is no guarantee that this method will be completely executed. The Java Virtual Machine might exit before a long destroy method has completed.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Life Cycle of an Applet
Next page: Methods for Drawing and Event Handling


Methods for Drawing and Event Handling (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Getting Started with Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Methods for Drawing and Event Handling

Using the Paint Method

To draw the applet's representation within a browser page, you use the paint method.

For example, the Simple applet defines its onscreen appearance by overriding the paint method:

public void paint(Graphics g) {
    //Draw a Rectangle around the applet's display area.
        g.drawRect(0, 0,
           getWidth() - 1,
           getHeight() - 1);

    //Draw the current string inside the rectangle.
        g.drawString(buffer.toString(), 5, 15);
    }

Applets inherit the paint method from the Abstract Window Toolkit (AWT) Container class.

Handling Events

Applets inherit a group of event-handling methods from the Container class.

The Container class defines several methods, such as processKeyEvent and processMouseEvent, for handling particular types of events, and then one catch-all method called processEvent.

To react to an event, an applet must override the appropriate event-specific method. For example, the following program, SimpleClick, implements a MouseListener and overrides the mouseClicked method.

/*
 * Java(TM) SE 6 version.
 */

import java.awt.event.MouseListener;
import java.awt.event.MouseEvent;
import java.applet.Applet;
import java.awt.Graphics;

//No need to extend JApplet, since we don't add any components;
//we just paint.
public class SimpleClick extends Applet
             implements MouseListener {

    StringBuffer buffer;

    public void init() {
    addMouseListener(this);
    buffer = new StringBuffer();
        addItem("initializing... ");
    }

    public void start() {
        addItem("starting... ");
    }

    public void stop() {
        addItem("stopping... ");
    }

    public void destroy() {
        addItem("preparing for unloading...");
    }

    void addItem(String newWord) {
        System.out.println(newWord);
        buffer.append(newWord);
        repaint();
    }

    public void paint(Graphics g) {
    //Draw a Rectangle around the applet's display area.
        g.drawRect(0, 0,
           getWidth() - 1,
           getHeight() - 1);

    //Draw the current string inside the rectangle.
        g.drawString(buffer.toString(), 5, 15);
    }

    //The following empty methods could be removed
    //by implementing a MouseAdapter (usually done
    //using an inner class).
    public void mouseEntered(MouseEvent event) {
    }
    public void mouseExited(MouseEvent event) {
    }
    public void mousePressed(MouseEvent event) {
    }
    public void mouseReleased(MouseEvent event) {
    }

    public void mouseClicked(MouseEvent event) {
    addItem("click!... ");
    }
}
Below is the resulting applet. When you click within its rectangle, it displays the word "click!...".

Note: If you don't see the applet running above, you need to install Java Plug-in, which happens automatically when you install the Java(TM) SE JRE or JDK. This applet requires JDK 1.4 or later. You can find more information on the Java Plug-in home page.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Methods for Milestones
Next page: Methods for Adding UI Components


Methods for Adding UI Components (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Getting Started with Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Methods for Adding UI Components
The Simple applet's display code (implemented in its paint method) is flawed: It doesn't support scrolling. Once the text it displays reaches the end of the display rectangle, you can't see any new text. Here's an example of the problem:

The output from the Simple applet demo showing the lack of scrolling.
This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

The simplest cure for this problem is to use a pre-made user interface (UI) component that has the right behavior.

Note: This page glosses over many details. To really learn about using UI components, go to Creating a GUI with JFC/Swing.

Pre-Made UI Components

Swing supplies the following UI components (the class that implements each component is listed in parentheses):
  • Buttons (javax.swing.JButton)
  • Checkboxes (javax.swing.JCheckBox)
  • Single-line text fields (javax.swing.JTextField)
  • Larger text display and editing areas (javax.swing.JTextArea)
  • Labels (javax.swing.JLabel)
  • Lists (javax.swing.JList)
  • Pop-ups (javax.swing.Popup)
  • Scrollbars (javax.swing.JScrollBar)
  • Sliders (javax.swing.JSlider)
  • Drawing areas (java.awt.Canvas)
  • Menus (javax.swing.JMenu,javax.swing.JMenuBar javax.swing.JMenuItem, javax.swing.JCheckBoxMenuItem)
  • Containers (javax.swing.JPanel, javax.swing.JWindow and its subclasses)

Methods for Using UI Components in Applets

Because the JApplet class inherits from the AWT Container class, it's easy to add components to applets and to use layout managers to control the components' onscreen positions. Here are some of the Container methods an applet can use:
add
Adds the specified Component.
remove
Removes the specified Component.
setLayout
Sets the layout manager.

Adding a Non-Editable Text Field to the Simple Applet

To make the Simple applet use a scrolling, non-editable text field, we can use the JTextField class. Here is the revised ScrollingSimple class.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * Java(TM) SE 6 version.
 */

import javax.swing.JApplet;
import javax.swing.JTextField;
import javax.swing.SwingUtilities;

//Since we're adding a Swing component, we now need to
//extend JApplet. We need to be careful to access
//components only on the event-dispatching thread.
public class ScrollingSimple extends JApplet {

    JTextField field;

    public void init() {
        //Execute a job on the event-dispatching thread:
        //creating this applet's GUI.
        try {
            SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    createGUI();
                }
            });
        } catch (Exception e) {
            System.err.println("createGUI didn't successfully complete");
        }

        addItem(false, "initializing... ");
    }

    private void createGUI() {
        //Create the text field and make it uneditable.
        field = new JTextField();
        field.setEditable(false);

        //Set the layout manager so that the text field will be
        //as wide as possible.
        setLayout(new java.awt.GridLayout(1,0));

        //Add the text field to the applet.
        add(field);
    }

    public void start() {
        addItem(false, "starting... ");
    }

    public void stop() {
        addItem(false, "stopping... ");
    }

    public void destroy() {
        addItem(false, "preparing for unloading...");
        cleanUp();
    }

    private void cleanUp() {
        //Execute a job on the event-dispatching thread:
        //taking the text field out of this applet.
        try {
            SwingUtilities.invokeAndWait(new Runnable() {
                public void run() {
                    remove(field);
                }
            });
        } catch (Exception e) {
            System.err.println("cleanUp didn't successfully complete");
        }
        field = null;
    }

    private void addItem(boolean alreadyInEDT, String newWord) {
        if (alreadyInEDT) {
            addItem(newWord);
        } else {
            final String word = newWord;
            //Execute a job on the event-dispatching thread:
            //invoking addItem(newWord).
            try {
                SwingUtilities.invokeAndWait(new Runnable() {
                    public void run() {
                        addItem(word);
                    }
                });
            } catch (Exception e) {
                System.err.println("addItem didn't successfully complete");
            }
        }
    }

    //Invoke this method ONLY from the event-dispatching thread.
    private void addItem(String newWord) {
        String t = field.getText();
        System.out.println(newWord);
        field.setText(t + newWord);
    }
}

The createGUI method creates an uneditable text field (a JTextField instance). It sets the applet's layout manager to one that makes the text field as wide as possible (you'll learn about layout managers in Laying Out Components within a Container) and then adds the text field to the applet.

Below is the resulting applet.

Note: If you don't see the applet running above, you need to install Java Plug-in, which happens automatically when you install the Java(TM) SE JRE or JDK. This applet requires JDK 1.4 or later. You can find more information on the Java Plug-in home page.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Methods for Drawing and Event Handling
Next page: What Applets Can and Can't Do


What Applets Can and Can't Do (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Getting Started with Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
What Applets Can and Can't Do
This page gives an overview of both the restrictions applets face and the special capabilities they have. You'll find more details in the Security Restrictions section.

Security Restrictions

Every browser implements security policies to keep applets from compromising system security. This section describes the security policies that current browsers adhere to. However, the implementation of the security policies differs from browser to browser. Also, security policies are subject to change. For example, if a browser is developed for use only in trusted environments, then its security policies will likely be much more lax than those described here.

Current browsers impose the following restrictions on any applet that is loaded over the network:

  • An applet cannot load libraries or define native methods.
  • It cannot ordinarily read or write files on the host that's executing it.
  • It cannot make network connections except to the host that it came from.
  • It cannot start any program on the host that's executing it.
  • It cannot read certain system properties.
  • Windows that an applet brings up look different than windows that an application brings up.
Each browser has a SecurityManager object that implements its security policies. When a SecurityManager detects a violation, it throws a SecurityException. Your applet can catch this SecurityException and react appropriately.

Applet Capabilities

The java.applet package provides an API that gives applets some capabilities that applications do not have.

Here are some other things that current browers and other applet viewers let applets do:

  • Applets can usually make network connections to the host they came from.
  • Applets running within a Web browser can easily cause HTML documents to be displayed.
  • Applets can invoke public methods of other applets on the same page.
  • Applets that are loaded from the local file system (from a directory in the user's CLASSPATH) have none of the restrictions that applets loaded over the network do.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Methods for Adding UI Components
Next page: Taking Advantage of the Applet API


Taking Advantage of the Applet API (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Taking Advantage of the Applet API

The applet API lets you take advantage of the close relationship that applets have with Web browsers. The API is provided by the javax.swing.JApplet class and the java.applet.AppletContext interface.

Applets can use these APIs to do the following:

  • Be notified by the browser of milestones.
  • Load data files specified relative to the URL of the applet or the page in which it is running.
  • Display short status strings.
  • Make the browser display a document.
  • Find other applets running in the same page.
  • Play sounds.
  • Get parameters specified by the user in the <APPLET> tag.

This section discusses each of these topics in turn, except for the milestone methods (init, start, and so on), which are explained in the Methods for Milestones section. For information about how to use non-applet-specific APIs in an applet, see the Practical Considerations When Writing Applets section.

Finding and Loading Data Files

This section describes how to load your applet's data files, such as images.

Displaying Short Status Strings

This section describes how to make an applet display a string on the status line of the application in which it is running.

Displaying Documents in the Browser

This section tells you how to use the two showDocument methods to request that the browser visit a particular URL.

Sending Messages to Other Applets

This section provides details and example applets that communicate with each other.

Playing Sounds

The AudioClip interface provides support for playing sounds in applets, as explained and demonstrated in this section.

Defining and Using Applet Parameters

This section describes how to decide which parameters to provide, how to implement them, and how to inform the user about them.

Using the APPLET Tag

This section tells you how to customize an applet by editing its HTML tag.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: What Applets Can and Can't Do
Next page: Finding and Loading Data Files


Finding and Loading Data Files (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Taking Advantage of the Applet API
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Finding and Loading Data Files

Whenever an applet needs to load some data from a file that's specified with a relative URL (a URL that doesn't completely specify the file's location), the applet usually uses either the code base or the document base to form the complete URL.

The code base, returned by the JApplet getCodeBase method, is a URL that specifies the directory from which the applet's classes were loaded.

The document base, returned by the JApplet getDocumentBase method, specifies the directory of the HTML page that contains the applet.

Unless the <APPLET> tag specifies a code base, both the code base and document base refer to the same directory on the same server.

Data that the applet might need, or needs to rely on as a backup, is usually specified relative to the code base. Data that the applet developer specifies, often by using parameters, is usually specified relative to the document base.

Note: For security reasons, browsers limit the URLs from which untrusted applets can read. For example, most browsers don't allow untrusted applets to use ".." to get to directories above the code base or document base. Also, since untrusted applets can't read files except those on the applet's originating host, the document base isn't generally useful if the document and the untrusted applet are on different servers.

The JApplet class defines convenient forms of image-loading and sound-loading methods that let you specify images and sounds relative to a base URL. For example, assume an applet is set up with one of the directory structures shown in the following figure.

Two directory structures showing the image files and class files in separate locations, with different structures.

To create an Image object using the a.gif image file under imgDir, the applet can use the following code:

Image image = getImage(getCodeBase(), "imgDir/a.gif");
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Taking Advantage of the Applet API
Next page: Displaying Short Status Strings


Displaying Short Status Strings (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Taking Advantage of the Applet API
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Displaying Short Status Strings

All browsers allow applets to display a short status string. All applets on the page, as well as the browser itself, share the same status line.

You should never put crucial information in the status line. If many users might need the information, it should instead be displayed within the applet area. If only a few, sophisticated users might need the information, consider displaying the information on the standard output (see Displaying Diagnostics to the Standard Output and Error Streams).

The status line is not usually very prominent, and it can be overwritten by other applets or by the browser. For these reasons, it's best used for incidental, transitory information. For example, an applet that loads several image files might display the name of the image file it's currently loading.

Applets display status lines with the showStatus method, inherited in the JApplet class from the Applet class.

Here's an example of its use:

showStatus("MyApplet: Loading image file " + file);
Note: Please don't put scrolling text in the status line. Browser users find such status line abuse highly annoying!
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Finding and Loading Data Files
Next page: Displaying Documents in the Browser


Displaying Documents in the Browser (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Taking Advantage of the Applet API
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Displaying Documents in the Browser

Have you ever wanted an applet to display formatted HTML text? There's an easy way to do it: Ask the browser to display the text for you.

With the AppletContext showDocument methods, an applet can tell the browser which URL to show and in which browser window.

Here are the two forms of showDocument:

public void showDocument(java.net.URL url)
public void showDocument(java.net.URL url, String targetWindow)

The one-argument form of showDocument simply tells the browser to display the document at the specified URL, without specifying the window to display the document in.

Terminology Note: In this discussion, frame refers not to a Swing JFrame, but to an HTML frame within a browser window.

The two-argument form of showDocument lets you specify which window or HTML frame to display the document in. The second argument can have the values listed below.

"_blank"
Display the document in a new, nameless window.
"windowName"
Display the document in a window named windowName. This window is created if necessary.
"_self"
Display the document in the window and frame that contain the applet.
"_parent"
Display the document in parent frame of the applet's frame. If the applet frame has no parent frame, this acts the same as "_self".
"_top"
Display the document in the top-level frame. If the applet's frame is the top-level frame, this acts the same as "_self".

The following applet lets you try every option of both forms of showDocument. The applet brings up a window that lets you type in a URL and choose any of the showDocument options. When you press Return or click the Show document button, the applet calls showDocument.

Note: If you don't see the applet running above, you need to install Java Plug-in, which happens automatically when you install the Java(TM) SE JRE or JDK. This applet requires JDK 1.4 or later. You can find more information on the Java Plug-in home page.

Following is the applet code that calls showDocument. (Here's the whole program.)

        ...//In an Applet subclass:
        urlWindow = new URLWindow(getAppletContext());
        . . .

class URLWindow extends Frame {
    . . .
    public URLWindow(AppletContext appletContext) {
        . . .
        this.appletContext = appletContext;
        . . .
    }
    . . .
    public boolean action(Event event, Object o) {
        . . .
            String urlString = /* user-entered string */;
            URL url = null;
            try {
                url = new URL(urlString);
            } catch (MalformedURLException e) {
                ...//Inform the user and return...
            }

            if (url != null) {
                if (/* user doesn't want to specify the window */) {
                    appletContext.showDocument(url);
                } else {
                    appletContext.showDocument(url,
                                               /* user-specified window */);
                }
            }
        . . .
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Displaying Short Status Strings
Next page: Sending Messages to Other Applets


Sending Messages to Other Applets (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Taking Advantage of the Applet API
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Sending Messages to Other Applets

Applets can find other applets and send messages to them, with the following security restrictions:

  • Many browsers require that the applets originate from the same server.
  • Many browsers further require that the applets originate from the same directory on the server (the same code base).
  • The Java API requires that the applets be running on the same page, in the same browser window.
Note: Some browsers let applets invoke methods on other applets — even applets on different pages in the same browser — as long as all of the applets come from the same code base. This method of interapplet communication isn't supported by the Java API, so it's possible that it will not be supported by all browsers.

An applet can find another applet either by looking it up by name (using the AppletContext getApplet method) or by finding all the applets on the page (using the AppletContext getApplets method). Both methods, if successful, give the caller one or more Applet objects. Once the caller finds an Applet object, the caller can invoke methods on the object.

Finding an Applet by Name: The getApplet Method

The getApplet method looks through all of the applets on the current page to see if one of them has the specified name. If so, getApplet returns the applet's Applet object.

By default, an applet has no name. For an applet to have a name, one must be specified in the HTML code that adds the applet to a page. You can specify an applet's name in two ways:

  • By specifying a NAME attribute within the applet's <APPLET> tag. For example:
    <APPLET CODEBASE=example/ CODE=Sender.class
    WIDTH=450
    HEIGHT=200
    NAME="buddy">
. . .
</APPLET>
  • By specifying a NAME parameter with a <PARAM> tag. For example:
    <APPLET CODEBASE=example/ CODE=Receiver.class
    WIDTH=450
    HEIGHT=50>
<PARAM NAME="name" value="old pal">
. . .
</APPLET>

Browser Note: Although at least one browser enabled with Java technology conducts a case-sensitive search, the expected behavior is for the getApplet method to perform a case-insensitive search. For example, getApplet("old pal") and getApplet("OLD PAL") should both find an applet named "Old Pal".

Below are two applets that illustrate lookup by name. The first, the Sender, looks up the second, the Receiver. When the Sender finds the Receiver, the Sender sends a message to the Receiver by invoking one of the Receiver's methods (passing the Sender's name as an argument). The Receiver reacts to this method call by changing its leftmost text string to "Received message from sender-name!".

Sample Output

Note: If you don't see the applet running above, you need to install Java Plug-in, which happens automatically when you install the Java(TM) SE JRE or JDK. This applet requires JDK 1.4 or later. You can find more information on the Java Plug-in home page.
Try this: Click the Send message button of the top applet (the Sender). Some status information will appear in the Sender's window, and the Receiver will confirm (with its own status string) that it received a message, After you've read the Receiver status string, press the Receiver's Clear button to reset the Receiver. In the Sender's text field labeled "Receiver name:," type in buddy and press Return. Since "buddy" is the Sender's own name, the Sender will find an applet named buddy but won't send it a message, since it isn't a Receiver instance.

Here's the whole Sender program. The code it uses to look up and communicate with the Receiver is listed below. Code that you can use without change in your own applet is in bold font.

Applet receiver = null;
String receiverName = nameField.getText(); //Get name to search for.
receiver = getAppletContext().getApplet(receiverName);
The Sender goes on to make sure that the Receiver was found and that it's an instance of the correct class (Receiver). If all goes well, the Sender sends a message to the Receiver. (Here's the Receiver program.)
if (receiver != null) {
    //Use the instanceof operator to make sure the applet
    //we found is a Receiver object.
    if (!(receiver instanceof Receiver)) {
        status.appendText("Found applet named "
                          + receiverName + ", "
                          + "but it's not a Receiver object.\n");
    } else {
        status.appendText("Found applet named "
                          + receiverName + ".\n"
                          + "  Sending message to it.\n");
        //Cast the receiver to be a Receiver object
        //(instead of just an Applet object) so that the
        //compiler will let us call a Receiver method.
        ((Receiver)receiver).processRequestFrom(myName);
    }
} . . .

From an applet's point of view, its name is stored in a parameter named NAME. It can get the value of the parameter using the Applet getParameter method. For example, Sender gets its own name with the following code:

myName = getParameter("NAME");

For more information on using getParameter, see Writing the Code to Support Parameters.

The example applets in this page perform one-way communication — from the Sender to the Receiver. If you want your receiver to be able to send messages to the sender, then you just need to have the sender give a reference to itself (this) to the receiver. For example:

((Receiver)receiver).startCommunicating(this);

Finding All the Applets on a Page: The getApplets Method

The getApplets method returns a list (an Enumeration, to be precise) of all the applets on the page. For security reasons, many browsers and applet viewers implement getApplets so that it returns only those applets that originated from the same host as the applet calling getApplets. Here's an applet that simply lists all the applets it can find on this page:

Sample Output

Note: If you don't see the applet running above, you need to install Java Plug-in, which happens automatically when you install the Java(TM) SE JRE or JDK. This applet requires JDK 1.4 or later. You can find more information on the Java Plug-in home page.

Below are the relevant parts of the method that calls getApplets. (Here's the whole program.)

public void printApplets() {
    //Enumeration will contain all applets on this page (including
    //this one) that we can send messages to.
    Enumeration e = getAppletContext().getApplets();
    . . .
    while (e.hasMoreElements()) {
        Applet applet = (Applet)e.nextElement();
        String info = ((Applet)applet).getAppletInfo();
        if (info != null) {
            textArea.appendText("- " + info + "\n");
        } else {
            textArea.appendText("- "
                                + applet.getClass().getName()
                                + "\n");
        }
    }
    . . .
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Displaying Documents in the Browser
Next page: Playing Sounds


Playing Sounds (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Taking Advantage of the Applet API
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Playing Sounds

The JApplet class in the Java Swing package (javax.swing), and the AudioClip interface in the Java Applet package (java.applet) provide basic support for playing sounds. Currently, the Java API supports only one sound format: 8 bit, µ-law, 8000 Hz, one-channel, Sun ".au" files. You can create these on a Sun workstation using the audiotool application. You can convert files from other sound formats using an audio format conversion program.

Sound-Related Methods

Below are the sound-related Applet methods. The two-argument form of each method takes a base URL, which is usually returned by either getDocumentBase or getCodeBase, and the location of the sound file relative to the base URL.

getAudioClip(URL), getAudioClip(URL, String)
Return an object that implements the AudioClip interface.
play(URL), play(URL, String)
Play the AudioClip corresponding to the specified URL.

The AudioClip interface defines the following methods:

loop
Starts playing the clip repeatedly.
play
Plays the clip once.
stop
Stops the clip. Works with both looping and one-time sounds.

An Example

Here is an applet called SoundExample that illustrates a few things about sound. Note that, for instructional purposes, the applet adds up to 10 seconds to the load time for each sound. If the sounds were larger or the user's connection slower than ours, these delays might be realistic.

Note: If you don't see the applet running above, you need to install Java Plug-in, which happens automatically when you install the Java(TM) SE JRE or JDK. This applet requires JDK 1.4 or later. You can find more information on the Java Plug-in home page.

The SoundExample applet provides an architecture for loading and playing multiple sounds in an applet. For this reason, it is more complex than necessary. Essentially, the sound loading and playing code boils down to this:

AudioClip onceClip, loopClip;
onceClip = applet.getAudioClip(getCodeBase(), "bark.au");
loopClip = applet.getAudioClip(getCodeBase(), "train.au");
onceClip.play();     //Play it once.
loopClip.loop();     //Start the sound loop.
loopClip.stop();     //Stop the sound loop.

Since there's nothing more annoying than an applet that continues to make noise after you've left its page, the SoundExample applet stops playing the continuously looping sound when the user leaves the page, and resumes playing it when the user comes back. It does this by implementing its stop and start methods as follows:

public void stop() {
    //If one-time sound were long, we'd stop it here, too.
    //looping is a boolean instance variable that's initially
    //false. It's set to true when the "Start sound loop" button
    //is clicked and to false when the "Stop sound loop" or "Reload
    //sounds" button is clicked.
    if (looping) {
        loopClip.stop();    //Stop the sound loop.
    }
}

public void start() {
    if (looping) {
        loopClip.loop();    //Restart the sound loop.
    }
}

The SoundExample applet features three classes:

  • A JApplet subclass, SoundExample, that controls the applet's execution.
  • A Hashtable subclass, SoundList, that holds AudioClips. This is overkill for this applet, but if you were to write an applet that used lots of sound files, a class like this would be useful.
  • A Thread subclass, SoundLoader, each instance of which loads an AudioClip in the background. During the applet's initialization, the applet preloads each sound by creating a SoundLoader for it.

Preloading the sounds in a background thread (with SoundLoader) improves the perceived performance by reducing the amount of time the user has to wait to be able to interact with the applet. It does this by reducing the amount of time spent in the init method. If you simply called getAudioClip in the applet's init method, it could take quite a while before getAudioClip returned, meaning that the applet couldn't perform the other statements in its init method, and that the applet's start wouldn't get called. (For this SoundExample applet, a delay in calling the start method doesn't matter.)

Another advantage of loading the sounds in a background thread is that it enables the applet to respond appropriately (and immediately) to user input that would normally cause a sound to play, even if that sound hasn't been loaded yet. If you simply use the Applet play method, for example, then the first time the user does something to make the applet play a particular sound, the applet's drawing and event handling are frozen while the sound is loaded. Instead, this applet detects that the sound hasn't been loaded yet and responds appropriately.

This example is discussed in more detail in Threads in Applets: Examples.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Sending Messages to Other Applets
Next page: Defining and Using Applet Parameters


Defining and Using Applet Parameters (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Taking Advantage of the Applet API
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Defining and Using Applet Parameters

Parameters are to applets what command-line arguments are to applications. They allow the user to customize the applet's operation. By defining parameters, you can increase your applet's flexibility, making your applet work in multiple situations without recoding and recompiling it.

The next few pages discuss parameters from the applet programmer's point of view. To learn about the user view of parameters, see Specifiying Parameters.

Deciding Which Parameters to Support

When implementing parameters, you must answer four questions:

  • What should the applet let the user configure?
  • What should the parameters be named?
  • What kind of value should each parameter take?
  • What should the default value of each parameter be?

Writing the Code to Support Parameters

Applets get the user-defined values of parameters by calling the Applet getParameter method.

Giving Information about Parameters

By implementing the getParameterInfo method, applets provide information that browsers can use to help the user set parameter values.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Playing Sounds
Next page: Deciding Which Parameters to Support


Deciding Which Parameters to Support (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Taking Advantage of the Applet API
Subsection: Defining and Using Applet Parameters
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Deciding Which Parameters to Support

This page guides you through the four questions you should ask as you implement parameters:

  • What should the applet let the user configure?
  • What should the parameters be named?
  • What kind of value should each parameter take?
  • What should the default value of each parameter be?

It ends with a discussion of the parameters defined in a sample <APPLET> tag.

What Should the Applet Let the User Configure?
The parameters your applet should support depend on what your applet does and on how flexible you want it to be. Applets that display images might have parameters to specify the image locations. Similarly, applets that play sounds might have parameters to specify the sounds.

Besides parameters that specify resource locations (such as image and sound files), applets sometimes provide parameters for specifying details of the applet's appearance or operation. For example, an animation applet might let the user specify the number of images shown per second. Or an applet might let the user change the strings the applet displays. Anything is possible.

What Should the Parameters Be Named?
Once you decide what parameters your applet will support, you need to figure out their names. Here are some typical parameter names:
SOURCE or SRC
For a data file such as an image file.
XXXSOURCE (for example, IMAGESOURCE)
Used in applets that let the user specify more than one type of data file.
XXXS
For a parameter that takes a list of XXXs (where XXX might be IMAGE, again).
NAME
Used only for an applet's name. Applet names are used for interapplet communication, as described in Sending Messages to Other Applets.

Clarity of names is more important than keeping the name length short. Do not use names of <APPLET> tag attributes, which are documented in Using the applet Tag.

Note: Although this tutorial usually refers to parameter names using ALL UPPERCASE, parameter names are case-insensitive. For example, IMAGESOURCE and imageSource both refer to the same parameter. Parameter values, on the other hand, are case-sensitive unless you take steps to interpret them otherwise, such as by using the String toLowerCase method before interpreting the parameter's value.

What Kind of Value Should Each Parameter Take?
Parameter values are all strings. Whether or not the user puts quotation marks around a parameter value, that value is passed to your applet as a string. However, your applet can interpret the string in many ways.

Applets typically interpret a parameter value as one of the following types:

  • A URL
  • An integer
  • A floating-point number
  • A boolean value -- typically "true"/"false" or "yes"/"no"
  • A string -- for example, the string to use as a window title
  • A list of any of the above

What Should the Default Value of Each Parameter Be?
Applets should attempt to provide useful default values for each parameter, so that the applet will execute even if the user doesn't specify a parameter or specifies it incorrectly. For example, an animation applet should provide a reasonable setting for the number of images it displays per second. This way, if the user doesn't specify the relevant parameter, the applet will still work well.

An Example: A Sample <APPLET> Tag

Here's what a typical <APPLET> tag looks like.
<APPLET CODE=SampleApplet.class CODEBASE=example
     WIDTH=350 HEIGHT=60>
<PARAM NAME=windowClass VALUE=BorderWindow>
<PARAM NAME=windowTitle VALUE="BorderLayout">
<PARAM NAME=buttonText
       VALUE="Click here to see a BorderLayout in action">
</APPLET>

When the user doesn't specify a value for a parameter, the applet uses a reasonable default value. For example, if the user doesn't specify the window's title, the applet uses the window's type as the title.

The next page shows you how to get parameter values from the user.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Defining and Using Applet Parameters
Next page: Writing the Code to Support Parameters


Writing the Code to Support Parameters (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Taking Advantage of the Applet API
Subsection: Defining and Using Applet Parameters
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Writing the Code to Support Parameters
Applets use the Applet getParameter method to get user-specified values for applet parameters. The getParameter method is defined as follows:
public String getParameter(String name)

Your applet might need to convert the string that getParameter returns into another form, such as an integer. The java.lang package provides classes such as Integer that you can use to help with converting strings to primitive types. Here's an example of converting a parameter's value into an integer:

int requestedWidth = 0;
. . .
String windowWidthString = getParameter("WINDOWWIDTH");
if (windowWidthString != null) {
    try {
        requestedWidth = Integer.parseInt(windowWidthString);
    } catch (NumberFormatException e) {
        //Use default width.
    }
}
Note that if the user doesn't specify a value for the WINDOWWIDTH parameter, the above code uses a default value of 0, which the applet interprets as "use the window's natural size." It's important that you supply default values wherever possible.

Besides using the getParameter method to get values of applet-specific parameters, you can also use getParameter to get the values of attributes of the applet's <APPLET> tag. See Using the applet Tag for a list of <APPLET> tag attributes.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Deciding Which Parameters to Support
Next page: Giving Information about Parameters


Giving Information about Parameters (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Taking Advantage of the Applet API
Subsection: Defining and Using Applet Parameters
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Giving Information about Parameters
Now that you've provided all those nice parameters to the user, you need to help the user set the parameter values correctly. Of course, your applet's documentation should describe each parameter and give the user examples and hints of setting them. Your job doesn't stop there, though. You should also implement the getParameterInfo method so that it returns information about your applet's parameters. Browsers can use this information to help the user set your applet's parameter values.

Below is an example of implementing the getParameterInfo method.

public String[][] getParameterInfo() {
    String[][] info = {
      // Parameter Name     Kind of Value   Description
        {"imagesource",     "URL",          "a directory"},
        {"startup",         "URL",          "displayed at startup"},
        {"background",      "URL",          "displayed as background"},
        {"startimage",      "int",          "start index"},
        {"endimage",        "int",          "end index"},
        {"namepattern",     "URL",          "used to generate indexed names"},
        {"pause",           "int",          "milliseconds"},
        {"pauses",          "ints",         "milliseconds"},
        {"repeat",          "boolean",      "repeat or not"},
        {"positions",       "coordinates",  "path"},
        {"soundsource",     "URL",          "audio directory"},
        {"soundtrack",      "URL",          "background music"},
        {"sounds",          "URLs",         "audio samples"},
    };
    return info;
}
As you can see, the getParameterInfo method must return an array of three-String arrays. In each three-String array, the first string is the parameter name. The second string gives the user a hint about what general kind of value the applet needs for the parameter. The third string describes the meaning of the parameter.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Writing the Code to Support Parameters
Next page: Using the APPLET Tag


Using the APPLET Tag (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Taking Advantage of the Applet API
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Using the APPLET Tag
This section tells you most of what you need to know to use the <APPLET> tag. It starts by showing you the tag's simplest form. It then discusses some of the most common additions to that simple form: the <PARAM> tag, alternate HTML code and text, the CODEBASE attribute, and the ARCHIVE attribute. For a detailed description of the <APPLET> tag, refer to Using the applet Tag.

You should already have seen the simplest form of the <APPLET> tag:

<APPLET CODE=AppletSubclass.class WIDTH=anInt HEIGHT=anInt>
</APPLET>
This tag tells the browser to load the applet whose Applet subclass is named AppletSubclass, displaying it in an area of the specified width and height.

Specifying Parameters

Some applets let the user customize the applet's configuration with parameters, as described in Defining and Using Applet Parameters. For example, AppletButton (an applet used throughout this tutorial to provide a button that brings up a window) allows the user to set the button's text by specifying the value of a parameter named BUTTONTEXT.

The developer provides the value of a parameter using a <PARAM> tag. The <PARAM> tags should appear just after the <APPLET> tag for the applet they affect:

<APPLET CODE=AppletSubclass.class WIDTH=anInt HEIGHT=anInt>
<PARAM NAME=parameter1Name VALUE=aValue>
<PARAM NAME=parameter2Name VALUE=anotherValue>
</APPLET>

Here's an example of the <PARAM> tag in use.

<APPLET CODE="Animator.class" WIDTH=460 HEIGHT=160>
<PARAM NAME="imageSource" VALUE="images/Beans">
<PARAM NAME="backgroundColor" VALUE="0xc0c0c0">
<PARAM NAME="endImage" VALUE=10>
<PARAM NAME="soundSource" VALUE="audio">
<PARAM NAME="soundtrack" VALUE="spacemusic.au">
<PARAM NAME="sounds"
    VALUE="1.au|2.au|3.au|4.au|5.au|6.au|7.au|8au|9.au|0.au">
<PARAM NAME="pause" VALUE=200>
. . .
</APPLET>

Specifying Alternate HTML Code and Text

Note the ellipsis points (". . .") in the previous HTML example. What did the example leave out? It omitted alternate HTML code — HTML code interpreted only by browsers that don't understand the <APPLET> tag. Alternate HTML code is any text that appears between the <APPLET> and </APPLET> tags, after any <PARAM> tags. Browsers enabled with Java technology ignore alternate HTML code.

To specify alternate text to browsers enabled with Java technology and other browsers that understand the <APPLET> tag, use the ALT attribute. If the browser can't display an applet for some reason, it can display the applet's ALT text.

We use alternate HTML code throughout the online version of this tutorial to tell readers about the applets they're missing. Often, the alternate HTML code includes one or more pictures of the applet. Here's the complete HTML code for the Animator example shown previously:

<APPLET CODE="Animator.class" WIDTH=460 HEIGHT=160
 ALT="If you could run this applet, you'd see some animation">
<PARAM NAME="imageSource" VALUE="images/Beans">
<PARAM NAME="backgroundColor" VALUE="0xc0c0c0">
<PARAM NAME="endImage" VALUE=10>
<PARAM NAME="soundSource" VALUE="audio">
<PARAM NAME="soundtrack" VALUE="spacemusic.au">
<PARAM NAME="sounds"
       VALUE="1.au|2.au|3.au|4.au|5.au|6.au|7.au|8au|9.au|0.au">
<PARAM NAME="pause" VALUE=200>
Your browser is completely ignoring the &lt;APPLET&gt; tag!
</APPLET>
A browser that does not understand the <APPLET> tag ignores everything in the previous HTML code except the line that starts with "Your". A browser that does understand the <APPLET> tag ignores everything on that line. If the applet-savvy browser can't run the applet, it might display the ALT text.

Specifying the Applet Directory

By default, a browser looks for an applet's class and archive files in the same directory as the HTML file that has the <APPLET> tag. (If the applet's class is in a package, then the browser uses the package name to construct a directory path underneath the HTML file's directory.) Sometimes, however, it's useful to put the applet's files somewhere else. You can use the CODEBASE attribute to tell the browser in which directory the applet's files are located:
<APPLET CODE=AppletSubclass.class CODEBASE=aURL
        WIDTH=anInt HEIGHT=anInt>
</APPLET>
If aURL is a relative URL, then it's interpreted relative to the HTML document's location. By making aURL an absolute URL, you can load an applet from just about anywhere — even from another HTTP server.

This tutorial uses CODEBASE="someDirectory/" frequently, since we group the examples for each lesson in subdirectories. For example, here's the <APPLET> tag that includes the Simple applet in The Life Cycle of an Applet:

<APPLET CODE=Simple.class CODEBASE="example/"
        WIDTH=500 HEIGHT=20>
</APPLET>
The following figure shows the location of the class file, relative to the HTML file, when CODEBASE is set to "example/".

Location of the class file when CODEBASE is set to

The next figure shows where the applet class can be if you specify an absolute URL for the value of CODEBASE.

Location of applet class when CODEBASE is set to an absolute URL.

Combining an Applet's Files into a Single File

If your applet has more than one file, you should consider providing an archive file that bundles the applet's files into a single file. Whether archive files make sense for your applet depends on several factors, including your applet's size, performance considerations, and the environment you expect your users to have.

Archive files reduce your applet's total download time. Much of the time saved comes from reducing the number of HTTP connections that the browser must make. Each HTTP connection can take several seconds to start. This means that for a multifile applet, connection time can dwarf transfer time. You can further reduce transfer time by compressing the files in your archive file.

If you specify one or more archive files, then the applet class loader looks for the archive files in the same directory that it would search for the applet class file. The applet class loader then looks for the applet's class files in the archive files. If a file isn't in the archive, then the applet class loader generally tries to load it in the browser just as it would if the archive file weren't present.

The standard Java archive format, called JAR, was introduced in JDK 1.1 and is based on the ZIP file format. You specify JAR files using the ARCHIVE attribute of the <APPLET> tag. You can specify multiple archive files by separating them with commas:

<APPLET CODE="AppletSubclass.class" ARCHIVE="file1, file2"
        WIDTH=anInt HEIGHT=anInt>
</APPLET>
Unfortunately, not all browsers understand the same archive format or use the same HTML code to specify the applet archive. Watch this page for the latest information about browser support for archives. To learn how to create a JAR file, see Creating a JAR File.

Other <APPLET> Tag Attributes

This section didn't discuss every attribute of the <APPLET> tag. Other attributes — which might seem familiar, since the <IMG> HTML tag uses them — include ALIGN, VSPACE, and HSPACE. The <APPLET> tag also allows you to load a serialized (saved) applet by specifying the OBJECT attribute instead of specifying a class file with CODE. Finally, you can name an applet using the NAME attribute. For a detailed description of the <APPLET> tag, see Using the applet Tag.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Giving Information about Parameters
Next page: Practical Considerations When Writing Applets


Practical Considerations When Writing Applets (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Practical Considerations When Writing Applets
The first two sections in this lesson discussed all of the applet-specific API. However, most applets rely on a lot of API that isn't specific to applets. This section gives you hints about using the Java API, covering the areas that are affected by applets' close relationships with browsers.

Security Restrictions

This section lists the security restrictions that untrusted applets face. It also describes some ways to get around the restrictions.

Creating a User Interface

This section discusses the elements of an applet's UI. It then goes on to give hints for creating a GUI and creating debugging output using the standard output and standard error streams.

Getting System Properties

This section discusses the system properties that an applet can get to find out about its environment. It includes an example applet that displays the ten properties applets can get. It also lists some properties that applets typically can't get.

Threads in Applets

This section delves into the issues of using threads in applets. A thread — sometimes called an execution context or a lightweight process — is a single sequential flow of control within a process. Even the simplest applets run in multiple threads, although it's not always apparent. Many applets create and use their own threads so that they perform well without affecting the performance of the browser they run in or the performance of other applets.

Working with a Server-Side Application

This section shows how even untrusted applets can use networking code to communicate with programs running on the host from which they came.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using the APPLET Tag
Next page: Security Restrictions


Security Restrictions (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Practical Considerations When Writing Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Security Restrictions
One of the main goals of the Java environment is to make browser users feel secure running any applet. To achieve this goal, we've started out conservatively, restricting capabilities perhaps more than necessary. As time passes, applets will probably get more and more abilities.

This page tells you about the current applet security restrictions, from the point of view of how they affect applet design. For more information on applet security, you should refer to:

Frequently Asked Questions - Applet Security

Each applet viewer has a SecurityManager object that checks for applet security violations. When a SecurityManager detects a violation, it creates and throws a SecurityException object. Generally, the SecurityException constructor prints a warning message to the standard output. An applet can catch SecurityExceptions and react appropriately, such as by reassuring the user and by resorting to a "safer" (but less ideal) way of accomplishing the task.

Some applet viewers swallow some SecurityExceptions, so that the applet never gets the SecurityException. For example, the JDK Applet Viewer's implementation of the AppletContext getApplet and getApplets methods simply catches and ignores any SecurityExceptions. The user can see an error message in the standard output, but at least the applet gets a valid result from the methods. This makes some sense, since getApplets should be able to return any valid applets it finds, even if it encounters invalid ones. (The Applet Viewer considers an applet valid if it's loaded from the same host as the applet that's calling getApplets.)

To learn about security managers and the kinds of security violations they can check for, see The Security Manager.

Existing applet viewers (including Web browsers) impose the following restrictions:

Applets cannot load libraries or define native methods.
Applets can use only their own Java code and the Java API the applet viewer provides. At a minimum, each applet viewer must provide access to the API defined in the java.* packages.

An applet cannot ordinarily read or write files on the host that is executing it.
The JDK Applet Viewer actually permits some user-specified exceptions to this rule, but older browsers generally do not. Applets in any applet viewer can read files specified with full URLs, instead of by a filename. A workaround for not being able to write files is to have the applet forward data to an application on the host the applet came from. This application can write the data files on its own host. See Working with a Server-Side Application for more examples.

An applet cannot make network connections except to the host that it came from.
The workaround for this restriction is to have the applet work with an application on the host it came from. The application can make its own connections anywhere on the network. See Using a Server to Work Around Security Restrictions for an example.

An applet cannot start any program on the host that is executing it.
Again, an applet can work with a server-side application instead.

An applet cannot read certain system properties.
See Getting System Properties for more information.

Windows that an applet brings up look different than windows that an application brings up.
You can identify the Applet window by the name 'Java Applet Window', which is displayed at the bottom of the window. Application window would not have any name at its bottom. This helps the user distinguish applet windows from those of trusted applications.

The following figures show a window brought up by a program that can run either as an applet or as an application. The first figure shows what the window looks like when the program is run as an application on the Microsoft Windows platform. The second figure shows the window when the program runs as an applet on the Windows platform within the Mozilla browser.

A screenshot of the program running as an application.

A program running as an application

A screenshot of the same program running as an applet.

Same program running as an applet

As you can see, the applet window has a label informing the user that it is running as an applet.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Practical Considerations When Writing Applets
Next page: Creating a User Interface


Creating a User Interface (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Practical Considerations When Writing Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Creating a User Interface
Most applets have a graphical user interface (GUI). This is a natural consequence of the fact that each applet appears within a browser window. Because the JApplet class is a subclass of the AppletPanel class and thus participates in the AWT event and drawing model, creating an applet's GUI is just as easy as creating an application's GUI — easier, actually, since the applet's window (the browser window) already exists.

In addition to its graphical UI, an applet can use several other UI types, depending on the kind of information it needs to give or get. Some applets play sounds, either to give the user feedback or to provide ambiance. Applets can get configuration information from the user through parameters that the applet defines. To give text information to the user, an applet can use its GUI, display a short status string (for text that's not crucial), or display to the standard output or standard error stream (for debugging purposes).

For information about sound, parameters, and status strings, see the Taking Advantage of the Applet API section. The rest of this section discusses the following topics, as they pertain to applets:

  • Creating a GUI
  • Displaying Diagnostics to the Standard Output and Error Streams
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Security Restrictions
Next page: Creating a GUI


Creating a GUI (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Practical Considerations When Writing Applets
Subsection: Creating a User Interface
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Creating a GUI
This page discusses the few issues that are particular to applet GUIs. Some of the information in this section might not make sense until you've read the Creating a GUI with JFC/Swing trail and, in particular, the How to Make Applets section. That trail discusses all the GUI concepts referred to on this page.

Applets appear in pre-existing browser windows.
This has two implications. First, unlike GUI-based applications, applets don't have to create a window in which to display themselves. They can, if they have a good reason, but they often just display themselves within the browser window. Second, depending on the browser implementation, your applet's components might not be shown unless your applet calls validate after adding components to itself. Fortunately, calling validate can't hurt.

The applet background color might not match the page color.
By default, applets have a white background color. HTML pages, however, can have other background colors and can use background patterns. If the applet designer and page designer aren't careful, the applet's different background color can cause it to stick out on the page or cause noticeable flashing when the applet is drawn. One solution is to define an applet parameter that specifies the applet's background color. The JApplet class can use JComponent's setBackground method to set the applet's background to the color specified in the web page. Using the background color parameter, the page designer can choose an applet color that works well with the page colors. You'll learn about parameters in Defining and Using Applet Parameters.

Each applet has a user-specified, pre-determined size.
The <APPLET> tag requires that the applet's width and height be specified. The web designer can set an applet's size by pixels, or by indicating a percentage of the browser window. Note that even if the amount of space is ideal for one platform, the platform-specific parts of the applet (such as buttons) might require a different amount of space on another platform. You can compensate by recommending that pages that include your applet specify a little more space than might be necessary, and by using flexible layouts, such as the GridBagLayout and BorderLayout classes, that adapt well to extra space.

Applets load images using the Applet getImage methods.
The Applet class provides a convenient form of getImage that lets you specify a base URL as one argument, followed by a second argument that specifies the image file location, relative to the base URL. The Applet getCodeBase and getDocumentBase methods provide the base URLs that most applets use. Images that an applet always needs, or needs to rely on as a backup, are usually specified relative to where the applet's code was loaded from (the code base). Images that are specified by the applet user (often with parameters in the HTML file) are usually relative to the page that includes the applet (the document base).

Applet classes (and often the data files they use) are loaded over the network, which can be slow.
Applets can do several things to decrease the perceived startup time. The Applet subclass can be a small one that immediately displays a status message. If some of the applet's classes or data aren't used right away, the applet can preload the classes or data in a background thread.

For example, if an applet class start method launches a thread that gets the Class object for a window, then the applet's main purpose in doing so is to make sure the class name the user specified is valid. An added benefit is that getting the Class object forces the class file to be loaded before the class is instantiated. When the user requests that the window be created, the applet instantiates the window class much quicker than if the applet still had to load the window class file.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating a User Interface
Next page: Displaying Diagnostics to the Standard Output and Error Streams


Displaying Diagnostics to the Standard Output and Error Streams (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Practical Considerations When Writing Applets
Subsection: Creating a User Interface
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Displaying Diagnostics to the Standard Output and Error Streams
Displaying diagnostics to the standard output can be an invaluable tool when you're debugging an applet. Another time you'll see messages at the standard output is when an uncaught exception occurs in an applet. Applets also have the option of using the standard error stream.

Where exactly the standard output and error are displayed varies, depending on how the applet's viewer is implemented, what platform it's running on, and (sometimes) how you launch the browser or applet viewer. When you launch the Applet Viewer from a UNIX shell window, for example, strings displayed to the standard output and error appear in that shell window, unless you redirect the output. When you launch the Applet Viewer from an X Windows menu, the standard output and error go to the console window.

Applets display to the standard output stream using System.out.print(String) and System.out.println(String). Displaying to the standard error stream is similar; just specify System.err instead of System.out. Here's an example of displaying to the standard output:

//Where instance variables are declared:
boolean DEBUG = true;
. . .
//Later, when we want to print some status:
if (DEBUG) {
    System.out.println("Called someMethod(" + x + "," + y + ")");
}
Note: Displaying to the standard output and error streams is relatively slow. If you have a timing-related problem, printing messages to either of these streams might not be helpful.

You should be sure to disable all debugging output before you release your applet.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating a GUI
Next page: Getting System Properties


Getting System Properties (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Practical Considerations When Writing Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Getting System Properties
To find out about the current working environment, applets can read system properties. System properties are key/value pairs that contain information such as the operating system that the applet is running under. System properties are covered in detail in the Properties page.

Applets can read some, but not all, system properties.

System Properties that Applets Can Read

Applets can read the following system properties:

Valid System Properties
Key | Meaning
"file.separator" | File separator (for example, "/")
"java.class.version" | Java class version number
"java.vendor" | Java vendor-specific string
"java.vendor.url" | Java vendor URL
"java.version" | Java version number
"line.separator" | Line separator
"os.arch" | Operating system architecture
"os.name" | Operating system name
"path.separator" | Path separator (for example, ":")

To read a system property from within an applet, the applet uses the System class method getProperty. For example:

String newline = System.getProperty("line.separator");
The following applet reads all of the properties that are available to all applets:

Sample Output

You can find the source code in GetOpenProperties.java.

Forbidden System Properties

For security reasons, no existing browsers or applet viewers let applets read the following system properties.

Forbidden System Properties
Key | Meaning
"java.class.path" | Java classpath
"java.home" | Java installation directory
"user.dir" | User's current working directory
"user.home" | User home directory
"user.name" | User account name

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Displaying Diagnostics to the Standard Output and Error Streams
Next page: Threads in Applets


Threads in Applets (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Practical Considerations When Writing Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Threads in Applets
Note: This page assumes that you know what a thread is. If you don't, please read Processes and Threads before reading this page.

Every applet can run in multiple threads. The applet's GUI is created on the event-dispatching thread. The threads that the major milestone methods — init, start, stop, and destroy — are called from depends on the application that's running the applet. But no application ever calls them from the event handling thread.

Many browsers allocate a thread for each applet on a page, using that thread for all calls to the applet's major milestone methods. Some browsers allocate a thread group for each applet, so that it's easy to kill all the threads that belong to a particular applet. In any case, you're guaranteed that every thread that any of an applet's major milestone methods creates belongs to the same thread group.

Below is a PrintThread applet. PrintThread is a modified version of SimpleApplet that prints the thread and thread group that its init, start, stop, destroy, and update methods are called from. Here's the code for the PrintThread example.

As usual, to see the output for the methods such as destroy that are called during unloading, you need to look at the standard output. For standard output for an applet run in a browser, open the Java Console from the browser's Tools menu. See Displaying Diagnostics to the Standard Output and Error Streams for information about the standard output stream.

Note: If you don't see the applet running above, you need to install Java Plug-in, which happens automatically when you install the Java(TM) SE JRE or JDK. This applet requires JDK 1.4 or later. You can find more information on the Java Plug-in home page.

So why would an applet need to create and use its own threads? Imagine an applet that performs some time-consuming initialization — loading images, for example — in its init method. The thread that invokes init can not do anything else until init returns. In some browsers, this might mean that the browser can't display the applet or anything after it until the applet has finished initializing itself. So if the applet is at the top of the page, for example, then nothing would appear on the page until the applet has finished initializing itself.

Even in browsers that create a separate thread for each applet, it makes sense to put any time-consuming tasks into an applet-created thread, so that the applet can perform other tasks while it waits for the time-consuming ones to be completed.

Rule of Thumb: If an applet performs a time-consuming task, it should create and use its own thread to perform that task.

Applets typically perform two kinds of time-consuming tasks: tasks that they perform once, and tasks that they perform repeatedly. The next page gives an example of both.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Getting System Properties
Next page: Threads in Applets: Examples


Threads in Applets: Examples (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Practical Considerations When Writing Applets
Subsection: Threads in Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Threads in Applets: Examples
This page discusses two examples of using threads in applets. The first applet, AnimatorApplet, shows how to use a thread to perform repeated tasks. The second applet this page discusses, SoundExample, shows how to use threads for one-time initialization tasks. SoundExample is featured in Playing Sounds.

This page does not explain basic thread code. To learn about the Java implementation of threads, refer to Defining and Starting a Thread.

Using a Thread to Perform Repeated Tasks

An applet that performs the same task over and over again typically should have a thread with a while (or do...while) loop that performs the task. A typical example is an applet that performs timed animation, such as a movie player or a game. Animation applets need a thread that requests repaints at regular intervals. Another example is an applet that reads data supplied by a server-side application. (See Using a Server to Work Around Security Restrictions for such an example.)

Applets typically create threads for repetitive tasks in the applet start method. Creating the thread there makes it easy for the applet to stop the thread when the user leaves the page. All you need to do is implement the stop method so that it stops the applet's thread. When the user returns to the applet's page, the start method is called again, and the applet can again create a thread to perform the repetitive task.

Below is AnimatorApplet's implementation of the start and stop methods.

public void start() {
    if (frozen) {
        //Do nothing.  The user has requested that we
        //stop changing the image.
    } else {
        //Start animating!
        if (animatorThread == null) {
            animatorThread = new Thread(this);
        }
        animatorThread.start();
    }
}

public void stop() {
    animatorThread = null;
}

The this in new Thread(this) indicates that the applet provides the body of the thread. It does so by implementing the java.lang.Runnable interface, which requires the applet to provide a run method that forms the body of the thread. We'll discuss AnimatorApplet's run method more a little later.

Notice that nowhere in the AnimatorApplet class is the Thread stop method called. This is because calling the Thread stop method is like clubbing the thread over the head. It's a drastic way to get the thread to stop what it's doing. Instead, you can write the thread's run method in such a way that the thread will gracefully exit when you tap it on the shoulder. This shoulder tap comes in the form of setting to null an instance variable of type Thread.

In AnimatorApplet, this instance variable is called animatorThread. The start method sets it to refer to the newly created Thread object. When the applet needs to kill the thread, it sets animatorThread to null. This kills the thread not by making it be garbage collected — it can't be garbage collected while it's runnable — but because at the top of its loop, the thread checks animatorThread, continuing or exiting depending on the value of animatorThread. Here's the relevant code:

public void run() {
    . . .
    while (Thread.currentThread() == animatorThread) {
        ...//Display a frame of animation and then sleep.
    }
}

If animatorThread refers to the same thread as the currently executing thread, the thread continues executing. If, on the other hand, animatorThread is null, the thread exits. If animatorThread refers to another thread, then a race condition has occurred: start has been called so soon after stop (or this thread has taken such a long time in its loop) that start has created another thread before this thread reached the top of its while loop. Whatever the cause of the race condition, this thread should exit.

For more information about animation applets, see Creating the Animation Loop, a section in Creating a GUI with JFC/Swing.

Using a Thread to Perform One-Time Initialization

If your applet needs to perform some initialization task that can take a while, you should consider ways of performing the initialization in a thread. For example, anything that requires making a network connection should generally be done in a background thread. Fortunately, GIF, PNG, and JPEG image loading is automatically done in the background using threads that you don't need to worry about.

Sound loading, unfortunately, is not guaranteed to be done in the background. In current implementations, the Applet getAudioClip methods don't return until they've loaded all the audio data. As a result, if you want to preload sounds, you might want to create one or more threads to do so.

Using a thread to perform a one-time initialization task for an applet is a variation of the classic producer/consumer scenario. The thread that performs the task is the producer, and the applet is the consumer. Synchronization discusses how to use Java threads in a producer/consumer scenario.

SoundExample adheres closely to the model presented in Synchronizing Threads. Like the Synchronizing Threads example, SoundExample features three classes:

  • The producer: SoundLoader, a Thread subclass.
  • The consumer: SoundExample, an Applet subclass. Unlike the Synchronizing Threads consumer example, SoundExample is not a Thread; it doesn't even implement the Runnable interface. However, the SoundExample instance methods are executed by at least two threads, depending on the application that executes the SoundExample applet.
  • The storage object: SoundList, a Hashtable subclass. Unlike CubbyHole in the Synchronizing Threads example, SoundList can return null values if the sound data hasn't been stored yet. This makes sense for this applet because it needs to be able to react immediately to a user request to play the sound, even if the sound hasn't been loaded yet.
For more information on SoundExample, go to Playing Sounds.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Threads in Applets
Next page: Working with a Server-Side Application


Working with a Server-Side Application (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Practical Considerations When Writing Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Working with a Server-Side Application
Applets, like other Java programs, can use the API defined in the java.net package to communicate across the network. The only difference is that, for security reasons, the only host an applet can communicate with is the host it was delivered from.

Note: Depending on the networking environment an applet is loaded into, and depending on the browser that runs the applet, an applet might not be able to communicate with its originating host. For example, browsers running on hosts inside firewalls often cannot get much information about the world outside the firewall. As a result, some browsers might not allow applet communication to hosts outside the firewall.

It's easy to find out which host an applet came from. Just use the Applet getCodeBase method and the java.net.URL getHost method, like this:

String host = getCodeBase().getHost();

Once you have the right host name, you can use all the networking code that is documented in the Custom Networking trail.

Note: Not all browsers support all networking code flawlessly. For example, one widely used browser compatible with Java technology doesn't support posting to a URL.

A Simple Network Client Applet

Here's an example of implementing an applet that's a network client.

Using a Server to Work Around Security Restrictions

Here's an example of implementing a server to get around applet security restrictions.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Threads in Applets: Examples
Next page: A Simple Network Client Applet


A Simple Network Client Applet (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Practical Considerations When Writing Applets
Subsection: Working with a Server-Side Application
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
A Simple Network Client Applet
This section talks about the client to be an applet. Here's the applet source code. The client has been written not only to communicate with the host the applet came from, but also to have a graphical UI, and to have a loop so that it can get as many quotes as you like. You can run the applet by including it in a page with the following HTML code:
<APPLET CODE=QuoteClientApplet.class WIDTH=500 HEIGHT=100>
</APPLET>

Here's a link to a page that contains the above HTML code. By saving this page to a file on your local HTTP server, you can use it to communicate with the server-side application that will be running on the HTTP server. You must also save the compiled form of the applet to the same directory.

Before the applet can get quotes, you need to run the server on the host that the applet came from. You then need to note the number of the port that the server is listening on. After you enter this port number into the applet, it will hook up with the server and you'll be able to get one-line quotations. Below are detailed instructions, followed by pictures of the server and the applet in action.

  1. Compile QuoteServer.java and QuoteServerThread.java. Here's a text file ( one-liners.txt) that should be in the same directory as the resulting class files.
  2. On the computer that serves the applet class file (through HTTP), invoke the interpreter on the QuoteServer class. For example, if you view the applet's page with the URL http://mymachine/quoteApplet.html, then you need to run the server on the host named mymachine.
  3. Record the port number that the quote server displays.
  4. Enter this number into the applet's text field.
  5. Press the Send button to request a quote from the server. You should see a quote appear in the text area.
Here's a picture of the applet in action:

QuoteServer sample output

QuoteServer sample output

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Working with a Server-Side Application
Next page: Using a Server to Work Around Security Restrictions


Using a Server to Work Around Security Restrictions (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Practical Considerations When Writing Applets
Subsection: Working with a Server-Side Application
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Using a Server to Work Around Security Restrictions
As the What Applets Can and Can't Do section explains, applets are subject to many security restrictions. For example, they can't perform file I/O, they can't make network connections except to their original host, and they can't start programs.

One way of working around these restrictions is to use a server application that executes on the applet's host. The server won't be able to get around every applet restriction, but it can make more things possible. For example, a server probably can't save files on the host the applet's running on, but it'll be able to save files on the host the applet originated from.

This page features an example of a server that allows two applets to communicate with each other. The applets don't have to be running on the same page, in the same browser, or on the same computer. As long as the applets originate from the same computer, they can communicate through the server that's running on that originating computer. The example uses sockets, which are documented in All About Sockets.

Here are the source files:

TalkClientApplet.java
The source file for the client applet. After you compile it, you can run it by including it in an HTML page with this tag:
<APPLET CODE=TalkClientApplet.class WIDTH=550 HEIGHT=200>
</applet>

Here's a link to a page that includes the above HTML code. After saving this page to a file on your local HTTP server, you can use it to communicate with the talk server

TalkServer.java and TalkServerThread.java
The source files for the server applet. After compiling both files, you can run the server on the applets' originating host by invoking the interpreter on the TalkServer class.

The instructions for running the server are just like those for the previous example. Run the server on the applets' originating host, recording the port number the applets should rendezvous on. Then initialize both applets (which can be running on different machines) to talk to the server port number. After this initialization is complete, type a string into each applet's text field. Then press the Return key to send the message to the other applet.

Here's the server in action:

www% java TalkServer
TalkServer listening on rendezvous port: 36567
Here are pictures of the applets in action:

Sample talk output

Sample talk output

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: A Simple Network Client Applet
Next page: Finishing an Applet


Finishing an Applet (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Finishing an Applet

Before You Ship that Applet

Don't release your applet without making sure it follows the simple rules on this page.

The Perfectly Finished Applet

This page lists a few more things that a perfectly finished applet should do.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using a Server to Work Around Security Restrictions
Next page: Before You Ship that Applet


Before You Ship that Applet (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Finishing an Applet
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Before You Ship that Applet
Stop! Before you let the whole world know about your applet, make sure the answer to all of the following questions is yes.

  1. Have you removed or disabled debugging output?

    Debugging output (generally created with System.out.println), while useful to you, is generally confusing or annoying to users. If you need to give textual feedback to the user, try to do it inside the applet's display area or in the status area at the bottom of the window. Information on using the status area is in Displaying Short Status Strings.

  2. Does the applet stop running when it's offscreen?

    Most applets should not use CPU resources when the browser is iconified or is displaying a page that doesn't contain the applet. If your applet code doesn't launch any threads explicitly, then you're OK.

    If your applet code launches any threads, then unless you have a really good excuse not to, you should implement the stop method so that it stops and destroys (by setting to null) the threads you launched. For an example of implementing the stop method, see Threads in Applets: Examples.

  3. If the applet does something that might get annoying — play sounds or animation, for example — does it give the user a way of stopping the annoying behavior?

    Be kind to your users. Give them a way to stop the applet in its tracks, without leaving the page. In an applet that otherwise doesn't respond to mouse clicks, you can do this by implementing the mouseDown method so that a mouse click suspends or resumes the annoying thread. For example:
    boolean frozen = false; //an instance variable

public boolean mouseDown(Event e, int x, int y) {
    if (frozen) {
        frozen = false;
        start();
    } else {
        frozen = true;
        stop();
    }
    return true;
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Finishing an Applet
Next page: The Perfectly Finished Applet


The Perfectly Finished Applet (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Finishing an Applet
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
The Perfectly Finished Applet
The previous page lists some of the ways you can avoid making your applet's users want to throttle you. This page tells you about some other ways that you can make dealing with your applet as pleasant as possible.
Make your applet as flexible as possible.
You can often define parameters that let your applet be used in a variety of situations without any rewriting. See Defining and Using Applet Parameters for more information.
Make your applet accessible.
You can design your applet so that it is accessible to all. See How to Support Assistive Technologies for more information.
Implement the getParameterInfo method.
Implementing this method now might make your applet easier to customize in the future. Currently, no browsers use this method. Soon, however, we expect browsers to use this method to help generate a GUI that allows the user to interactively set parameter values. See Giving Information about Parameters for information on implementing getParameterInfo.
Implement the getAppletInfo method.
This method returns a short, informative string describing an applet. Although no browsers currently use this method, we expect them to in the future. Here's an example of implementing getAppletInfo:
public String getAppletInfo() {
    return "GetApplets by Kathy Walrath";
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Before You Ship that Applet
Next page: Deploying Applets


Deploying Applets (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Deploying Applets

This section explains to HTML authors how and when to use the applet, object, and embed tags to add Java applets to Web pages, and provides guidelines for deploying applets on the Internet and Intranets, and for use with different browsers.

General Deployment Considerations

This section discusses deploying applets for different browsers and on the Internet vs. an Intranet.

Using the applet Tag

You use the applet tag to deploy applets to a multi-browser environment.

Using the object Tag

You use the object tag to deploy applets that are to be used only with Internet Explorer.

Using the embed Tag

You use the embed tag to deploy applets that are to be used only with the Mozilla family of browsers.

Deploying Applets in a Mixed-Browser Environment

This section explains how to use HTML or JavaScript to deploy applets in a mixed-browser environment.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Perfectly Finished Applet
Next page: General Deployment Considerations


General Deployment Considerations (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Deploying Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
General Deployment Considerations

How you deploy an applet depends on whether users access the Web page through the Internet or an Intranet, and the type of browser they use. Note this information about your users, then follow the general guidelines below.

Deploying Applets on the Internet Versus an Intranet

When deploying applets:
  • Use the applet tag if the Web page is accessed through the Internet, or if it is accessed through an Intranet in which people use different browsers.
  • Use the object or embed tag if the Web page is accessed through an Intranet and you know which browser people use..

Deploying Applets for Specific Browsers

When deploying applets:
  • For Internet Explorer only, use the object tag.
  • For the Mozilla family of browsers only, use the embed tag.
If you must deploy an applet in a mixed-browser environment, follow the guidelines in the section Deploying Applets in a Mixed-Browser Environment.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Deploying Applets
Next page: Using the applet Tag


Using the applet Tag (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Deploying Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Using the applet Tag

You use the applet tag to deploy applets to a multi-browser environment.

For complete details on the applet tag, read the W3 HTML specification.

Note: The HTML specification states that the applet tag is deprecated, and that you should use the object tag instead. However, the specification is vague about how browsers should implement the object tag to support Java applets, and browser support is currently inconsistent. It is therefore recommended that you continue to use the applet tag as a consistent way to deploy Java applets across browsers on all platforms.

Following is an example of the applet tag:

    <applet code=Applet1.class width="200" height="200">
    Your browser does not support the applet tag.
    </applet>

For both Internet Explorer and the Mozilla family of browsers, if Java Plug-in is installed (version 1.3.1_01a or later) then the latest installed version of Java Plug-in is invoked to run the applet.

Note: You cannot use the applet tag to automatically download a JRE if one is not installed locally.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: General Deployment Considerations
Next page: Using the object Tag


Using the object Tag (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Deploying Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Using the object Tag

You use the object tag to deploy applets that are to be used only with Internet Explorer.

For complete details on the object tag, read the W3 HTML specification.

Following is an example of the object tag:

<OBJECT
  classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
  width="200" height="200">
  <PARAM name="code" value="Applet1.class">
</OBJECT>

The classid Attribute

The classid attribute identifies which version of Java Plug-in to use.

The example shown below is the most commonly used form of the classid attribute. This example instructs Internet Explorer to use the latest installed version of Java Plug-in.

classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"

Following is an alternative form of the classid attribute:

classid="clsid:CAFEEFAC-xxxx-yyyy-zzzz-ABCDEFFEDCBA"

In this form, "xxxx", "yyyy", and "zzzz" are four-digit numbers that identify the specific version of Java Plug-in to be used.

For example, to use Java Plug-in version 1.6.0, you specify:

classid="clsid:CAFEEFAC-0016-0000-0000-ABCDEFFEDCBA"

The codebase Attribute

You use the optional codebase attribute to specify the location to download JRE from in case it is not installed on the system.

The codebase attribute has two forms:

  • codebase=<URL>

    With this form, if the JRE specified by the classid attribute is not installed locally, then the user is prompted to download the JRE from the URL specified.

  • codebase=<URL>#Version=major,minor,micro,update

    With this form, Java Plug-in compares the classid of the locally installed JRE with the required version of JRE, and if the required version is higher, prompts the user to download and install the newer version of the JRE.

Following is an example of how to use the codebase attribute to set up automatic downloads from the Sun Java Web site:

<object
  classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"
  width="200" height="200"
  codebase="http://java.sun.com/update/1.6.0/
           jinstall-6-windows-i586.cab#Version=6,0,0,99">
  <param name="code" value="Applet1.class">
</object>
Note: In this example the codebase=http://java.sun.com ... line is broken for readability. In the actual HTML file it would be one long line.

Sun has packaged each version of the JRE installer in Microsoft cabinet (.cab) file format. You can view a list of these releases and the corresponding .cab file names.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using the applet Tag
Next page: Using the embed Tag


Using the embed Tag (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Deploying Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Using the embed Tag

You use the embed tag to deploy applets that are to be used only with the Mozilla family of browsers.

Following is an example of the embed tag:

<embed code="Applet1.class"
  width="200" height="200"
  type="application/x-java-applet;version=1.6.0"
  pluginspage="http://java.sun.com/javase/downloads"/>

The type attribute can have one of two forms:

  • type="application/x-java-applet;version=1.6.0"

    With this form, the highest installed JRE that supports the MIME type

    application/x-java-applet;version=1.6.0 is invoked to run the applet. If a JRE with a version number equal to or greater than the version number specified is installed locally, then that JRE is invoked. Otherwise the user is directed to the URL specified as the value of the pluginspage attribute and prompted to download and install the required JRE.

  • type="application/x-java-applet;jpi-version=1.6.0_01

    With this form, a JRE with the exact version given by the the value of jpi-version (in this example, 1.6.0_01) is invoked to run the applet. Otherwise the user is directed to the URL specified as the value of the pluginspage attribute and prompted to download and install the required JRE.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using the object Tag
Next page: Deploying Applets in a Mixed-Browser Environment


Deploying Applets in a Mixed-Browser Environment (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Section: Deploying Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Deploying Applets in a Mixed-Browser Environment

You can deploy applets for users of both Internet Explorer and the Mozilla family of browsers in one of two ways:

  • Through pure HTML
  • Through JavaScript

Using Pure HTML

When using a pure HTML approach to deploy applets in a mixed-browser environment, note the following:

  • Internet Explorer
    • Recognizes the object tag
    • Ignores the contents of the comment tag
  • Mozilla browsers
    • Ignore an object tag with the classid attribute
    • Interpret the contents of the comment tag

Consider the following example code from an HTML page:

<object
  classid="clsid:CAFEEFAC-0016-0000-0000-ABCDEFFEDCBA"
  <param name="code" value="Applet1.class">
    <comment>
      <embed code="Applet1.class"
        type="application/x-java-applet;jpi-version=1.6">
        <noembed>
          No Java Support.
        </noembed>
      </embed>
    </comment>
  </object>

Using JavaScript

Instead of using the pure HTML approach described above, you can use JavaScript to deploy applets in a mixed-browser environment.

Through JavaScript, you:

  1. Detect the user's browser through the appName variable.
  2. Use the document.write() method to write a tag based on the value of the appName variable:
    1. If the browser name equals "Netscape", write the embed tag.
    2. If the browser name equals "Microsoft Internet Explorer", write the object tag.

In the following example, the document.write() method outputs either an embed or object tag for each user “on the fly”:

<html>
<script language="Javascript">

  var _app = navigator.appName;

  if (_app == 'Netscape') {
    document.write('<embed code="Applet1.class"',
                   'width="200"',
                   'height="200"',
                   'type="application/x-java-applet;version=1.6">');
    }
  else if (_app == 'Microsoft Internet Explorer') {
    document.write('<OBJECT ',
                   'classid="clsid:8AD9C840-044E-11D1-B3E9-00805F499D93"',
                   'width="200"',
                   'height="200">',
                   '<PARAM name="code" value="Applet1.class">',
                   '</OBJECT>');
    }
  else {
    document.write('<p>Sorry, unsupported browser.</p>');
    }

</script>
</html>

You can use the HTML Converter tool to help with generating object and embed tags for mixed environments.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using the embed Tag
Next page: Solving Common Applet Problems


Solving Common Applet Problems (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Solving Common Applet Problems
This section covers some common problems that you might encounter when writing Java applets. After each problem there is a list of possible solutions.

Problem: Applet Viewer says there is no <APPLET> tag on my HTML page, but it really is there.

  • Check whether you have a closing applet tag: </APPLET>.
Problem: I recompiled my applet, but my applet viewing application would not show the new version, even though I told it to reload it.
  • In many applet viewers (including browsers), reloading is not reliable. This is why we recommend that you simply use the JDK Applet Viewer, invoking it anew every time you change the applet.
  • If you get an old version of the applet, no matter what you do, make sure that you don't have an old copy of the applet in a directory in your CLASSPATH. See Managing Source and Class Files for information about the CLASSPATH environment variable.
Problem: The background color of my applet causes the applet not to match or flicker, when it is drawn on a page of a different color.
  • You need to set the background color of the applet so that it works well with the page color. See Creating a GUI for details.
Problem: The Applet getImage method doesn't work.
  • Make sure you're calling getImage from the init method or a method that's called after init. The getImage method does not work when it is called from a constructor.
Problem: Now that I have copied my applet's class file onto my HTTP server, the applet doesn't work.
  • Does your applet define more than one class? If so, make sure that the class file (ClassName.class) for each class is on the HTTP server. Even if all the classes are defined in one source file, the compiler produces one class file per class.
  • Did you copy all the data files for your applet — image and sound files, for example — to the server?
  • Make sure all the applet's class and data files can be read by everyone.
  • Make sure the applet's class and data files weren't garbled during the transfer. One common source of trouble is using the ASCII mode of FTP (rather than the BINARY mode) to transfer files.
Problem: I can't get my applet to run. The browser displays a ClassCastException.
  • If your applet has multiple classes, did you specify the right one (an Applet subclass) in the applet tag's CODE attribute?
Problem: Applet is not loaded in my webpage. I see the error "java.lang.UnsupportedClassVersionError: Bad version number in .class file" in my Java Console.
  • The problem is that the source for the applet is compiled with a newer version of Java than the one installed on your system. Which JRE version are you using? If it is not the latest version, make sure you install the latest Java(TM) SE Runtime Environment (JRE).

    Tip for deployers: You can compile your applets with JDK 6 using compile time options as source -1.2 and target -1.2, so that you can run them with the older versions of JRE.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Deploying Applets in a Mixed-Browser Environment
Next page: Questions and Exercises: Java Applets


Questions and Exercises: Java Applets (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises
Home Page > Deployment > Applets
« Previous • Trail • Next »
Questions and Exercises: Java Applets

Questions

  1. Which classes can an applet extend?

  2. How do you cause the applet GUI in the browser to be refreshed when data in it may have changed?

  3. For what do you use the start() method?

  4. True or false: An applet can make network connections to any host on the Internet.

  5. How do you get the value of a parameter specified in the APPLET tag from within the applet's code?

  6. True or false: An applet can run multiple threads.

  7. Match the following tag names with the descriptions in the following lists:
    1. EMBED tag
    2. APPLET tag
    3. OBJECT tag

    1. Use to deploy applets to a multi-browser environment.
    2. Use to deploy applets that are to be used only with the Mozilla family of browsers
    3. Use to deploy applets that are to be used only with Internet Explorer

Exercises

  1. For an applet using the Exercise class, write the Applet tag that sets the ButtonName parameter to Save.

  2. Write the method to display an applet in the browser, so that the contents are contained in a rectangle around the phrase "Exercise Applet". Have the applet be one pixel less than the size specified on the web page, and the phrase starting at the coordinates 5, 15.
Check your answers.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Solving Common Applet Problems
Next page: End of Trail


Trail: Graphical User Interfaces (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Graphical User Interfaces
How do you write a program in the Java programming language with a graphical user interface? The short answer — the Swing toolkit! This trail gives you a brief overview of the graphical capabilities of the core Java platform with a special focus on Swing.

This trail, part of The Java Tutorial, does not show how to implement these features. For a "how-to" on using the Swing toolkit, see Creating a GUI with JFC/Swing.

A Brief Introduction to Swing provides a high-level table of the capabilities provided by the Swing toolkit and other Java Foundation Classes. A demo is provided that showcases many of these capabilities.

Swing Features explains the basic features of Swing, such as drag and drop, internationalization, pluggable look and feel, and provides a visual list of the components available in the Swing toolkit.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: A Brief Introduction to the Swing Package


Lesson: A Brief Introduction to the Swing Package (The Java™ Tutorials > Graphical User Interfaces)

A Brief Introduction to the Swing Package
What is Swing?
A Swing Demo
Trail: Graphical User Interfaces
Home Page > Graphical User Interfaces
« Previous • Trail • Next »
Lesson: A Brief Introduction to the Swing Package
This lesson gives you a brief introduction to the capabilities of the Java SE platform that pertain to developing programs with graphical user interfaces (GUIs). Next, it shows you a demo (sample code provided) that showcases many of these features.

The next lesson, Swing Features discusses these capabilities in more detail.

What is Swing?

The Swing toolkit, shipped as part of the Java SE platform, provides a rich set of GUI components. But Swing offers much more functionality than a collection of standard widgets. This section takes a look at Swing's rich functionality.

A Swing Demo

A rich multi-class Swing application, PasswordStore, is presented. The source code is provided as a reference to the user.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: What is Swing?


What is Swing? (The Java™ Tutorials > Graphical User Interfaces > A Brief Introduction to the Swing Package)

Trail: Graphical User Interfaces
Lesson: A Brief Introduction to the Swing Package
A Brief Introduction to the Swing Package
What is Swing?
A Swing Demo
Home Page > Graphical User Interfaces > A Brief Introduction to the Swing Package
« Previous • Trail • Next »
What is Swing?
To create a Java program with a graphical user interface (GUI), you'll want to learn about Swing.

The Swing toolkit includes a rich set of components for building GUIs and adding interactivity to Java applications. Swing includes all the components you would expect from a modern toolkit: table controls, list controls, tree controls, buttons, and labels.

Swing is far from a simple component toolkit, however. It includes rich undo support, a highly customizable text package, integrated internationalization and accessibility support. To truly leverage the cross-platform capabilities of the Java platform, Swing supports numerous look and feels, including the ability to create your own look and feel. The ability to create a custom look and feel is made easier with Synth, a look and feel specifically designed to be customized. Swing wouldn't be a component toolkit without the basic user interface primitives such as drag and drop, event handling, customizable painting, and window management.

Swing is part of the Java Foundation Classes (JFC). The JFC also include other features important to a GUI program, such as the ability to add rich graphics functionality and the ability to create a program that can work in different languages and by users with different input devices.

The following list shows some of the features that Swing and the Java Foundation Classes provide.

Swing GUI Components
The Swing toolkit includes a rich array of components: from basic components, such as buttons and check boxes, to rich and complex components, such as tables and text. Even deceptively simple components, such as text fields, offer sophisticated functionality, such as formatted text input or password field behavior. There are file browsers and dialogs to suit most needs, and if not, customization is possible. If none of Swing's provided components are exactly what you need, you can leverage the basic Swing component functionality to create your own.
Java 2D API
To make your application stand out; convey information visually; or add figures, images, or animation to your GUI, you'll want to use the Java 2DTM API. Because Swing is built on the 2D package, it's trivial to make use of 2D within Swing components. Adding images, drop shadows, compositing — it's easy with Java 2D.
Pluggable Look-and-Feel Support
Any program that uses Swing components has a choice of look and feel. The JFC classes shipped by Sun and Apple provide a look and feel that matches that of the platform. The Synth package allows you to create your own look and feel. The GTK+ look and feel makes hundreds of existing look and feels available to Swing programs.

A program can specify the look and feel of the platform it is running on, or it can specify to always use the Java look and feel, and without recompiling, it will just work. Or, you can ignore the issue and let the UI manager sort it out.

Data Transfer
Data transfer, via cut, copy, paste, and drag and drop, is essential to almost any application. Support for data transfer is built into Swing and works between Swing components within an application, between Java applications, and between Java and native applications.
Internationalization
This feature allows developers to build applications that can interact with users worldwide in their own languages and cultural conventions. Applications can be created that accept input in languages that use thousands of different characters, such as Japanese, Chinese, or Korean.

Swing's layout managers make it easy to honor a particular orientation required by the UI. For example, the UI will appear right to left in a locale where the text flows right to left. This support is automatic: You need only code the UI once and then it will work for left to right and right to left, as well as honor the appropriate size of components that change as you localize the text.

Accessibility API
People with disabilities use special software — assistive technologies — that mediates the user experience for them. Such software needs to obtain a wealth of information about the running application in order to represent it in alternate media: for a screen reader to read the screen with synthetic speech or render it via a Braille display, for a screen magnifier to track the caret and keyboard focus, for on-screen keyboards to present dynamic keyboards of the menu choices and toolbar items and dialog controls, and for voice control systems to know what the user can control with his or her voice. The accessibility API enables these assistive technologies to get the information they need, and to programmatically manipulate the elements that make up the graphical user interface.
Undo Framework API
Swing's undo framework allows developers to provide support for undo and redo. Undo support is built in to Swing's text component. For other components, Swing supports an unlimited number of actions to undo and redo, and is easily adapted to an application. For example, you could easily enable undo to add and remove elements from a table.
Flexible Deployment Support
If you want your program to run within a browser window, you can create it as an applet and run it using Java Plug-in, which supports a variety of browsers, such as Internet Explorer, Firefox, and Safari. If you want to create a program that can be launched from a browser, you can do this with Java Web Start. Of course, your application can also run outside of browser as a standard desktop application.

For more information on deploying an application, see the Deployment trail in this tutorial.

This trail provides an overview of Swing capabilities, beginning with a demo that showcases many of these features. When you are ready to begin coding, the Creating a GUI with JFC/Swing trail provides the programming techniques to take advantage of these features.

Next, a demo shows many of these features.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: A Brief Introduction to the Swing Package
Next page: A Swing Demo


A Swing Demo (The Java™ Tutorials > Graphical User Interfaces > A Brief Introduction to the Swing Package)

Trail: Graphical User Interfaces
Lesson: A Brief Introduction to the Swing Package
A Brief Introduction to the Swing Package
What is Swing?
A Swing Demo
Home Page > Graphical User Interfaces > A Brief Introduction to the Swing Package
« Previous • Trail • Next »
A Swing Demo
Here is an example of an application, PasswordStore, that illustrates some of Swing's rich feature set. PasswordStore allows the user to manage login information for various hosts. It also generates passwords, evaluates the effectiveness of a password, and allows you to store notes about a particular host or assign an icon to represent the host.

Click the launch button to run PasswordStore using Java Web Start. [Requires release 6.0.]

Launches the PasswordStore application

The following highlights some of the specific features of the PasswordStore application:

Host Info
At program launch, the list of hosts is displayed in a Swing list component. Using the View menu, the view can be toggled between the table and the list.

In both views, the Host/Account Filter text field can be used to dynamically restrict the entries to those where the host or account name contains the typed string.

List View
The Swing list component can be customized to include visual data. As shown in the following figure, an optional miniature icon to the left of the host name represents the host. The graphic to the right uses color and proportional fill to reflect the strength of the password (Red = poor, yellow = fair, green = good). The bar changes dynamically as the user enters/modifies the password in the text field below. The user has typed the text "oo" in the filter text field, which matches two entries: Heirloom Seeds and Pacific Zoo Shop.

This is a picture of the PasswordStore demo.

Host Info (List View) and Filter Text Field

Table View
The Swing table component allows the user to rearrange the columns by dragging the column header. Also, a column can be sorted by clicking the column header. If the column you click on isn't highlighted as the primary sorted column, it will become the primary sorted column in ascending order. Clicking on the primary sorted column toggles the sort order. For example, if column 1 isn't selected, clicking on it will make it the selected column and the data is sorted in ascending order. Clicking column 1 again will sort the data in descending order. Clicking on column 2 will make column 2 the primary column in ascending order.

This is a picture of the PasswordStore demo in the table view.

Host Info (Table View)

Details/Notes Tabbed Pane
The tabbed pane below the host info allows the user to choose between the Details panel and the Notes text pane, keeping the overall footprint of the window smaller and less overwhelming.
Details Panel
The icon area on the left can be assigned an image by either dragging an image (jpg, png, gif, or tif) to the area or by clicking the image well and bringing up a file browser.

The text fields (used to enter or modify the host name, login, and password) support cut/copy, paste, drag, drop, undo, and redo.

As the user enters or modifies the password, the 2D bar chart dynamically displays the distribution of the password. If the list view is currently displayed, the corresponding colored bar in the list also changes dynamically.

Notes Text Pane
This is the text component where the user can save notes about the selected host. If the text pane contains a URI, Swing's text component provides the ability to click on the URI and a browser window automatically opens to that location.
Wizzy 2D Graphics
PasswordStore uses customized graphics in several ways to enhance the UI: In the list view, images are used to represent each host; a colored bar, the Strength Visualizer, represents the effectiveness of a password; and a dynamic bar chart, the Password Visualizer, displays the distribution of a password. When you add an image, whether by dragging and dropping it into the image well (in the Details panel) or by clicking the well and bringing up the file browser, a mini-icon is automatically generated for the list view.
Note: This demo is meant to be illustrative only and not meant to be used for real analysis of passwords.

This picture of PasswordStore shows the whizzy graphics used.

2D Graphics Used

Multiple Look and Feels
This provides the ability to switch between three look and feels using the View menu: Java (called Metal), Motif/CDE, and the native look and feel: Windows on Microsoft Windows, Aqua on Mac OS X, and so on.
Undo and Redo
Undo and redo works on text, as you would expect, but it also works on actions. For example, you can generate a password using the Account > Generate Password menu, and if you don't like the new password you can undo it using Edit > Undo or the control-Z shortcut. Similarly, you can redo the undo using Edit > Redo, or the control-Y shortcut.

The PasswordStore demo has a reasonable level of complexity for a small Swing application and shows a sampling of Swing's capabilities. The source code is available for download, but it is outside the scope of this chapter to discuss the implementation in detail. For more information on the architecture and implementation of this application, see Scott Violet's Excellent Blog on java.net.

NOTE: If PasswordStore were a production application, it would most likely encrypt the password database; however, due to legal restrictions on distributing information of that nature, it is not included here.

NOTE: The dice, flower, pill, and pocketwatch images used in the demo are courtesy of http://www.freeimages.co.uk. The polar bear and cubs image by Steve Amstrup and the mountain image are courtesy of http://www.fws.gov. The spiral galaxy image is courtesy of http://grin.hq.nasa.gov.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: What is Swing?
Next page: Swing Features


Lesson: Swing Features (The Java™ Tutorials > Graphical User Interfaces)

Swing Features
A Visual Guide to Swing Components (Java Look and Feel)
A Visual Guide to Swing Components (Windows Look and Feel)
Pluggable Look and Feel
Data Transfer
Internationalization and Localization
Accessibility
Integrating with the Desktop
System Tray Icon Support
Questions and Exercises
Trail: Graphical User Interfaces
Home Page > Graphical User Interfaces
« Previous • Trail • Next »
Lesson: Swing Features
PasswordStore shows some of the rich functionality of a particular Swing application. This lesson discusses the general features available to applications using the Java SE platform and, in particular, the Swing toolkit.

A Visual Guide to Swing Components (Java Look and Feel)

Swing is primarily known for its rich set of GUI components. This section provides a visual menu of Swing's components, grouped by type, using the Java look and feel.

A Visual Guide to Swing Components (Windows Look and Feel)

This page shows the same components, using the Windows look and feel.

Pluggable Look and Feel

The pluggable look and feel architecture allows a program to have control over its appearance. This section describes what options are available to the programmer.

Data Transfer

Most programs will want to use drag and drop or cut, copy and paste. This section talks a bit about data transfer and what is implemented for you.

Internationalization and Localization

Internationalizing an application makes it easy to tailor it to the customs and languages of end users around the world. This section describes the difference between internationalization and localization.

Accessibility

Making your program accessible means that it can be used, without modification, by anyone with permanent or temporary disabilities who may require special devices. And, in many countries, making programs accessible is the law.

Integrating with the Desktop

An application that is well integrated with the desktop will, where appropriate, allow the user to launch the default mail application or internet browser, pre-populating text fields as needed. It will also allow the user to launch another application to open, edit or print a file associated with that application.

System Tray Icon Support

Some platforms, such as Microsoft Windows, feature a system tray on the desktop. As of version 6 of the Java SE, your application can now add a tray icon to the system tray.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: A Visual Guide to Swing Components (Java Look and Feel)


A Visual Guide to Swing Components (Java Look and Feel) (The Java™ Tutorials > Graphical User Interfaces > Swing Features)

Trail: Graphical User Interfaces
Lesson: Swing Features
Swing Features
A Visual Guide to Swing Components (Java Look and Feel)
A Visual Guide to Swing Components (Windows Look and Feel)
Pluggable Look and Feel
Data Transfer
Internationalization and Localization
Accessibility
Integrating with the Desktop
System Tray Icon Support
Questions and Exercises
Home Page > Graphical User Interfaces > Swing Features
« Previous • Trail • Next »
A Visual Guide to Swing Components (Java Look and Feel)
This page shows Swing components in the Java look and feel. The following page shows the same components in the Windows look and feel.

Basic Controls
Simple components that are used primarily to get input from the user;
they may also show simple state.
JButton | JCheckBox | Combo box image JComboBox | JList
JMenu | Radio Button image JRadioButton | JSlider
JSpinner | Text field image JTextField |  | Password field image JPasswordField

Interactive Displays of Highly Formatted Information
These components display highly formatted information that
(if you choose) can be modified by the user.
Color Chooser Image JColorChooser | Text pane Image JEditorPane and JTextPane
File Chooser Image JFileChooser
JTable | JTextArea | JTree

Uneditable Information Displays
These components exist solely to give the user information.

JLabel

Progress bar image

JProgressBar

JSeparator

Tool tip image

JToolTip

Top-Level Containers
At least one of these components must be present in any Swing application.

JApplet

JDialog

JFrame

General-Purpose Containers
These general-purpose containers are used in most Swing applications.
JPanel | Scroll pane image JScrollPane
Split pane image JSplitPane | Tabbed pane image JTabbedPane
JToolBar |

Special-Purpose Containers
These special-purpose containers play specific roles in the UI.
Internal frame image JInternalFrame | Layered pane image JLayeredPane
Root pane image Root pane

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Swing Features
Next page: A Visual Guide to Swing Components (Windows Look and Feel)


A Visual Guide to Swing Components (Windows Look and Feel) (The Java™ Tutorials > Graphical User Interfaces > Swing Features)

Trail: Graphical User Interfaces
Lesson: Swing Features
Swing Features
A Visual Guide to Swing Components (Java Look and Feel)
A Visual Guide to Swing Components (Windows Look and Feel)
Pluggable Look and Feel
Data Transfer
Internationalization and Localization
Accessibility
Integrating with the Desktop
System Tray Icon Support
Questions and Exercises
Home Page > Graphical User Interfaces > Swing Features
« Previous • Trail • Next »
A Visual Guide to Swing Components (Windows Look and Feel)
This page shows Swing components in the Windows look and feel. The previous page shows the same components in the Java look and feel.

Basic Controls
Simple components that are used primarily to get input from the user;
they may also show simple state.
JButton | JCheckBox | Combo box image JComboBox | JList
JMenu | Radio Button image JRadioButton | JSlider
JSpinner | Text field image JTextField |  | Password field image JPasswordField

Interactive Displays of Highly Formatted Information
These components display highly formatted information that
(if you choose) can be modified by the user.
Color Chooser Image JColorChooser | Text pane Image JEditorPane and JTextPane
File Chooser Image JFileChooser
JTable | JTextArea | JTree

Uneditable Information Displays
These components exist solely to give the user information.

JLabel

Progress bar image

JProgressBar

JSeparator

Tool tip image

JToolTip

Top-Level Containers
At least one of these components must be present in any Swing application.

JApplet

JDialog

JFrame

General-Purpose Containers
These general-purpose containers are used in most Swing applications.
JPanel | Scroll pane image JScrollPane
Split pane image JSplitPane | Tabbed pane image JTabbedPane
JToolBar |

Special-Purpose Containers
These special-purpose containers play specific roles in the UI.
Internal frame image JInternalFrame | Layered pane image JLayeredPane
Root pane image Root pane

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: A Visual Guide to Swing Components (Java Look and Feel)
Next page: Pluggable Look and Feel


Pluggable Look and Feel (The Java™ Tutorials > Graphical User Interfaces > Swing Features)

Trail: Graphical User Interfaces
Lesson: Swing Features
Swing Features
A Visual Guide to Swing Components (Java Look and Feel)
A Visual Guide to Swing Components (Windows Look and Feel)
Pluggable Look and Feel
Data Transfer
Internationalization and Localization
Accessibility
Integrating with the Desktop
System Tray Icon Support
Questions and Exercises
Home Page > Graphical User Interfaces > Swing Features
« Previous • Trail • Next »
Pluggable Look and Feel
The Swing toolkit allows you to decide how to configure the particular look and feel of your application. If you don't specify a look and feel, the Swing UI manager figures out which one to use. The options for setting a look and feel include:
  • Leave it up to the Swing UI manager. If a particular look and feel is not specified by the program, Swing's UI manager checks whether the user has specified a preference. If that preference hasn't been specified or isn't available, the default look and feel is used. The default look and feel is determined by the supplier of the JRE. For the JRE that Sun provides, the Java look and feel (called Metal) is used. The Java look and feel works on all platforms.

  • Use the look and feel of the native platform. If the application is running on a Microsoft Windows XP machine, the Windows look and feel is used. On Mac OS platforms, the Aqua look and feel is used. On UNIX platforms, such as Solaris or Linux, either the GTK+ look and feel or the CDE/Motif look and feel is used, depending on the user's desktop choice.

  • Specify a particular look and feel. Swing ships with four look and feels: Java (also called Metal), Microsoft Windows, GTK+, and CDE/Motif. The GTK+ look and feel requires a theme, and there are many available for free on the Internet.

  • Create your own look and feel using the Synth package.

  • Use an externally provided look and feel.

As shown in the following figures, PasswordStore offers a choice of three look and feels. The Alloy and Synthetica look and feels have been provided courtesy of Incors.

This is a picture of the PasswordStore demo in the Java look and feel.

Java look and feel

This is a picture of the PasswordStore demo in the Windows look and feel.

Windows look and feel

This is a picture of the PasswordStore demo in the CDE/Motif look and feel.

CDE/Motif look and feel

This is a picture of the PasswordStore demo in the Alloy default look and feel.

Default Alloy look and feel

This is a picture of the PasswordStore demo in the Synthetica look and feel.

Synthetica look and feel

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: A Visual Guide to Swing Components (Windows Look and Feel)
Next page: Data Transfer


Data Transfer (The Java™ Tutorials > Graphical User Interfaces > Swing Features)

Trail: Graphical User Interfaces
Lesson: Swing Features
Swing Features
A Visual Guide to Swing Components (Java Look and Feel)
A Visual Guide to Swing Components (Windows Look and Feel)
Pluggable Look and Feel
Data Transfer
Internationalization and Localization
Accessibility
Integrating with the Desktop
System Tray Icon Support
Questions and Exercises
Home Page > Graphical User Interfaces > Swing Features
« Previous • Trail • Next »
Data Transfer
The Swing toolkit supports the ability to transfer data between components within the same Java application, between different Java applications, and between Java and native applications. Data can be transferred via a drag and drop gesture, or via the clipboard using cut, copy, and paste.

Drag and Drop

Drag-and-drop support can be easily enabled for many of Swing's components (sometimes with a single line of code). For example, it's trivial to enable drag and drop and copy and paste support for JTable, Swing's table component. All you need to provide is the data representing the selection and how to get your data from the clipboard — that's it!

Cut, Copy, and Paste

Most of the text-based components, such as editor pane and text field, support cut/copy and paste out of the box. Of course, menu items need to be created and "wired up" to the appropriate actions. Other components, such as list and tree, can support cut, copy, and paste with some minimal work.

PasswordStore supports data transfer in a variety of ways:

  • The text in both the list and the table view supports cut, copy, and paste.

  • The text fields in the Details Panel, the Filter text field, and the Notes text pane support cut/copy, paste, and drag and drop.

  • The Company icon region in the Details panel accepts a dropped image (jpg, png, gif, or tif).
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Pluggable Look and Feel
Next page: Internationalization and Localization


Internationalization and Localization (The Java™ Tutorials > Graphical User Interfaces > Swing Features)

Trail: Graphical User Interfaces
Lesson: Swing Features
Swing Features
A Visual Guide to Swing Components (Java Look and Feel)
A Visual Guide to Swing Components (Windows Look and Feel)
Pluggable Look and Feel
Data Transfer
Internationalization and Localization
Accessibility
Integrating with the Desktop
System Tray Icon Support
Questions and Exercises
Home Page > Graphical User Interfaces > Swing Features
« Previous • Trail • Next »
Internationalization and Localization
Internationalization is the process of designing an application so that the user can run it using his or her cultural preferences without modifying or recompiling the code. These cultural preferences, collectively known as locale, include (but aren't limited to): language, currency formatting, time and date formatting, and numeric formatting.

An internationalized program is designed so that text elements, such as status messages and GUI component labels, are stored outside the source code in resource bundles and retrieved dynamically. Separating the locale-specific information from the code is what allows a program to run in different languages and with different preferences without having to recompile.

Localization is the process of translating the text to a particular language and adding any locale-specific components. When an application is localized to a language and you run the app in that locale, Swing grabs the localized strings from the resource bundle and the layout manager resizes the component accordingly.

For example, an English-speaking person writes an application following the rules of internationalization; later, that application is localized to Japanese and Spanish. When a user with the Language System Preference set to Japanese runs the application, Swing detects this. When the application appears, the menus, labels, buttons, and so on, show Japanese text, and the components are scaled accordingly. If that user then quits the program, sets the language system preference to Spanish, and re-launches the application, the application appears in Spanish, scaled according to the new character set.

Swing's layout managers understand how locale affects a UI — it is not necessary to create a new layout for each locale. For example, in a locale where text flows right to left, the layout manager will arrange components in the same orientation, if specified. Bidi text (mixed directional text, used by Hebrew and Arabic, for example) is supported as well.

Every program should be designed with internationalization in mind: GUI component labels, status messages, currency, date, phone, and address formats should not be hardcoded into programs. Once a program has been internationalized, a language expert can perform the actual translation at a later date without requiring any recompiling.

As the following screenshots show, PasswordStore has been localized to Japanese and Arabic.

This is a picture of the PasswordStore demo in Japanese.

PasswordStore in Japanese

This is a picture of the PasswordStore demo in Arabic.

PasswordStore in Arabic

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Data Transfer
Next page: Accessibility


Accessibility (The Java™ Tutorials > Graphical User Interfaces > Swing Features)

Trail: Graphical User Interfaces
Lesson: Swing Features
Swing Features
A Visual Guide to Swing Components (Java Look and Feel)
A Visual Guide to Swing Components (Windows Look and Feel)
Pluggable Look and Feel
Data Transfer
Internationalization and Localization
Accessibility
Integrating with the Desktop
System Tray Icon Support
Questions and Exercises
Home Page > Graphical User Interfaces > Swing Features
« Previous • Trail • Next »
Accessibility
Assistive technologies exist to enable people with permanent or temporary disabilities to use the computer. This includes a wide variety of techniques and equipment — voice interfaces, magnifiers, screen readers, closed captioning, keyboard enhancements, and so on. In many countries, including the United States, Australia, Canada, and the European Union, there are laws requiring that programs function smoothly with assistive technologies. For more information, see Sun Microsystems' Accessibility Program - Relevant Laws.

A certain level of accessibility is built-in to all Swing components, but full accessibility can be achieved by following some simple rules. For example, assign tool tips, keyboard alternatives, and textual descriptions for images, wherever possible.

The PasswordStore demo follows the rules set out for accessibility. In the following figure, you can see an example of tool tip text.

The PasswordStore demo showing a tooltip.

PasswordStore With a Tooltip

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Internationalization and Localization
Next page: Integrating with the Desktop


Integrating with the Desktop (The Java™ Tutorials > Graphical User Interfaces > Swing Features)

Trail: Graphical User Interfaces
Lesson: Swing Features
Swing Features
A Visual Guide to Swing Components (Java Look and Feel)
A Visual Guide to Swing Components (Windows Look and Feel)
Pluggable Look and Feel
Data Transfer
Internationalization and Localization
Accessibility
Integrating with the Desktop
System Tray Icon Support
Questions and Exercises
Home Page > Graphical User Interfaces > Swing Features
« Previous • Trail • Next »
Integrating with the Desktop
The Desktop API, introduced in version 6 of the Java Platform, Standard Edition (Java SE), enables Java applications to integrate seamlessly with the desktop. Three types of integration are supported:
  • The ability to launch the host system's default browser with a specific Uniform Resource Identifier (URI).
  • The ability to launch the host system's default email client.
  • The ability to launch applications to open, edit, or print files associated with those applications.

You can see this in the PasswordStore demo in the Notes text pane. Click on the link that is displayed in the text pane — it opens the specified URI in the default browser.

This is a picture of the PasswordStore demo showing a URI in the text pane.

Click on the URI and it opens in the Default Browser

For more information, see the Using the Desktop API in Java SE 6 (Mustang) article.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Accessibility
Next page: System Tray Icon Support


System Tray Icon Support (The Java™ Tutorials > Graphical User Interfaces > Swing Features)

Trail: Graphical User Interfaces
Lesson: Swing Features
Swing Features
A Visual Guide to Swing Components (Java Look and Feel)
A Visual Guide to Swing Components (Windows Look and Feel)
Pluggable Look and Feel
Data Transfer
Internationalization and Localization
Accessibility
Integrating with the Desktop
System Tray Icon Support
Questions and Exercises
Home Page > Graphical User Interfaces > Swing Features
« Previous • Trail • Next »
System Tray Icon Support
The desktop of some platforms, such as Microsoft Windows, includes a system tray, as shown in the following screenshot:

System Tray on Windows XP

On Microsoft Windows, it is called the "Taskbar Status Area." On Gnome, the "Notification Area", and on KDE, the "System Tray." However it may be called, the system tray is shared by all applications.

On platforms where it is supported, an application may insert a mini-icon, called a Tray Icon, into the system tray. This icon can be used to notify the user of a change in the application's status, or a need to take a particular action. Clicking the tray icon can bring up the application window. A popup menu and a tooltip can also be attached to the tray icon.

System tray support was added in version 6 of Java SE. For more information, see the New System Tray Functionality in Mustang article.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Integrating with the Desktop
Next page: Questions and Exercises: Graphical User Interfaces


Questions and Exercises: Graphical User Interfaces (The Java™ Tutorials > Graphical User Interfaces > Swing Features)

Trail: Graphical User Interfaces
Lesson: Swing Features
Swing Features
A Visual Guide to Swing Components (Java Look and Feel)
A Visual Guide to Swing Components (Windows Look and Feel)
Pluggable Look and Feel
Data Transfer
Internationalization and Localization
Accessibility
Integrating with the Desktop
System Tray Icon Support
Questions and Exercises
Home Page > Graphical User Interfaces > Swing Features
« Previous • Trail • Next »
Questions and Exercises: Graphical User Interfaces

Questions

1. Does Swing support multiple look and feels?

2. True or False: The Java look and feel is the only look and feel that works across all platforms.

3. True or False: Swing's Undo Framework supports an unlimited number of actions to undo (and redo).

4. Can Swing's list component (JList) only display text?

5. Which Swing component provides undo support out of the box?

6. Can Java applications interact with the native desktop? components.

7. Can I deploy my Swing application on the web?

Check your answers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: System Tray Icon Support
Next page: End of Trail


Trail: Creating a GUI with JFC/Swing (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Creating a GUI with JFC/Swing

Also known as The Swing Tutorial

This trail tells you how to create graphical user interfaces (GUIs) for applications and applets, using the Swing components.

Getting Started with Swing is a quick start lesson. First it gives you a bit of background about the JFC and Swing. Then it tells you how to compile and run programs that use Swing components.

Learning Swing with the NetBeans IDE is the fastest and easiest way to begin working with Swing. This lesson explores the NetBeans IDE's GUI builder, a powerful feature that lets you visually construct your Graphical User Interfaces.

Using Swing Components tells you how to use each of the Swing components — buttons, tables, text components, and all the rest. It also tells you how to use borders and icons.

Concurrency in Swing discusses concurrency as it applies to Swing programming. Information on the event dispatch thread and the SwingWorker class are included.

Using Other Swing Features tells you how to use actions, timers, and the system tray; how to integrate with the desktop class, how to support assistive technologies, how to print tables and text, how to create a splash screen, and how to use modality in dialogs.

Laying Out Components Within a Container tells you how to choose a layout manager, how to use each of the layout manager classes the JavaTM platform provides, how to use absolute positioning instead of a layout manager, and how to create your own layout manager.

Modifying the Look and Feel tells you how to specify the look and feel of Swing components.

Drag and Drop and Data Transfer tells you what you need to know to implement data transfer in your application.

Writing Event Listeners tells you how to handle events in your programs.

Performing Custom Painting gives you information on painting your own Swing components. It discusses painting issues specific to Swing components, provides an overview of painting concepts, and has examples of custom components that paint themselves.

Other UI-Related Trails

Although this is the main trail for learning about GUIs, it isn't the only trail with UI-related information.
  • 2D Graphics, which describes the 2D graphics features available in the JDK.
  • Sound, which discusses the sound capabilities available in the JDK.
  • Applets, which describes API available only to applets.
  • Essential Classes, which covers many topics, including properties and the standard I/O streams.
  • The Bonus trail contains Full-Screen Exclusive Mode API, a lesson that describes how to use API introduced in v1.4 to render graphics directly to the screen.
« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Getting Started with Swing


Lesson: Getting Started with Swing (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Getting Started with Swing
About the JFC and Swing
Compiling and Running Swing Programs
Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Lesson: Getting Started with Swing
Examples Index

This lesson gives you a brief introduction to using the Java Foundation Classes (JFC) and Swing. After telling you about JFC and Swing, it helps you get the necessary software and walks you through how to compile and run a program that uses the Swing packages.

The following lesson, Learning Swing with the NetBeans IDE, will build on these first steps to help you create several progressively more complex examples. For now, let's start with the basics.

About the JFC and Swing

This section gives you an overview of the JFC and Swing.

Compiling and Running Swing Programs

This section gives you detailed instructions on where to obtain the latest JDK and how to create, compile and run a program that uses Swing components.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: About the JFC and Swing


About the JFC and Swing (The Java™ Tutorials > Creating a GUI with JFC/Swing > Getting Started with Swing)

Trail: Creating a GUI with JFC/Swing
Lesson: Getting Started with Swing
Getting Started with Swing
About the JFC and Swing
Compiling and Running Swing Programs
Home Page > Creating a GUI with JFC/Swing > Getting Started with Swing
« Previous • Trail • Next »
About the JFC and Swing
JFC is short for Java Foundation Classes, which encompass a group of features for building graphical user interfaces (GUIs) and adding rich graphics functionality and interactivity to Java applications. It is defined as containing the features shown in the table below.

Features of the Java Foundation Classes
Feature Description

Swing GUI Components

Includes everything from buttons to split panes to tables. Many components are capable of sorting, printing, and drag and drop, to name a few of the supported features.

Pluggable Look-and-Feel Support

The look and feel of Swing applications is pluggable, allowing a choice of look and feel. For example, the same program can use either the Java or the Windows look and feel. Additionally, the Java platform supports the GTK+ look and feel, which makes hundreds of existing look and feels available to Swing programs. Many more look-and-feel packages are available from various sources.

Accessibility API

Enables assistive technologies, such as screen readers and Braille displays, to get information from the user interface.

Java 2D API

Enables developers to easily incorporate high-quality 2D graphics, text, and images in applications and applets. Java 2D includes extensive APIs for generating and sending high-quality output to printing devices.

Internationalization

Allows developers to build applications that can interact with users worldwide in their own languages and cultural conventions. With the input method framework developers can build applications that accept text in languages that use thousands of different characters, such as Japanese, Chinese, or Korean.

This trail concentrates on the Swing components. We help you choose the appropriate components for your GUI, tell you how to use them, and give you the background information you need to use them effectively. We also discuss other JFC features as they apply to Swing components.

Which Swing Packages Should I Use?

The Swing API is powerful, flexible — and immense. The Swing API has 18 public packages:

javax.accessibility

javax.swing.plaf

javax.swing.text

javax.swing

javax.swing.plaf.basic

javax.swing.text.html

javax.swing.border

javax.swing.plaf.metal

javax.swing.text.html.parser

javax.swing.colorchooser

javax.swing.plaf.multi

javax.swing.text.rtf

javax.swing.event

javax.swing.plaf.synth

javax.swing.tree

javax.swing.filechooser

javax.swing.table

javax.swing.undo

Fortunately, most programs use only a small subset of the API. This trail sorts out the API for you, giving you examples of common code and pointing you to methods and classes you're likely to need. Most of the code in this trail uses only one or two Swing packages:
  • javax.swing
  • javax.swing.event (not always required)
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Getting Started with Swing
Next page: Compiling and Running Swing Programs


Compiling and Running Swing Programs (The Java™ Tutorials > Creating a GUI with JFC/Swing > Getting Started with Swing)

Trail: Creating a GUI with JFC/Swing
Lesson: Getting Started with Swing
Getting Started with Swing
About the JFC and Swing
Compiling and Running Swing Programs
Home Page > Creating a GUI with JFC/Swing > Getting Started with Swing
« Previous • Trail • Next »
Compiling and Running Swing Programs
This section explains how to compile and run a Swing application from the command line. For information on compiling and running a Swing application using NetBeans IDE, see Running Tutorial Examples in NetBeans IDE. The compilation instructions work for all Swing programs — applets, as well as applications. Here are the steps you need to follow:
  • Install the latest release of the Java SE platform, if you haven't already done so.
  • Create a program that uses Swing components.
  • Compile the program.
  • Run the program.

Install the Latest Release of the Java SE Platform

You can download the latest release of the JDK for free from http://java.sun.com/javase/downloads.

Create a Program That Uses Swing Components

You can use a simple program we provide, called HelloWorldSwing, that brings up the GUI shown in the figure below. The program is in a single file, HelloWorldSwing.java. When you save this file, you must match the spelling and capitalization of its name exactly.

Compile the Program

Your next step is to compile the program. Here's an example of compiling HelloWorldSwing.java:
javac HelloWorldSwing.java
If you can't compile, make sure you're using the compiler in a recent release of the Java platform. Once you've updated your JDK, you should be able to use the programs in this trail without changes. Another common mistake is installing the Java Runtime Environment (JRE) and not the full Java Development Kit (JDK) needed to compile these programs. Refer to the Getting Started trail to help you solve any compiling problems you encounter. Another resource is the Troubleshooting Guide for Java™ SE 6 Desktop Technologies.

Run the Program

After you compile the program successfully, you can run it. For example:
java HelloWorldSwing
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: About the JFC and Swing
Next page: Learning Swing with the NetBeans IDE


Lesson: Learning Swing with the NetBeans IDE (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Learning Swing with the NetBeans IDE
Setting up the CelsiusConverter Project
NetBeans IDE Basics
Creating the CelsiusConverter GUI
Adjusting the CelsiusConverter GUI
Adding the Application Logic
Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Lesson: Learning Swing with the NetBeans IDE
Examples Index

This lesson provides an introduction to Graphical User Interface (GUI) programming with Swing and the NetBeans IDE. As you learned in the "Hello World!" lesson, the NetBeans IDE is a free, open-source, cross-platform integrated development environment with built-in support for the Java programming language. It offers many advantages over coding with a text editor; we recommend its use whenever possible. If you have not yet read the above lesson, please take a moment to do so now. It provides valuable information about downloading and installing the JDK and NetBeans IDE.

The goal of this lesson is to introduce the Swing API by designing a simple application that converts temperature from Celsius to Fahrenheit. Its GUI will be basic, focusing on only a subset of the available Swing components. We will use the NetBeans IDE GUI builder, which makes user interface creation a simple matter of drag and drop. Its automatic code generation feature simplifies the GUI development process, letting you focus on the application logic instead of the underlying infrastructure.

Because this lesson is a step-by-step checklist of specific actions to take, we recommend that you run the NetBeans IDE and perform each step as you read along. This will be the quickest and easiest way to begin programming with Swing. If you are unable to do so, simply reading along should still be useful, since each step is illustrated with screenshots.

If you prefer the traditional approach of programming each component manually (without the assistance of an IDE), think of this lesson as an entry point into the lower-level discussions already provided elsewhere in the tutorial. Hyperlinks in each discussion will take you to related lessons, should you wish to learn such lower-level details.

The finished GUI for this application will look as follows:

Figure showing the completed CelsiusConverter application.

The CelsiusConverter Application.

Click the Launch button to run CelsiusConverter using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.
Launches the CelsiusConverter example

From an end-user's perspective, usage is simple: enter a temperature (in Celsius) into the text box, click the "Convert" button, and watch the converted temperature (in Fahrenheit) appear on screen. The minimize, maximize, and close buttons will behave as expected, and the application will also have a title that appears along the top of the window.

From a programmer's perspective, we will write the application in two main stages. First, we will populate the GUI with the various Swing components and arrange them as shown above. Then, we will add the application logic, so that the program actually performs a conversion when the user presses the "Convert" button.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Setting up the CelsiusConverter Project


Setting up the CelsiusConverter Project (The Java™ Tutorials > Creating a GUI with JFC/Swing > Learning Swing with the NetBeans IDE)

Trail: Creating a GUI with JFC/Swing
Lesson: Learning Swing with the NetBeans IDE
Learning Swing with the NetBeans IDE
Setting up the CelsiusConverter Project
NetBeans IDE Basics
Creating the CelsiusConverter GUI
Adjusting the CelsiusConverter GUI
Adding the Application Logic
Home Page > Creating a GUI with JFC/Swing > Learning Swing with the NetBeans IDE
« Previous • Trail • Next »
Setting up the CelsiusConverter Project
If you have worked with the NetBeans IDE in the past, much of this section will look familiar, since the initial steps are similar for most projects. Still, the following steps describe settings that are specific to this application, so take care to follow them closely.

Step 1: Create a New Project

To create a new project, launch the NetBeans IDE and choose New Project from the File menu:

Creating a New Project within the GUI

Creating a New Project

Keyboard shortcuts for each command appear on the far right of each menu item. The look and feel of the NetBeans IDE may vary across platforms, but the functionality will remain the same.

Step 2: Choose General -> Java Application

Next, select General from the Categories column, and Java Application from the Projects column:

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

You may notice mention of "J2SE" in the description pane; that is the old name for what is now known as the "Java SE" platform. Press the button labeled "Next" to proceed.

Step 3: Set a Project Name

Now enter "CelsiusConverterProject" as the project name. You can leave the Project Location and Project Folder fields set to their default values, or click the Browse button to choose an alternate location on your system.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Make sure to deselect the "Create Main Class" checkbox; leaving this option selected generates a new class as the main entry point for the application, but our main GUI window (created in the next step) will serve that purpose, so checking this box is not necessary. Click the "Finish" button when you are done.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

When the IDE finishes loading, you will see a screen similar to the above. All panes will be empty except for the Projects pane in the upper left hand corner, which shows the newly created project.

Step 4: Add a JFrame Form

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Now right-click the CelsiusConverterProject name and choose New -> JFrame Form (JFrame is the Swing class responsible for the main frame for your application.) You will learn how to designate this class as the application's entry point later in this lesson.

Step 5: Name the GUI Class

Next, type CelsiusConverterGUI as the class name, and learn as the package name. You can actually name this package anything you want, but here we are following the tutorial convention of naming the package after the lesson in which is resides.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

The remainder of the fields should automatically be filled in, as shown above. Click the Finish button when you are done.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

When the IDE finishes loading, the right pane will display a design-time, graphical view of the CelsiusConverterGUI. It is on this screen that you will visually drag, drop, and manipulate the various Swing components.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Learning Swing with the NetBeans IDE
Next page: NetBeans IDE Basics


NetBeans IDE Basics (The Java™ Tutorials > Creating a GUI with JFC/Swing > Learning Swing with the NetBeans IDE)

Trail: Creating a GUI with JFC/Swing
Lesson: Learning Swing with the NetBeans IDE
Learning Swing with the NetBeans IDE
Setting up the CelsiusConverter Project
NetBeans IDE Basics
Creating the CelsiusConverter GUI
Adjusting the CelsiusConverter GUI
Adding the Application Logic
Home Page > Creating a GUI with JFC/Swing > Learning Swing with the NetBeans IDE
« Previous • Trail • Next »
NetBeans IDE Basics
It is not necessary to learn every feature of the NetBeans IDE before exploring its GUI creation capabilities. In fact, the only features that you really need to understand are the Palette, the Design Area, the Property Editor, and the Inspector. We will discuss these features below.

The Palette

The Palette contains all of the components offered by the Swing API. You can probably already guess what many of these components are for, even if this is your first time using them (JLabel is a text label, JList is a drop-down list, etc.)

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

From this list, our application will use only JLabel (a basic text label), JTextField (for the user to enter the temperature), and JButton (to convert the temperature from Celsius to Fahrenheit.)

The Design Area

The Design Area is where you will visually construct your GUI. It has two views: source view, and design view. Design view is the default, as shown below. You can toggle between views at any time by clicking their respective tabs.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

The figure above shows a single JFrame object, as represented by the large shaded rectangle with blue border. Commonly expected behavior (such as quitting when the user clicks the "close" button) is auto-generated by the IDE and appears in the source view between uneditable blue sections of code known as guarded blocks.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

A quick look at the source view reveals that the IDE has created a private method named initComponents, which initializes the various components of the GUI. It also tells the application to "exit on close", performs some layout-specific tasks, then packs the (soon to be added) components together on screen.

Don't feel that you need to understand this code in any detail; we mention it here simply to explore the source tab. For more information about these components, see:

How to Make Frames (Main Windows) and Laying Out Components Within a Container.

The Property Editor

The Property Editor does what its name implies: it allows you to edit the properties of each component. The Property Editor is intuitive to use; in it you will see a series of rows — one row per property — that you can click and edit without entering the source code directly. The following figure shows the Property Editor for the newly added JFrame object:

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

The screenshot above shows the various properties of this object, such as background color, foreground color, font, and cursor.

The Inspector

The last component of the NetBeans IDE that we will use in this lesson is the Inspector:

The Inspector

The Inspector provides a graphical representation of your application's components. We will use the Inspector only once, to change a few variable names to something other than their defaults.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Setting up the CelsiusConverter Project
Next page: Creating the CelsiusConverter GUI


Creating the CelsiusConverter GUI (The Java™ Tutorials > Creating a GUI with JFC/Swing > Learning Swing with the NetBeans IDE)

Trail: Creating a GUI with JFC/Swing
Lesson: Learning Swing with the NetBeans IDE
Learning Swing with the NetBeans IDE
Setting up the CelsiusConverter Project
NetBeans IDE Basics
Creating the CelsiusConverter GUI
Adjusting the CelsiusConverter GUI
Adding the Application Logic
Home Page > Creating a GUI with JFC/Swing > Learning Swing with the NetBeans IDE
« Previous • Trail • Next »
Creating the CelsiusConverter GUI

This section explains how to use the NetBeans IDE to create the application's GUI. As you drag each component from the Palette to the Design Area, the IDE will auto-generate the appropriate source code.

Step 1: Set the Title

First, set the title of the application's JFrame to "Celsius Converter", by single-clicking the JFrame in the Inspector:

Selecting the JFrame

Selecting the JFrame

Then, set its title with the Property Editor:

Setting the Title

Setting the Title

You can set the title by either double-clicking the title property and entering the new text directly, or by clicking the [image] button and entering the title in the provided field. Or, as a shortcut, you could single-click the JFrame of the inspector and enter its new text directly without using the property editor.

Step 2: Add a JTextField

Next, drag a JTextField from the Palette to the upper left corner of the Design Area. As you approach the upper left corner, the GUI builder will will provide visual cues (dashed lines) that suggest the appropriate spacing. Using these cues as a guide, drop a JTextField into the upper left hand corner of the window as shown below:

Adding a JTextField

Adding a JTextField

You may be tempted to erase the default text "JTextField1", but just leave it in place for now. We will replace it later in this lesson as we make the final adjustments to each component. For more information about this component, see How to Use Text Fields.

Step 3: Add a JLabel

Next, drag a JLabel onto the Design Area. Place it to the right of the JTextField, again watching for visual cues that suggest an appropriate amount of spacing. Make sure that text base for this component is aligned with that of the JTextField. The visual cues provided by the IDE should make this easy to determine.

Adding a JLabel

Adding a JLabel

For more information about this component, see How to Use Labels.

Step 4: Add a JButton

Next, drag a JButton from the Palette and position it to the left and underneath the JTextField. Again, the visual cues will help guide it into place.

Adding a JButton

Adding a JButton

You may be tempted to manually adjust the width of the JButton and JTextField, but just leave them as they are for now. You will learn how to correctly adjust these components later in this lesson. For more information about this component, see How to Use Buttons.

Step 5: Add a Second JLabel

Adding a Second JLabel

Adding a Second JLabel

Finally, add a second JLabel, repeating the process in step 2. Place this second label to the right of the JButton, as shown above.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: NetBeans IDE Basics
Next page: Adjusting the CelsiusConverter GUI


Adjusting the CelsiusConverter GUI (The Java™ Tutorials > Creating a GUI with JFC/Swing > Learning Swing with the NetBeans IDE)

Trail: Creating a GUI with JFC/Swing
Lesson: Learning Swing with the NetBeans IDE
Learning Swing with the NetBeans IDE
Setting up the CelsiusConverter Project
NetBeans IDE Basics
Creating the CelsiusConverter GUI
Adjusting the CelsiusConverter GUI
Adding the Application Logic
Home Page > Creating a GUI with JFC/Swing > Learning Swing with the NetBeans IDE
« Previous • Trail • Next »
Adjusting the CelsiusConverter GUI
With the GUI components now in place, it is time to make the final adjustments. There are a few different ways to do this; the order suggested here is just one possible approach.

Step 1: Set the Component Text

First, double-click the JTextField and JButton to change the default text that was inserted by the IDE. When you erase the text from the JTextField, it will shrink in size as shown below. Change the text of the JButton from "JButton1" to "Convert." Also change the top JLabel text to "Celsius" and the bottom to "Fahrenheit."

Setting the Component Text

Setting the Component Text

Step 2: Set the Component Size

Next, shift-click the JTextField and JButton components. This will highlight each showing that they are selected. Right-click (control-click for mac users) Same Size -> Same Width. The components will now be the same width, as shown below. When you perform this step, make sure that JFrame itself is not also selected. If it is, the Same Size menu will not be active.

Setting the JTextField and JButton Sizes

Setting the JTextField and JButton Sizes

Step 3: Remove Extra Space

Finally, grab the lower right-hand corner of the JFrame and adjust its size to eliminate any extra whitespace. Note that if you eliminate all of the extra space (as shown below) the title (which only appears at runtime) may not show completely. The end-user is free to resize the application as desired, but you may want to leave some extra space on the right side to make sure that everything fits correctly. Experiment, and use the screenshot of the finished GUI as a guide.

The Completed GUI

The Completed GUI

The GUI portion of this application is now complete! If the NetBeans IDE has done its job, you should feel that creating this GUI was a simple, if not trivial, task. But take a minute to click on the source tab; you might be surprised at the amount of code that has been generated.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

To see the code in its entirety, scroll up and down within the IDE as necessary. You can expand or collapse certain blocks of code (such as method bodies) by clicking the + or - symbol on the left-hand side of the source editor.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating the CelsiusConverter GUI
Next page: Adding the Application Logic


Adding the Application Logic (The Java™ Tutorials > Creating a GUI with JFC/Swing > Learning Swing with the NetBeans IDE)

Trail: Creating a GUI with JFC/Swing
Lesson: Learning Swing with the NetBeans IDE
Learning Swing with the NetBeans IDE
Setting up the CelsiusConverter Project
NetBeans IDE Basics
Creating the CelsiusConverter GUI
Adjusting the CelsiusConverter GUI
Adding the Application Logic
Home Page > Creating a GUI with JFC/Swing > Learning Swing with the NetBeans IDE
« Previous • Trail • Next »
Adding the Application Logic
It is now time to add in the application logic.

Step 1: Change the Default Variable Names

The figure below shows the default variable names as they currently appear within the Inspector. For each component, the variable name appears first, followed by the object's type in square brackets. For example, jTextField1 [JTextField] means that "jTextField1" is the variable name and "JTextField" is its type.

Default Variable Names

Default Variable Names

The default names are not very relevant in the context of this application, so it makes sense to change them from their defaults to something that is more meaningful. Right-click each variable name and choose "Change variable name." When you are finished, the variable names should appear as follows:

New Variable Names

New Variable Names

The new variable names are "tempTextField", "celsiusLabel", "convertButton", and "fahrenheitLabel." Each change that you make in the Inspector will automatically propagate its way back into the source code. You can rest assured that compilation will not fail due to typos or mistakes of that nature — mistakes that are common when editing by hand.

Step 2: Register the Event Listeners

When an end-user interacts with a Swing GUI component (such as clicking the Convert button), that component will generate a special kind of object — called an event object — which it will then broadcast to any other objects that have previously registered themselves as listeners for that event. The NetBeans IDE makes event listener registration extremely simple:

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

In the Design Area, click on the Convert button to select it. Make sure that only the Convert button is selected (if the JFrame itself is also selected, this step will not work.) Right-click the Convert button and choose Events -> Action -> ActionPerformed. This will generate the required event-handling code, leaving you with empty method bodies in which to add your own functionality:

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

There are many different event types representing the various kinds of actions that an end-user can take (clicking the mouse triggers one type of event, typing at the keyboard triggers another, moving the mouse yet another, and so on.) Our application is only concerned with the ActionEvent; for more information about event handling, see Writing Event Listeners.

Step 3: Add the Temperature Conversion Code

The final step is to simply paste the temperature conversion code into the empty method body. The following code is all that is necessary to convert a temperature from Celsius to Fahrenheit:
    //Parse degrees Celsius as a double and convert to Fahrenheit.
    int tempFahr = (int)((Double.parseDouble(tempTextField.getText()))
            * 1.8 + 32);
    fahrenheitLabel.setText(tempFahr + " Fahrenheit");
Simply copy this code and paste it into the convertButtonActionPerformed method as shown below:

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

With the conversion code in place, the application is now complete.

Step 4: Run the Application

Running the application is simply a matter of choosing Run -> Run Main Project within the NetBeans IDE. The first time you run this application, you will be prompted with a dialog asking to set CelsiusConverterGUI as the main class for this project. Click the OK button, and when the program finishes compiling, you should see the application running in its own window.

Congratulations! You have completed your first Swing application!

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Adjusting the CelsiusConverter GUI
Next page: Questions and Exercises: Learning Swing with the NetBeans IDE


Questions and Exercises: Learning Swing with the NetBeans IDE (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Questions and Exercises: Learning Swing with the NetBeans IDE

Questions

  1. When creating this new project, we left the "Create Main Class" checkbox deselected. Why?

  2. The _____ contains all of the components offered by the Swing API.

  3. What is the purpose of the Design Area?

  4. Explain the difference between the Source and Design tabs.

  5. Name some advantages to editing an object with the Property Editor (as opposed to editing it directly in the source code.)

  6. This lesson used Swing objects of three different types. What were they?

  7. Describe the process for setting two components to the same width in the Design Area.

Exercises

  1. Use the property editor to change the appearance of this application. Experiment by changing some values and seeing what effect your changes have.

Check your answers

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Adding the Application Logic
Next page: Using Swing Components


Lesson: Using Swing Components (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Lesson: Using Swing Components
Examples Index

This lesson gives you the background information you need to use the Swing components, and then describes every Swing component. It assumes that you have successfully compiled and run a program that uses Swing components, and that you are familiar with basic Swing concepts. These prerequisites are covered in Getting Started with Swing and Learning Swing with the NetBeans IDE.

A Visual Index to the Swing Components (Java Look and Feel)
A Visual Index to the Swing Components (Windows Look and Feel)

Before you get started, you may want to check out these pages (from the Graphical User Interfaces lesson in the Core trail) which have pictures of all the standard Swing components, from top-level containers to scroll panes to buttons. To find the section that discusses a particular component, just click the component's picture.

Using Top-Level Containers

Discusses how to use the features shared by the JFrame, JDialog, and JApplet classes — content panes, menu bars, and root panes. It also discusses the containment hierarchy, which refers to the tree of components contained by a top-level container.

The JComponent Class

Tells you about the features JComponent provides to its subclasses — which include almost all Swing components — and gives tips on how to take advantage of these features. This section ends with API tables describing the commonly used API defined by JComponent and its superclasses, Container and Component.

Using Text Components

Describes the features and API shared by all components that descend from JTextComponent. You probably do not need to read this section if you are just using text fields (formatted or not) or text areas.

How to...

Sections on how to use each Swing component, in alphabetical order. We do not expect you to read these sections in order. Instead, we recommend reading the relevant "How to" sections once you are ready to start using Swing components in your own programs. For example, if your program needs a frame, a label, a button, and a color chooser, you should read How to Make Frames, How to Use Labels, How to Use Buttons, and How to Use Color Choosers.

Using HTML in Swing Components

Describes how to vary the font, color, or other formatting of text displayed by Swing components by using HTML tags.

Using Models

Tells you about the Swing model architecture. This variation on Model-View-Controller (MVC) means that you can, if you wish, specify how the data and state of a Swing component are stored and retrieved. The benefits are the ability to share data and state between components, and to greatly improve the performance of components such as tables that display large amounts of data.

Using Borders

Borders are very handy for drawing lines, titles, and empty space around the edges of components. (You might have noticed that the examples in this trail use a lot of borders.) This section tells you how to add a border to any JComponent.

Using Icons

Many Swing components can display icons. Usually, icons are implemented as instances of the ImageIcon class.

Solving Common Component Problems

This section discusses solutions to common component-related problems.

Questions and Exercises

Try these questions and exercises to test what you have learned in this lesson.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Using Top-Level Containers


Using Top-Level Containers (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
Using Top-Level Containers
As we mentioned before, Swing provides three generally useful top-level container classes: JFrame, JDialog, and JApplet. When using these classes, you should keep these facts in mind:
  • To appear onscreen, every GUI component must be part of a containment hierarchy. A containment hierarchy is a tree of components that has a top-level container as its root. We'll show you one in a bit.

  • Each GUI component can be contained only once. If a component is already in a container and you try to add it to another container, the component will be removed from the first container and then added to the second.

  • Each top-level container has a content pane that, generally speaking, contains (directly or indirectly) the visible components in that top-level container's GUI.

  • You can optionally add a menu bar to a top-level container. The menu bar is by convention positioned within the top-level container, but outside the content pane. Some look and feels, such as the Mac OS look and feel, give you the option of placing the menu bar in another place more appropriate for the look and feel, such as at the top of the screen.
Note: Although JInternalFrame mimics JFrame, internal frames aren't actually top-level containers.
Here's a picture of a frame created by an application. The frame contains a green menu bar (with no menus) and, in the frame's content pane, a large blank, yellow label.

A simple application with a frame that contains a menu bar and a content pane.

A diagram of the frame's major parts

You can find the entire source for this example in TopLevelDemo.java. Although the example uses a JFrame in a standalone application, the same concepts apply to JApplets and JDialogs.

Here's the containment hierarchy for this example's GUI:

Containment hierarchy for the TopLeveDemo example's GUI.

As the ellipses imply, we left some details out of this diagram. We reveal the missing details a bit later. Here are the topics this section discusses:

  • Top-Level Containers and Containment Hierarchies
  • Adding Components to the Content Pane
  • Adding a Menu Bar
  • The Root Pane (a.k.a. The Missing Details)

Top-Level Containers and Containment Hierarchies
Each program that uses Swing components has at least one top-level container. This top-level container is the root of a containment hierarchy — the hierarchy that contains all of the Swing components that appear inside the top-level container.

As a rule, a standalone application with a Swing-based GUI has at least one containment hierarchy with a JFrame as its root. For example, if an application has one main window and two dialogs, then the application has three containment hierarchies, and thus three top-level containers. One containment hierarchy has a JFrame as its root, and each of the other two has a JDialog object as its root.

A Swing-based applet has at least one containment hierarchy, exactly one of which is rooted by a JApplet object. For example, an applet that brings up a dialog has two containment hierarchies. The components in the browser window are in a containment hierarchy rooted by a JApplet object. The dialog has a containment hierarchy rooted by a JDialog object.

Adding Components to the Content Pane
Here's the code that the preceding example uses to get a frame's content pane and add the yellow label to it:
frame.getContentPane().add(yellowLabel, BorderLayout.CENTER);
As the code shows, you find the content pane of a top-level container by calling the getContentPane method. The default content pane is a simple intermediate container that inherits from JComponent, and that uses a BorderLayout as its layout manager.

It's easy to customize the content pane — setting the layout manager or adding a border, for example. However, there is one tiny gotcha. The getContentPane method returns a Container object, not a JComponent object. This means that if you want to take advantage of the content pane's JComponent features, you need to either typecast the return value or create your own component to be the content pane. Our examples generally take the second approach, since it's a little cleaner. Another approach we sometimes take is to simply add a customized component to the content pane, covering the content pane completely.

Note that the default layout manager for JPanel is FlowLayout; you'll probably want to change it.

To make a component the content pane, use the top-level container's setContentPane method. For example:

//Create a panel and add components to it.
JPanel contentPane = new JPanel(new BorderLayout());
contentPane.setBorder(someBorder);
contentPane.add(someComponent, BorderLayout.CENTER);
contentPane.add(anotherComponent, BorderLayout.PAGE_END);

topLevelContainer.setContentPane(contentPane);
Note: As a convenience, the add method and its variants, remove and setLayout have been overridden to forward to the contentPane as necessary. This means you can write
frame.add(child);
and the child will be added to the contentPane.

Note that only these three methods do this. This means that getLayout() will not return the layout set with setLayout().

Adding a Menu Bar
In theory, all top-level containers can hold a menu bar. In practice, however, menu bars usually appear only in frames and applets. To add a menu bar to a top-level container, create a JMenuBar object, populate it with menus, and then call setJMenuBar. The TopLevelDemo adds a menu bar to its frame with this code:
frame.setJMenuBar(greenMenuBar);
For more information about implementing menus and menu bars, see How to Use Menus.

The Root Pane
Each top-level container relies on a reclusive intermediate container called the root pane. The root pane manages the content pane and the menu bar, along with a couple of other containers. You generally don't need to know about root panes to use Swing components. However, if you ever need to intercept mouse clicks or paint over multiple components, you should get acquainted with root panes.

Here's a list of the components that a root pane provides to a frame (and to every other top-level container):

A root pane manages four other panes: a layered pane, a menu bar, a content pane, and a glass pane.

We've already told you about the content pane and the optional menu bar. The two other components that a root pane adds are a layered pane and a glass pane. The layered pane contains the menu bar and content pane, and enables Z-ordering of other components. The glass pane is often used to intercept input events occuring over the top-level container, and can also be used to paint over multiple components.

For more details, see How to Use Root Panes.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Swing Components
Next page: The JComponent Class


The JComponent Class (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
The JComponent Class
With the exception of top-level containers, all Swing components whose names begin with "J" descend from the JComponent class. For example, JPanel, JScrollPane, JButton, and JTable all inherit from JComponent. However, JFrame and JDialog don't because they implement top-level containers.

The JComponent class extends the Container class, which itself extends Component. The Component class includes everything from providing layout hints to supporting painting and events. The Container class has support for adding components to the container and laying them out. This section's API tables summarize the most often used methods of Component and Container, as well as of JComponent.

JComponent Features

The JComponent class provides the following functionality to its descendants:
  • Tool tips
  • Painting and borders
  • Application-wide pluggable look and feel
  • Custom properties
  • Support for layout
  • Support for accessibility
  • Support for drag and drop
  • Double buffering
  • Key bindings
Tool tips
By specifying a string with the setToolTipText method, you can provide help to users of a component. When the cursor pauses over the component, the specified string is displayed in a small window that appears near the component. See How to Use Tool Tips for more information.

Painting and borders
The setBorder method allows you to specify the border that a component displays around its edges. To paint the inside of a component, override the paintComponent method. See How to Use Borders and Performing Custom Painting for details.

Application-wide pluggable look and feel
Behind the scenes, each JComponent object has a corresponding ComponentUI object that performs all the drawing, event handling, size determination, and so on for that JComponent. Exactly which ComponentUI object is used depends on the current look and feel, which you can set using the UIManager.setLookAndFeel method. See How to Set the Look and Feel for details.

Custom properties
You can associate one or more properties (name/object pairs) with any JComponent. For example, a layout manager might use properties to associate a constraints object with each JComponent it manages. You put and get properties using the putClientProperty and getClientProperty methods. For general information about properties, see Properties.

Support for layout
Although the Component class provides layout hint methods such as getPreferredSize and getAlignmentX, it doesn't provide any way to set these layout hints, short of creating a subclass and overriding the methods. To give you another way to set layout hints, the JComponent class adds setter methods — setMinimumSize, setMaximumSize, setAlignmentX, and setAlignmentY. See Laying Out Components Within a Container for more information.

Support for accessibility
The JComponent class provides API and basic functionality to help assistive technologies such as screen readers get information from Swing components, For more information about accessibility, see How to Support Assistive Technologies.

Support for drag and drop
The JComponent class provides API to set a component's transfer handler, which is the basis for Swing's drag and drop support. See Introduction to DnD for details.

Double buffering
Double buffering smooths on-screen painting. For details, see Performing Custom Painting.

Key bindings
This feature makes components react when the user presses a key on the keyboard. For example, in many look and feels when a button has the focus, typing the Space key is equivalent to a mouse click on the button. The look and feel automatically sets up the bindings between pressing and releasing the Space key and the resulting effects on the button. For more information about key bindings, see How to Use Key Bindings.

The JComponent API

The JComponent class provides many new methods and inherits many methods from Component and Container. The following tables summarize the methods we use the most.
  • Customizing Component Appearance
  • Setting and Getting Component State
  • Handling Events
  • Painting Components
  • Dealing with the Containment Hierarchy
  • Laying Out Components
  • Getting Size and Position Information
  • Specifying Absolute Size and Position

Customizing Component Appearance
Method Purpose
void setBorder(Border)
Border getBorder() 		Set or get the border of the component. See How to Use Borders for details.
void setForeground(Color)
void setBackground(Color) 		Set the foreground or background color for the component. The foreground is generally the color used to draw the text in a component. The background is (not surprisingly) the color of the background areas of the component, assuming that the component is opaque.
Color getForeground()
Color getBackground() 		Get the foreground or background color for the component.
void setOpaque(boolean)
boolean isOpaque() 		Set or get whether the component is opaque. An opaque component fills its background with its background color.
void setFont(Font)
Font getFont() 		Set or get the component's font. If a font has not been set for the component, the font of its parent is returned.
void setCursor(Cursor)
Cursor getCursor() 		Set or get the cursor displayed over the component and all components it contains (except for children that have their own cursor set). Example: aPanel.setCursor( Cursor.getPredefinedCursor( Cursor.WAIT_CURSOR));

Setting and Getting Component State
Method | Purpose
void setComponentPopupMenu(JPopupMenu) Sets the JPopupMenu for this JComponent. The UI is responsible for registering bindings and adding the necessary listeners such that the JPopupMenu will be shown at the appropriate time. When the JPopupMenu is shown depends upon the look and feel: some may show it on a mouse event, some may enable a key binding.

If popup is null, and getInheritsPopupMenu returns true, then getComponentPopupMenu will be delegated to the parent. This provides for a way to make all child components inherit the popupmenu of the parent.
void setTransferHandler(TransferHandler)
TransferHandler getTransferHandler() 		Set or remove the transferHandler property. The TransferHandler supports exchanging data via cut, copy, or paste to/from a clipboard as well a drag and drop. See Introduction to DnD for more details.
void setToolTipText(String) | Set the text to display in a tool tip. See How to Use Tool Tips for more information.
void setName(String)
String getName() 		Set or get the name of the component. This can be useful when you need to associate text with a component that does not display text.
boolean isShowing() | Determine whether the component is showing on screen. This means that the component must be visible, and it must be in a container that is visible and showing.
void setEnabled(boolean)
boolean isEnabled() 		Set or get whether the component is enabled. An enabled component can respond to user input and generate events.
void setVisible(boolean)
boolean isVisible() 		Set or get whether the component is visible. Components are initially visible, with the exception of top-level components.

Handling Events
(see Writing Event Listeners for details)
Method Purpose
void addHierarchyListener(hierarchyListener l)
void removeHierarchyListener(hierarchyListener l)
Adds or removes the specified hierarchy listener to receive hierarchy changed events from this component when the hierarchy to which this container belongs changes. If listener l is null, no exception is thrown and no action is performed.
void addMouseListener(MouseListener)
void removeMouseListener(MouseListener) 		Add or remove a mouse listener to or from the component. Mouse listeners are notified when the user uses the mouse to interact with the listened-to component.
void addMouseMotionListener(MouseMotionListener)
void removeMouseMotionListener(MouseMotionListener) 		Add or remove a mouse motion listener to or from the component. Mouse motion listeners are notified when the user moves the mouse within the listened-to component's bounds.
void addKeyListener(KeyListener)
void removeKeyListener(KeyListener) 		Add or remove a key listener to or from the component. Key listeners are notified when the user types at the keyboard and the listened-to component has the keyboard focus.
void addComponentListener(ComponentListener)
void removeComponentListener(ComponentListener) 		Add or remove a component listener to or from the component. Component listeners are notified when the listened-to component is hidden, shown, moved, or resized.
boolean contains(int, int)
boolean contains(Point) 		Determine whether the specified point is within the component. The argument should be specified in terms of the component's coordinate system. The two int arguments specify x and y coordinates, respectively.
Component getComponentAt(int, int)
Component getComponentAt(Point) 		Return the component that contains the specified x, y position. The top-most child component is returned in the case where components overlap. This is determined by finding the component closest to the index 0 that claims to contain the given point via Component.contains().
Component setComponentZOrder(component comp, int index)
 Moves the specified component to the specified z-order index in the container.

If the component is a child of some other container, it is removed from that container before being added to this container. The important difference between this method and java.awt.Container.add(Component, int) is that this method doesn't call removeNotify on the component while removing it from its previous container unless necessary and when allowed by the underlying native windowing system. This way, if the component has the keyboard focus, it maintains the focus when moved to the new position.

Note: The z-order determines the order that components are painted. The component with the highest z-order paints first and the component with the lowest z-order paints last. Where components overlap, the component with the lower z-order paints over the component with the higher z-order.

Component getComponentZOrder(component comp) 		Returns the z-order index of the component inside the container. The higher a component is in the z-order hierarchy, the lower its index. The component with the lowest z-order index is painted last, above all other child components.

Painting Components
(see Performing Custom Painting for details)
Method | Purpose
void repaint()
void repaint(int, int, int, int) 		Request that all or part of the component be repainted. The four int arguments specify the bounds (x, y, width, height, in that order) of the rectangle to be painted.
void repaint(Rectangle) | Request that the specified area within the component be repainted.
void revalidate() | Request that the component and its affected containers be laid out again. You should not generally need to invoke this method unless you explicitly change a component's size/alignment hints after it's visible or change a containment hierarchy after it is visible. Always invoke repaint after revalidate.
void paintComponent(Graphics) | Paint the component. Override this method to implement painting for custom components.

Dealing with the Containment Hierarchy
(see Using Top-Level Containers for more information)
Method | Purpose
Component add(Component)
Component add(Component, int)
void add(Component, Object) 		Add the specified component to this container. The one-argument version of this method adds the component to the end of the container. When present, the int argument indicates the new component's position within the container. When present, the Object argument provides layout constraints to the current layout manager.
void remove(int)
void remove(Component)
void removeAll() 		Remove one of or all of the components from this container. When present, the int argument indicates the position within the container of the component to remove.
JRootPane getRootPane() | Get the root pane that contains the component.
Container getTopLevelAncestor() | Get the topmost container for the component — a Window, Applet, or null if the component has not been added to any container.
Container getParent() | Get the component's immediate container.
int getComponentCount() | Get the number of components in this container.
Component getComponent(int)
Component[] getComponents() 		Get the one of or all of the components in this container. The int argument indicates the position of the component to get.
Component getComponentZOrder(int)
Component[] getComponentZOrder() 		Returns the z-order index of the component inside the container. The higher a component is in the z-order hierarchy, the lower its index. The component with the lowest z-order index is painted last, above all other child components.

Laying Out Components
(see Laying Out Components Within a Container for more information)
Method | Purpose
void setPreferredSize(Dimension)
void setMaximumSize(Dimension)
void setMinimumSize(Dimension) 		Set the component's preferred, maximum, or minimum size, measured in pixels. The preferred size indicates the best size for the component. The component should be no larger than its maximum size and no smaller than its minimum size. Be aware that these are hints only and might be ignored by certain layout managers.
Dimension getPreferredSize()
Dimension getMaximumSize()
Dimension getMinimumSize() 		Get the preferred, maximum, or minimum size of the component, measured in pixels. Many JComponent classes have setter and getter methods. For those non-JComponent subclasses, which do not have the corresponding setter methods, you can set a component's preferred, maximum, or minimum size by creating a subclass and overriding these methods.
void setAlignmentX(float)
void setAlignmentY(float) 		Set the alignment along the x- or y- axis. These values indicate how the component would like to be aligned relative to other components. The value should be a number between 0 and 1 where 0 represents alignment along the origin, 1 is aligned the furthest away from the origin, and 0.5 is centered, and so on. Be aware that these are hints only and might be ignored by certain layout managers.
float getAlignmentX()
float getAlignmentY() 		Get the alignment of the component along the x- or y- axis. For non-JComponent subclasses, which do not have the corresponding setter methods, you can set a component's alignment by creating a subclass and overriding these methods.
void setLayout(LayoutManager)
LayoutManager getLayout() 		Set or get the component's layout manager. The layout manager is responsible for sizing and positioning the components within a container.
void applyComponentOrientation(ComponentOrientation) void setComponentOrientation(ComponentOrientation) | Set the ComponentOrientation property of this container and all the components contained within it. See Setting the Container's Orientation for more information.

Getting Size and Position Information
Method | Purpose
int getWidth()
int getHeight() 		Get the current width or height of the component measured in pixels.
Dimension getSize()
Dimension getSize(Dimension) 		Get the component's current size measured in pixels. When using the one-argument version of this method, the caller is responsible for creating the Dimension instance in which the result is returned.
int getX()
int getY() 		Get the current x or y coordinate of the component's origin relative to the parent's upper left corner measured in pixels.
Rectangle getBounds()
Rectangle getBounds(Rectangle) 		Get the bounds of the component measured in pixels. The bounds specify the component's width, height, and origin relative to its parent. When using the one-argument version of this method, the caller is responsible for creating the Rectangle instance in which the result is returned.
Point getLocation()
Point getLocation(Point)
Gets the current location of the component relative to the parent's upper left corner measured in pixels. When using the one-argument version of getLocation method, the caller is responsible for creating the Point instance in which the result is returned.
Point getLocationOnScreen() | Returns the position relative to the upper left corner of the screen.
Insets getInsets() | Get the size of the component's border.

Specifying Absolute Size and Position
(see Doing Without a Layout Manager (Absolute Positioning) for more information)
Method Purpose
void setLocation(int, int)
void setLocation(Point) 		Set the location of the component, in pixels, relative to the parent's upper left corner. The two int arguments specify x and y, in that order. Use these methods to position a component when you are not using a layout manager.
void setSize(int, int)
void setSize(Dimension) 		Set the size of the component measured in pixels. The two int arguments specify width and height, in that order. Use these methods to size a component when you are not using a layout manager.
void setBounds(int, int, int, int)
void setBounds(Rectangle) 		Set the size and location relative to the parent's upper left corner, in pixels, of the component. The four int arguments specify x, y, width, and height, in that order. Use these methods to position and size a component when you are not using a layout manager.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Top-Level Containers
Next page: Using Text Components


Using Text Components (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
Using Text Components
This section provides background information you might need when using Swing text components. If you intend to use an unstyled text component — a text field, password field, formatted text field, or text area — go to its how-to page and return here only if necessary. If you intend to use a styled text component, see How to Use Editor Panes and Text Panes, and read this section as well. If you do not know which component you need, read on.

Swing text components display text and optionally allow the user to edit the text. Programs need text components for tasks ranging from the straightforward (enter a word and press Enter) to the complex (display and edit styled text with embedded images in an Asian language).

Swing provides six text components, along with supporting classes and interfaces that meet even the most complex text requirements. In spite of their different uses and capabilities, all Swing text components inherit from the same superclass, JTextComponent, which provides a highly-configurable and powerful foundation for text manipulation.

The following figure shows the JTextComponent hierarchy.

Swing's hierarchy of text components

The following picture shows an application called TextSamplerDemo that uses each Swing text component.

An application that provides a sample of each Swing text component

Try this:
  1. Click the Launch button to run TextSamplerDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    2. Launches the TextSamplerDemo Application

  2. Type some text in the text field and press Enter. Do the same in the password field. The label beneath the fields is updated when you press Enter.
  3. Try entering valid and invalid dates into the formatted text field. Note that when you press Enter the label beneath the fields is updated only if the date is valid.
  4. Select and edit text in the text area and the text pane. Use keyboard bindings, Ctrl-X, Ctrl-C, and Ctrl-V, to cut, copy, and paste text, respectively.
  5. Try to edit the text in the editor pane, which has been made uneditable with a call to setEditable.
  6. Look in the text pane to find an example of an embedded component and an embedded icon.

The TextSamplerDemo example uses the text components in very basic ways. The following table tells you more about what you can do with each kind of text component.

Group | Description | Swing Classes
Text Controls | Also known simply as text fields, text controls can display only one line of editable text. Like buttons, they generate action events. Use them to get a small amount of textual information from the user and perform an action after the text entry is complete. | JTextField and its subclasses JPasswordField and JFormattedTextField
Plain Text Areas | JTextArea can display multiple lines of editable text. Although a text area can display text in any font, all of the text is in the same font. Use a text area to allow the user to enter unformatted text of any length or to display unformatted help information. | JTextArea
Styled Text Areas A styled text component can display editable text using more than one font. Some styled text components allow embedded images and even embedded components. Styled text components are powerful and multi-faceted components suitable for high-end needs, and offer more avenues for customization than the other text components.

Because they are so powerful and flexible, styled text components typically require more initial programming to set up and use. One exception is that editor panes can be easily loaded with formatted text from a URL, which makes them useful for displaying uneditable help information.

JEditorPane
and its subclass
JTextPane

This Tutorial provides information about the foundation laid by the JTextComponent class and tells you how to accomplish some common text-related tasks. Because the JTextComponent class and its subclasses have too many features to be completely described in this Tutorial, please visit the Swing and AWT forum at java.net for help and information.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The JComponent Class
Next page: Text Component Features


Text Component Features (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: Using Text Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
Text Component Features
The JTextComponent class is the foundation for Swing text components. This class provides the following customizable features for all of its descendants:
  • A model, known as a document, that manages the component's content.
  • A view, which displays the component on screen.
  • A controller, known as an editor kit, that reads and writes text and implements editing capabilities with actions.
  • Support for infinite undo and redo.
  • A pluggable caret and support for caret change listeners and navigation filters.
See the example called TextComponentDemo to explore these capabilities. Although the TextComponentDemo example contains a customized instance of JTextPane, the capabilities discussed in this section are inherited by all JTextComponent subclasses.

A snapshot of TextComponentDemo, which contains a customized text pane and a standard text area

The upper text component is the customized text pane. The lower text component is an instance of JTextArea, which serves as a log that reports all changes made to the contents of the text pane. The status line at the bottom of the window reports either the location of the selection or the position of the caret, depending on whether text is selected.
Try this:
  1. Click the Launch button to run TextComponentDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TextComponentDemo Application

  2. Use the mouse to select text and place the cursor in the text pane. Information about the selection and cursor is displayed at the bottom of the window.
  3. Enter text by typing on the keyboard. You can move the caret around using the arrow keys on the keyboard or the four emacs key bindings: Ctrl-B (backward one character), Ctrl-F (forward one character), Ctrl-N (down one line), and Ctrl-P (up one line).
  4. Open the Edit menu, and use its menu items to edit text in the text pane. Make a selection in the text area at the bottom of the window. Because the text area is not editable, only some of the Edit menu's commands, like copy-to-clipboard, work. It is important to note though, that the menu operates on both text components.
  5. Use the items in the Style menu to apply different styles to the text in the text pane.
Using the TextComponentDemo example as a reference point, this section covers the following topics:
  • Associating Text Actions With Menus and Buttons
  • Associating Text Actions With Key Strokes
  • Implementing Undo and Redo
  • Concepts: About Documents
  • Implementing a Document Filter
  • Listening for Changes on a Document
  • Listening for Caret and Selection Changes
  • Concepts: About Editor Kits

Associating Text Actions With Menus and Buttons
All Swing text components support standard editing commands such as cut, copy, paste, and insert characters. Each editing command is represented and implemented by an Action object. (To learn more about actions see How to Use Actions.) Actions allow you to associate a command with a GUI component, such as a menu item or button, and therefore build a GUI around a text component.

You can invoke the getActions method on any text component to receive an array containing all actions supported by this component. It is also possible to load the array of actions into a HashMap so your program can retrieve an action by name. Here is the code from the TextComponentDemo example that takes the actions from the text pane and loads them into a HashMap.

private HashMap<Object, Action> createActionTable(JTextComponent textComponent) {
        HashMap<Object, Action> actions = new HashMap<Object, Action>();
        Action[] actionsArray = textComponent.getActions();
        for (int i = 0; i < actionsArray.length; i++) {
            Action a = actionsArray[i];
            actions.put(a.getValue(Action.NAME), a);
        }
    return actions;
    }
Here is the method for retrieving an action by its name from the hash map:
private Action getActionByName(String name) {
    return actions.get(name);
}
You can use both methods verbatim in your programs.

The following code shows how the cut menu item is created and associated with the action of removing text from the text component.

protected JMenu createEditMenu() {
    JMenu menu = new JMenu("Edit");
    ...
    menu.add(getActionByName(DefaultEditorKit.cutAction));
    ...
This code gets the action by name using the handy method shown previously. It then adds the action to the menu. That is all you need to do. The menu and the action take care of everything else. Note that the name of the action comes from DefaultEditorKit. This kit provides actions for basic text editing and is the superclass for all the editor kits provided by Swing. So its capabilities are available to all text components unless thay are overridden by a customization.

For efficiency, text components share actions. The Action object returned by getActionByName(DefaultEditorKit.cutAction) is shared by the uneditable JTextArea at the bottom of the window. This sharing characteristic has two important ramifications:

  • Generally, you should not modify Action objects you get from editor kits. If you do, the changes affect all text components in your program.
  • Action objects can operate on other text components in the program, sometimes more than you intended. In this example, even though it is not editable, the JTextArea shares actions with the JTextPane. (Select some text in the text area, then choose the cut-to-clipboard menu item. You will hear a beep because the text area is not editable.) If you do not want to share, instantiate the Action object yourself. DefaultEditorKit defines a number of useful Action subclasses.
Here is the code that creates the Style menu and puts the Bold menu item in it:
protected JMenu createStyleMenu() {
    JMenu menu = new JMenu("Style");

    Action action = new StyledEditorKit.BoldAction();
    action.putValue(Action.NAME, "Bold");
    menu.add(action);
    ...
The StyledEditorKit provides Action subclasses to implement editing commands for styled text. You will note that instead of getting the action from the editor kit, this code creates an instance of the BoldAction class. Thus, this action is not shared with any other text component, and changing its name will not affect any other text component.

Associating Text Actions With Key Strokes
In addition to associating an action with a GUI component, you can also associate an action with a key stroke by using a text component's input map. Input maps are described in How to Use Key Bindings.

The text pane in the TextComponentDemo example supports four key bindings not provided by default.

  • Ctrl-B to move the caret backward one character
  • Ctrl-F to move the caret forward one character
  • Ctrl-N to move the caret down one line
  • Ctrl-P to move the caret up one line
The following code adds the Ctrl-B key binding to the text pane. The code for adding the other three bindings listed above is similar.
InputMap inputMap = textPane.getInputMap();

KeyStroke key = KeyStroke.getKeyStroke(KeyEvent.VK_B,
                                       Event.CTRL_MASK);
inputMap.put(key, DefaultEditorKit.backwardAction);

First, the code obtains the text component's input map. Next, it finds a KeyStroke object representing the Ctrl-B key sequence. Finally, the code binds the key stroke to the Action that moves the cursor backward.

Implementing Undo and Redo
Implementing undo and redo has two parts:
  • Remembering undoable edits.
  • Implementing the undo and redo commands and providing a user interface for them.

Part 1: Remembering Undoable Edits
To support undo and redo, a text component must remember each edit that occurs, the order of edits, and what is needed to undo each edit. The example program uses an instance of the UndoManager class to manage its list of undoable edits. The undo manager is created where the member variables are declared:

protected UndoManager undo = new UndoManager();
Now, let us look at how the program discovers undoable edits and adds them to the undo manager.

A document notifies interested listeners whenever an undoable edit occurs on the document content. An important step in implementing undo and redo is to register an undoable edit listener on the document of the text component. The following code adds an instance of MyUndoableEditListener to the text pane's document:

doc.addUndoableEditListener(new MyUndoableEditListener());
The undoable edit listener used in our example adds the edit to the undo manager's list:
protected class MyUndoableEditListener
          implements UndoableEditListener {
    public void undoableEditHappened(UndoableEditEvent e) {
        //Remember the edit and update the menus
        undo.addEdit(e.getEdit());
        undoAction.updateUndoState();
        redoAction.updateRedoState();
    }
}
Note that this method updates two objects: undoAction and redoAction. These are the action objects attached to the Undo and Redo menu items, respectively. The next step shows you how to create the menu items and how to implement the two actions. For general information about undoable edit listeners and undoable edit events, see How to Write an Undoable Edit Listener.
Note: By default, each undoable edit undoes a single character entry. It is possible with some effort to group edits so that a series of key strokes is combined into one undoable edit. Grouping edits in this manner would require you to define a class that intercepts undoable edit events from the document, combining them if appropriate and forwarding the results to your undoable edit listener.

Part 2: Implementing the Undo and Redo Commands
The first step in implementing undo and redo is to create the actions to put in the Edit menu.

JMenu menu = new JMenu("Edit");

//Undo and redo are actions of our own creation
undoAction = new UndoAction();
menu.add(undoAction);

redoAction = new RedoAction();
menu.add(redoAction);
...
The undo and redo actions are implemented by custom AbstractAction subclasses: UndoAction and RedoAction, respectively. These classes are inner classes of the example's primary class.

When the user invokes the undo command, the actionPerformed method of the UndoAction class is called:

public void actionPerformed(ActionEvent e) {
    try {
        undo.undo();
    } catch (CannotUndoException ex) {
        System.out.println("Unable to undo: " + ex);
        ex.printStackTrace();
    }
    updateUndoState();
    redoAction.updateRedoState();
}
This method calls the undo manager's undo method and updates the menu items to reflect the new undo/redo state.

Similarly, when the user invokes the redo command, the actionPerformed method of the RedoAction class is called:

public void actionPerformed(ActionEvent e) {
    try {
        undo.redo();
    } catch (CannotRedoException ex) {
        System.out.println("Unable to redo: " + ex);
        ex.printStackTrace();
    }
    updateRedoState();
    undoAction.updateUndoState();
}
This method is similar to undo, except that it calls the undo manager's redo method.

Much of the code in the UndoAction and RedoAction classes is dedicated to enabling and disabling the actions as appropriate of the current state, and changing the names of the menu items to reflect the edit to be undone or redone.

Note: The implementation of undo and redo in the TextComponentDemo example was taken from the NotePad demo that comes with the JDK software. Many programmers will also be able to copy this implementation of undo/redo without modification.

Concepts: About Documents
Like other Swing components, a text component separates its data (known as the model) from its view of the data. If you are not yet familiar with the model-view split used by Swing components, refer to Using Models.

A text component's model is known as a document and is an instance of a class that implements the Document interface. A document provides the following services for a text component:

  • Contains the text. A document stores the textual content in Element objects, which can represent any logical text structure, such as paragraphs, or text runs that share styles. We do not describe Element objects here. However, The Swing Connection has at least one article on the subject.
  • Provides support for editing the text through the remove and insertString methods.
  • Notifies document listeners and undoable edit listeners of changes to the text.
  • Manages Position objects, which track a particular location within the text even as the text is modified.
  • Allows you to obtain information about the text, such as its length, and segments of the text as a string.
The Swing text package contains a subinterface of Document, StyledDocument, that adds support for marking up the text with styles. One JTextComponent subclass, JTextPane, requires that its document be a StyledDocument rather than merely a Document.

The javax.swing.text package provides the following hierarchy of document classes, which implement specialized documents for the various JTextComponent subclasses:

The hierarchy of document classes that javax.swing.text provides.

A PlainDocument is the default document for text fields, password fields, and text areas. PlainDocument provides a basic container for text where all the text is displayed in the same font. Even though an editor pane is a styled text component, it uses an instance of PlainDocument by default. The default document for a standard JTextPane is an instance of DefaultStyledDocument — a container for styled text in no particular format. However, the document instance used by any particular editor pane or text pane depends on the type of content bound to it. If you use the setPage method to load text into an editor pane or text pane, the document instance used by the pane might change. Refer to How to Use Editor Panes and Text Panes for details.

Although you can set the document of a text component, it is usually easier to allow it to set automatically, and if necessary, use a document filter to change how the text component's data is set. You can implement certain customizations either by installing a document filter or by replacing a text component's document with one of your own. For example, the text pane in the TextComponentDemo example has a document filter that limits the number of characters the text pane can contain.

Implementing a Document Filter
To implement a document filter, create a subclass of DocumentFilter and then attach it to a document using the setDocumentFilter method defined in the AbstractDocument class. Although it is possible to have documents that do not descend from AbstractDocument, by default Swing text components use AbstractDocument subclasses for their documents.

The TextComponentDemo application has a document filter, DocumentSizeFilter, that limits the number of characters that the text pane can contain. Here is the code that creates the filter and attaches it to the text pane's document:

...//Where member variables are declared:
JTextPane textPane;
AbstractDocument doc;
static final int MAX_CHARACTERS = 300;
...
textPane = new JTextPane();
...
StyledDocument styledDoc = textPane.getStyledDocument();
if (styledDoc instanceof AbstractDocument) {
    doc = (AbstractDocument)styledDoc;
    doc.setDocumentFilter(new DocumentSizeFilter(MAX_CHARACTERS));
}
To limit the characters allowed in the document, DocumentSizeFilter overrides the DocumentFilter class's insertString method, which is called each time that text is inserted into the document. It also overrides the replace method, which is most likely to be called when the user pastes in new text. In general, text insertion can result when the user types or pastes in new text, or when the setText method is called. Here is the DocumentSizeFilter class's implementation of the insertString method:
public void insertString(FilterBypass fb, int offs,
                         String str, AttributeSet a)
    throws BadLocationException {

    if ((fb.getDocument().getLength() + str.length()) <= maxCharacters)="maxCharacters)" super.insertString(fb,="super.insertString(fb," offs,="offs," str,="str," a);="a);" else="else" Toolkit.getDefaultToolkit().beep();="Toolkit.getDefaultToolkit().beep();" }="}"

The code for replace is similar. The FilterBypass parameter to the methods defined by the DocumentFilter class is simply an object that enables the document to be updated in a thread-safe way.

Because the preceding document filter is concerned with additions to the document's data, it only overrides the insertString and replace methods. Most document filters would override DocumentFilter's remove method as well.

Listening for Changes on a Document
You can register two different types of listeners on a document: document listeners and undoable edit listeners. This subsection describes document listeners. For information about undoable edit listeners, refer to Implementing Undo and Redo.

A document notifies registered document listeners of changes to the document. Use a document listener to create a reaction when text is inserted or removed from a document, or when the text style changes.

The TextComponentDemo program uses a document listener to update the change log whenever a change is made to the text pane. The following line of code registers an instance of the MyDocumentListener class as a listener on the text pane's document:

doc.addDocumentListener(new MyDocumentListener());
Here is the implementation of the MyDocumentListener class:
protected class MyDocumentListener implements DocumentListener {
    public void insertUpdate(DocumentEvent e) {
        displayEditInfo(e);
    }
    public void removeUpdate(DocumentEvent e) {
        displayEditInfo(e);
    }
    public void changedUpdate(DocumentEvent e) {
        displayEditInfo(e);
    }
    private void displayEditInfo(DocumentEvent e) {
            Document document = (Document)e.getDocument();
            int changeLength = e.getLength();
            changeLog.append(e.getType().toString() + ": "
                + changeLength + " character"
                + ((changeLength == 1) ? ". " : "s. ")
                + " Text length = " + document.getLength()
                + "." + newline);
    }
}
The listener implements three methods for handling three different types of document events: insertion, removal, and style changes. StyledDocument instances can fire all three types of events. PlainDocument instances fire events only for insertion and removal. For general information about document listeners and document events, see How to Write a Document Listener.

Remember that the document filter for this text pane limits the number of characters allowed in the document. If you try to add more text than the document filter allows, the document filter blocks the change and the listener's insertUpdate method is not called. Document listeners are notified of changes only if the change has already occurred.

You may want to change the document's text within a document listener. However, you should never modify the contents of a text component from within a document listener. If you do, the program will likely deadlock. Instead, you can use a formatted text field or provide a document filter.

Listening for Caret and Selection Changes
The TextComponentDemo program uses a caret listener to display the current position of the caret or, if text is selected, the extent of the selection.

The caret listener class in this example is a JLabel subclass. Here is the code that creates the caret listener label and makes it a caret listener of the text pane:

//Create the status area
CaretListenerLabel caretListenerLabel = new CaretListenerLabel(
                        "Caret Status");
...
textPane.addCaretListener(caretListenerLabel);
A caret listener must implement one method, caretUpdate, which is called each time the caret moves or the selection changes. Here is the CaretListenerLabel implementation of caretUpdate:
public void caretUpdate(CaretEvent e) {
    //Get the location in the text
    int dot = e.getDot();
    int mark = e.getMark();
    if (dot == mark) {  // no selection
        try {
            Rectangle caretCoords = textPane.modelToView(dot);
            //Convert it to view coordinates
            setText("caret: text position: " + dot +
                    ", view location = [" +
                    caretCoords.x + ", " + caretCoords.y + "]" +
                    newline);
        } catch (BadLocationException ble) {
            setText("caret: text position: " + dot + newline);
        }
     } else if (dot < mark) {
        setText("selection from: " + dot + " to " + mark + newline);
     } else {
        setText("selection from: " + mark + " to " + dot + newline);
     }
}
As you can see, this listener updates its text label to reflect the current state of the caret or selection. The listener gets the information to display from the caret event object. For general information about caret listeners and caret events, see How to Write a Caret Listener.

As with document listeners, a caret listener is passive. It reacts to changes in the caret or in the selection, but does not change the caret or the selection itself. If you want to change the caret or selection, use a navigation filter or a custom caret.

Implementing a navigation filter is similar to implementing a document filter. First, write a subclass of NavigationFilter. Then attach an instance of the subclass to a text component with the setNavigationFilter method.

You might create a custom caret to customize the appearance of a caret. To create a custom caret, write a class that implements the Caret interface — perhaps by extending the DefaultCaret class. Then provide an instance of your class as an argument to the setCaret method on a text component.

Concepts: About Editor Kits

Text components use an EditorKit to tie the various pieces of the text component together. The editor kit provides the view factory, document, caret, and actions. An editor kit also reads and writes documents of a particular format. Although all text components use editor kits, some components hide theirs. You cannot set or get the editor kit used by a text field or text area. Editor panes and text panes provide the getEditorKit method to get the current editor kit and the setEditorKit method to change it.

For all components, the JTextComponent class provides the API for you to indirectly invoke or customize some editor kit capabilities. For example, JTextComponent provides the read and write methods, which invoke the editor kit's read and write methods. JTextComponent also provides a method, getActions, which returns all of the actions supported by a component.

The Swing text package provides the following editor kits:

DefaultEditorKit
Reads and writes plain text, and provides a basic set of editing commands. Details about how the text system treats newlines can be found in the DefaultEditorKit API documentation. Briefly, the '\n' character is used internally, but the document or platform line separators are used when writing files. All the other editor kits are descendants of the DefaultEditorKit class.
StyledEditorKit
Reads and writes styled text, and provides a minimal set of actions for styled text. This class is a subclass of DefaultEditorKit and is the editor kit used by JTextPane by default.
HTMLEditorKit
Reads, writes, and edits HTML. This is a subclass of StyledEditorKit.
Each of the editor kits listed above has been registered with the JEditorPane class and associated with the text format that the kit reads, writes, and edits. When a file is loaded into an editor pane, the pane checks the format of the file against its registered kits. If a registered kit is found that supports that file format, the pane uses the kit to read the file, display, and edit it. Thus, the editor pane effectively transforms itself into an editor for that text format. You can extend JEditorPane to support your own text format by creating an editor kit for it, and then using JEditorPane's registerEditorKitForContentType to associate your kit with your text format.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Text Components
Next page: The Text Component API


The Text Component API (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: Using Text Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
The Text Component API
This section lists commonly used parts of the API that are shared by text components. Much of this API is defined by the JTextComponent class. Text Component Features discusses how to use some of this API.

The JComponent Class describes the API that text components inherit from JComponent. For information about the API related to specific text components, see the how-to page for that component: text field, password field, formatted text field, text area, or editor pane and text pane.

For complete details about the text API, see the API documentation for JTextComponent and for the various classes and interfaces in the text package.

The API listed in this section includes the following categories:

  • Setting Attributes
  • Manipulating the Selection
  • Converting Positions Between the Model and the View
  • Text Editing Commands
  • Classes and Interfaces That Represent Documents
  • Working With Documents
  • Manipulating Carets and Selection Highlighters
  • Reading and Writing Text

Setting Attributes
These methods are defined in the JTextComponent class.
Method Description
void setEditable(boolean)
boolean isEditable() 		Sets or indicates whether the user can edit the text in the text component.
void setDragEnabled(boolean)
boolean getDragEnabled() 		Sets or gets the dragEnabled property, which must be true to enable drag handling on this component. The default value is false. See Drag and Drop for more details.
void setDisabledTextColor(Color)
Color getDisabledTextColor() 		Sets or gets the color used to display text when the text component is disabled.
void setMargin(Insets)
Insets getMargin() 		Sets or gets the margin between the text and the text component's border.

Manipulating the Selection
These methods are defined in the JTextComponent class.
Method | Description
String getSelectedText() | Gets the currently selected text.
void selectAll()
void select(int, int) 		Selects all text or selects text within a start and end range.
void setSelectionStart(int)
void setSelectionEnd(int)
int getSelectionStart()
int getSelectionEnd() 		Sets or gets the extent of the current selection by index.
void setSelectedTextColor(Color)
Color getSelectedTextColor() 		Sets or gets the color of selected text.
void setSelectionColor(Color)
Color getSelectionColor() 		Sets or gets the background color of selected text.

Converting Positions Between the Model and the View
These methods are defined in the JTextComponent class.
Method | Description
int viewToModel(Point) | Converts the specified point in the view coordinate system to a position within the text.
Rectangle modelToView(int) | Converts the specified position within the text to a rectangle in the view coordinate system.

Text Editing Commands
Class or Method | Description
void cut()
void copy()
void paste()
void replaceSelection(String)
(in JTextComponent) 		Cuts, copies, and pastes text using the system clipboard, or replaces the selected text with the string specified by an argument, respectively.
EditorKit | Provides a text component's view factory, document, caret, and actions, as well as reading and writing documents of a particular format.
DefaultEditorKit | A concrete subclass of EditorKit that provides the basic text editing capabilities.
StyledEditorKit | A subclass of Default EditorKit that provides additional editing capabilities for styled text.
String xxxxAction
(in DefaultEditorKit) 		The names of all the actions supported by the default editor kit. See Associating Text Actions with Menus and Buttons.
BeepAction
CopyAction
CutAction
DefaultKeyTypedAction
InsertBreakAction
InsertContentAction
InsertTabAction
PasteAction
(in DefaultEditorKit) 		Inner classes that implement various text editing commands.
AlignmentAction
BoldAction
FontFamilyAction
FontSizeAction
ForegroundAction
ItalicAction
StyledTextAction
UnderlineAction
(in StyledEditorKit) 		Inner classes that implement various editing commands for styled text.
Action[] getActions()
(in JTextComponent) 		Gets the actions supported by this component. This method gets the array of actions from the editor kit if one is used by the component.
InputMap getInputMap()
(in JComponent) 		Gets the input map that binds key strokes to actions. See Associating Text Actions with Key Strokes.
void put(KeyStroke, Object)
(in InputMap) 		Binds the specified key to the specified action. You generally specify the action by its name, which for standard editing actions is represented by a string constant such as DefaultEditorKit.backwardAction.

Classes and Interfaces That Represent Documents
Interface or Class | Description
Document | An interface that defines the API that must be implemented by all documents.
AbstractDocument | An abstract superclass implementation of the Document interface. This is the superclass for all documents provided by the Swing text package.
PlainDocument | A class that implements the Document interface. This is the default document for the plain text components (text field, password field, and text area). Additionally, this class is used by the editor panes and text panes when loading plain text or text of an unknown format.
StyledDocument | A Document subinterface. Defines the API that must be implemented by documents that support styled text. JTextPane requires that its document be of this type.
DefaultStyledDocument | A class that implements the StyledDocument interface. The default document for JTextPane.

Working With Documents
Class or Method | Description
DocumentFilter | The superclass of all document filters. You can use a document filter to change what gets inserted or removed from a document, without having to implement a document yourself. See Implementing a Document Filter.
void setDocumentFilter(DocumentFilter)
(in AbstractDocument) 		Sets the document filter.
void setDocument(Document)
Document getDocument()
(in JTextComponent) 		Sets or gets the document for a text component.
Document createDefaultModel()
(in JTextField) 		Creates a default PlainDocument model. Override this method to create a custom document instead of the default PlainDocument.
void addDocumentListener(DocumentListener)
void removeDocumentListener(DocumentListener)
(in Document) 		Adds or removes a document listener. See Listening for Changes on a Document.
void addUndoableEditListener(UndoableEditListener)
void removeUndoableEditListener(UndoableEditlistener)
(in Document) 		Adds or removes an undoable edit listener. Undoable edit listeners are used in Implementing Undo and Redo.
int getLength()
Position getStartPosition()
Position getEndPosition()
String getText(int, int)
(in Document) 		Document methods that return various descriptive information about the document.
Object getProperty(Object)
void putProperty(Object, Object)
(in Document)
void setDocumentProperties(Dictionary)
Dictionary getDocumentProperties()
(in AbstractDocument) 		A Document maintains a set of properties that you can manipulate with these methods.

Manipulating Carets and Selection Highlighters
These methods are defined in the JTextComponent class.
Interface, Class, or Method | Description
Caret | An interface that defines the API for objects that represent an insertion point within documents.
DefaultCaret | The default caret used by all text components.
void setCaret(Caret)
Caret getCaret() 		Sets or gets the caret object used by a text component.
void setCaretColor(Color)
Color getCaretColor() 		Sets or gets the color of the caret.
void setCaretPosition(int)
void moveCaretPosition(int)
int getCaretPosition() 		Sets or gets the current position of the caret within the document.
void addCaretListener(CaretListener)
void removeCaretListener(CaretListener) 		Adds or removes a caret listener from a text component.
NavigationFilter | The superclass for all navigation filters. A navigation filter lets you modify caret changes that are about to occur for a text component.
void setNavigationFilter(NavigationFilter) | Attaches a navigation filter to a text component.
Highlighter | An interface that defines the API for objects used to highlight the current selection.
DefaultHighlighter | The default highlighter used by all text components.
void setHighlighter(Highlighter)
Highlighter getHighlighter() 		Sets or gets the highlighter used by a text component.

Reading and Writing Text
Method Description
void read(Reader, Object)
void write(Writer)
(in JTextComponent) 		Reads or writes text.
void read(Reader, Document, int)
void read(InputStream, Document, int)
(in EditorKit) 		Reads text from a stream into a document.
void write(Writer, Document, int, int)
void write(OutputStream, Document, int, int)
(in EditorKit) 		Writes text from a document to a stream.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Text Component Features
Next page: How to Use Various Components


How to Use Various Components (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Various Components
Each of the following pages describes how to use a particular kind of Swing component. Another way to get to these pages is through A Visual Guide to Swing Components (Java Look and Feel) or A Visual Guide to Swing Components (Windows Look and Feel).
  • How to Make Applets
  • How to Use Buttons, Check Boxes, and Radio Butt ons
  • How to Use Color Choosers
  • How to Use Combo Boxes
  • How to Make Dialogs
  • How to Use Editor Panes and Text Panes
  • How to Use File Choosers
  • How to Use Formatted Text Fields
  • How to Make Frames (Main Windows)
  • How to Use Internal Frames
  • How to Use Labels
  • How to Use Layered Panes
  • How to Use Lists
  • How to Use Menus
  • How to Use Panels
  • How to Use Password Fields
  • How to Use Progress Bars
  • How to Use Root Panes
  • How to Use Scroll Panes
  • How to Use Separators
  • How to Use Sliders
  • How to Use Spinners
  • How to Use Split Panes
  • How to Use Tabbed Panes
  • How to Use Tables
  • How to Use Text Areas
  • How to Use Text Fields
  • How to Use Tool Bars
  • How to Use Tool Tips
  • How to Use Trees
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Text Component API
Next page: How to Make Applets


How to Make Applets (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Make Applets
This section covers JApplet — a class that enables applets to use Swing components. JApplet is a subclass of java.applet.Applet, which is covered in the Applets trail. If you've never written a regular applet before, we urge you to read that trail before proceeding with this section. The information provided in that trail applies to Swing applets, with a few exceptions that this section explains.

Any applet that contains Swing components must be implemented with a subclass of JApplet. Here's a Swing version of one of the applets that helped make Java famous — an animation applet that (in its most well known configuration) shows our mascot Duke doing cartwheels: Your browser is completely ignoring the <APPLET> tag!

Note: If you don't see the applet running above, you need to install release 6 of the JDK. You can find the main source code for this applet in TumbleItem.java.

This section discusses the following topics:

  • Features Provided by JApplet
  • Threads in Applets
  • Using Images in a Swing Applet
  • Embedding an Applet in an HTML Page
  • The JApplet API
  • Applet Examples

Features Provided by JApplet

Because JApplet is a top-level Swing container, each Swing applet has a root pane. The most noticeable effects of the root pane's presence are support for adding a menu bar and the need to use a content pane.

As described in Using Top-Level Containers, each top-level container such as a JApplet has a single content pane. The content pane makes Swing applets different from regular applets in the following ways:

  • You add components to a Swing applet's content pane, not directly to the applet. Adding Components to the Content Pane shows you how.
  • You set the layout manager on a Swing applet's content pane, not directly on the applet.
  • The default layout manager for a Swing applet's content pane is BorderLayout. This differs from the default layout manager for Applet, which is FlowLayout.
  • You should not put painting code directly in a JApplet object. See Performing Custom Painting for examples of how to perform custom painting in applets.

Threads in Applets

Swing components should be created, queried, and manipulated on the event-dispatching thread, but browsers don't invoke applet "milestone" methods from that thread. For this reason, the milestone methods — init, start, stop, and destroy — should use the SwingUtilities method invokeAndWait (or, if appropriate, invokeLater) so that code that refers to the Swing components is executed on the event-dispatching thread. More information about these methods and the event-dispatching thread is in Concurrency in Swing.

Here is an example of an init method:

public void init() {
    //Execute a job on the event-dispatching thread:
    //creating this applet's GUI.
    try {
        javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
                createGUI();
            }
        });
    } catch (Exception e) {
        System.err.println("createGUI didn't successfully complete");
    }
}

private void createGUI() {
    JLabel label = new JLabel(
                       "You are successfully running a Swing applet!");
    label.setHorizontalAlignment(JLabel.CENTER);
    label.setBorder(BorderFactory.createMatteBorder(1,1,1,1,Color.black));
    getContentPane().add(label, BorderLayout.CENTER);
}

The invokeLater method is not appropriate for this implementation because it allows init to return before initialization is complete, which can cause applet problems that are difficult to debug.

The init method in TumbleItem is more complex, as the following code shows. Like the first example, this init method implementation uses SwingUtilities.invokeAndWait to execute the GUI creation code on the event-dispatching thread. This init method sets up a Swing timer to fire action events the update the animation. Also, init uses javax.swing.SwingWorker to create a background task that loads the animation image files, letting the applet present a GUI right away, without waiting for all resources to be loaded.

private void createGUI() {
    ...
    animator = new Animator();
    animator.setOpaque(true);
    animator.setBackground(Color.white);
    setContentPane(animator);
    ...
}

public void init() {
    loadAppletParameters();

    //Execute a job on the event-dispatching thread:
    //creating this applet's GUI.
    try {
        javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
            public void run() {
                createGUI();
            }
        });
    } catch (Exception e) {
        System.err.println("createGUI didn't successfully complete");
    }

    //Set up the timer that will perform the animation.
    timer = new javax.swing.Timer(speed, this);
    timer.setInitialDelay(pause);
    timer.setCoalesce(false);
    timer.start(); //Start the animation.

    //Background task for loading images.
    SwingWorker worker = (new SwingWorker() {
            public ImageIcon[] doInBackground() {
                final ImageIcon[] innerImgs = new ImageIcon[nimgs];
            ...//Load all the images...
            return imgs;
        }
        public void done() {
            //Remove the "Loading images" label.
            animator.removeAll();
            loopslot = -1;
            try {
                imgs = get();
            } ...//Handle possible exceptions
        }

    }).execute();
}

You can find the applet's source code in TumbleItem.java. To find all the files required for the applet, including a link to a JNLP file that lets you run it using Java Web Start, see the example index.

Using Images in a Swing Applet

The Applet class provides the getImage method for loading images into an applet. The getImage method creates and returns an Image object that represents the loaded image. Because Swing components use Icons rather than Images to refer to pictures, Swing applets tend not to use getImage. Instead Swing applets create instances of ImageIcon — an icon loaded from an image file. ImageIcon comes with a code-saving benefit: it handles image tracking automatically. Refer to How to Use Icons for more information.

The animation of Duke doing cartwheels requires 17 different pictures. The applet uses one ImageIcon per picture and loads them in its init method. Because images can take a long time to load, the icons are loaded in a separate thread implemented by a SwingWorker object. Here's the code:

public void init() {
    ...
    imgs = new ImageIcon[nimgs];
    (new SwingWorker() {
        public ImageIcon[] doInBackground() {
            //Images are numbered 1 to nimgs,
            //but fill array from 0 to nimgs-1.
            for (int i = 0; i < nimgs; i++) {
                imgs[i] = loadImage(i+1);
            }
            return imgs;
        }
        ...
    }).execute();

}
...
protected ImageIcon loadImage(int imageNum) {
    String path = dir + "/T" + imageNum + ".gif";
    int MAX_IMAGE_SIZE = 2400;  //Change this to the size of
                                 //your biggest image, in bytes.
    int count = 0;
    BufferedInputStream imgStream = new BufferedInputStream(
       this.getClass().getResourceAsStream(path));
    if (imgStream != null) {
        byte buf[] = new byte[MAX_IMAGE_SIZE];
        try {
            count = imgStream.read(buf);
            imgStream.close();
        } catch (java.io.IOException ioe) {
            System.err.println("Couldn't read stream from file: " + path);
            return null;
        }
        if (count <= 0) {
            System.err.println("Empty file: " + path);
            return null;
        }
        return new ImageIcon(Toolkit.getDefaultToolkit().createImage(buf));
    } else {
        System.err.println("Couldn't find file: " + path);
        return null;
    }
}
The loadImage method loads the image for the specified frame of animation. It uses the getResourceAsStream method rather than the usual getResource method to get the images. The resulting code isn't pretty, but getResourceAsStream is more efficient than getResource for loading images from JAR files into applets that are executed using Java Plug-inTM software. For further details, see Loading Images Into Applets.

Embedding an Applet in an HTML Page

The recommended way to include an applet in an HTML page is using the APPLET tag. Here's the APPLET tag for the cartwheeling Duke applet:
<applet code="TumbleItem.class"
        codebase="examples/"
        archive="tumbleClasses.jar, tumbleImages.jar"
        width="600" height="95">
    <param name="maxwidth" value="120">
    <param name="nimgs" value="17">
    <param name="offset" value="-57">
    <param name="img" value="images/tumble">

Your browser is completely ignoring the &lt;APPLET&gt; tag!
</applet>
To find out about the various <APPLET> tag parameters, refer to Using the applet Tag and Using the APPLET Tag .

The JApplet API

The next table lists the interesting methods that JApplet adds to the applet API. They give you access to features provided by the root pane. Other methods you might use are defined by the Component and Applet classes. See Component Methods for a list of commonly used Component methods, and Applets for help in using Applet methods.

Method Purpose
void setContentPane(Container)
Container getContentPane() 		Set or get the applet's content pane. The content pane contains the applet's visible GUI components and should be opaque.
void setRootPane(JRootPane)
JRootPane getRootPane() 		Create, set, or get the applet's root pane. The root pane manages the interior of the applet including the content pane, the glass pane, and so on.
void setJMenuBar(JMenuBar)
JMenuBar getJMenuBar() 		Set or get the applet's menu bar to manage a set of menus for the applet.
void setGlassPane(Component)
Component getGlassPane() 		Set or get the applet's glass pane. You can use the glass pane to intercept mouse events.
void setLayeredPane(JLayeredPane)
JLayeredPane getLayeredPane() 		Set or get the applet's layered pane. You can use the applet's layered pane to put components on top of or behind other components.

Applet Example

This table shows examples of Swing applets and where those examples are described.

Example | Where Described | Notes
TumbleItem | This page | An animation applet

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Various Components
Next page: How to Use Buttons, Check Boxes, and Radio Buttons


How to Use Buttons, Check Boxes, and Radio Buttons (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Buttons, Check Boxes, and Radio Buttons

To create a button, you can instantiate one of the many classes that descend from the AbstractButton class. The following table shows the Swing-defined AbstractButton subclasses that you might want to use:

Class | Summary | Where Described
JButton | A common button. | How to Use the Common Button API and How to Use JButton Features
JCheckBox | A check box button. | How to Use Check Boxes
JRadioButton | One of a group of radio buttons. | How to Use Radio Buttons
JMenuItem | An item in a menu. | How to Use Menus
JCheckBoxMenuItem | A menu item that has a check box. | How to Use Menus and How to Use Check Boxes
JRadioButtonMenuItem | A menu item that has a radio button. | How to Use Menus and How to Use Radio Buttons
JToggleButton | Implements toggle functionality inherited by JCheckBox and JRadioButton. Can be instantiated or subclassed to create two-state buttons. | Used in some examples

Note: If you want to collect a group of buttons into a row or column, then you should check out tool bars.
First, this section explains the basic button API that AbstractButton defines — and thus all Swing buttons have in common. Next, it describes the small amount of API that JButton adds to AbstractButton. After that, this section shows you how to use specialized API to implement check boxes and radio buttons.

How to Use the Common Button API

Here is a picture of an application that displays three buttons:

A snapshot of ButtonDemo

Try this:
  1. Click the Launch button to run the Button Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ButtonDemo example

  2. Click the left button.
    It disables the middle button (and itself, since it is no longer useful) and enables the right button.
  3. Click the right button.
    It enables the middle button and the left button, and disables itself.

As the ButtonDemo example shows, a Swing button can display both text and an image. In ButtonDemo, each button has its text in a different place, relative to its image. The underlined letter in each button's text shows the mnemonic — the keyboard alternative — for each button. In most look and feels, the user can click a button by pressing the Alt key and the mnemonic. For example, Alt-M would click the Middle button in ButtonDemo.

When a button is disabled, the look and feel automatically generates the button's disabled appearance. However, you could provide an image to be substituted for the normal image. For example, you could provide gray versions of the images used in the left and right buttons.

How you implement event handling depends on the type of button you use and how you use it. Generally, you implement an action listener, which is notified every time the user clicks the button. For check boxes you usually use an item listener, which is notified when the check box is selected or deselected.

Below is the code from ButtonDemo.java that creates the buttons in the previous example and reacts to button clicks. The bold code is the code that would remain if the buttons had no images.

//In initialization code:
    ImageIcon leftButtonIcon = createImageIcon("images/right.gif");
    ImageIcon middleButtonIcon = createImageIcon("images/middle.gif");
    ImageIcon rightButtonIcon = createImageIcon("images/left.gif");

    b1 = new JButton("Disable middle button", leftButtonIcon);
    b1.setVerticalTextPosition(AbstractButton.CENTER);
    b1.setHorizontalTextPosition(AbstractButton.LEADING); //aka LEFT, for left-to-right locales
    b1.setMnemonic(KeyEvent.VK_D);
    b1.setActionCommand("disable");

    b2 = new JButton("Middle button", middleButtonIcon);
    b2.setVerticalTextPosition(AbstractButton.BOTTOM);
    b2.setHorizontalTextPosition(AbstractButton.CENTER);
    b2.setMnemonic(KeyEvent.VK_M);

    b3 = new JButton("Enable middle button", rightButtonIcon);
    //Use the default text position of CENTER, TRAILING (RIGHT).
    b3.setMnemonic(KeyEvent.VK_E);
    b3.setActionCommand("enable");
    b3.setEnabled(false);

    //Listen for actions on buttons 1 and 3.
    b1.addActionListener(this);
    b3.addActionListener(this);

    b1.setToolTipText("Click this button to disable "
                      + "the middle button.");
    b2.setToolTipText("This middle button does nothing "
                      + "when you click it.");
    b3.setToolTipText("Click this button to enable the "
                      + "middle button.");
    ...
}

public void actionPerformed(ActionEvent e) {
    if ("disable".equals(e.getActionCommand())) {
        b2.setEnabled(false);
        b1.setEnabled(false);
        b3.setEnabled(true);
    } else {
        b2.setEnabled(true);
        b1.setEnabled(true);
        b3.setEnabled(false);
    }
}

protected static ImageIcon createImageIcon(String path) {
    java.net.URL imgURL = ButtonDemo.class.getResource(path);
    ...//error handling omitted for clarity...
    return new ImageIcon(imgURL);
}

How to Use JButton Features

Ordinary buttons — JButton objects — have just a bit more functionality than the AbstractButton class provides: You can make a JButton be the default button.

At most one button in a top-level container can be the default button. The default button typically has a highlighted appearance and acts clicked whenever the top-level container has the keyboard focus and the user presses the Return or Enter key. Here is a picture of a dialog, implemented in the ListDialog example, in which the Set button is the default button:

In the Java Look & Feel, the default button has a heavy border

You set the default button by invoking the setDefaultButton method on a top-level container's root pane. Here is the code that sets up the default button for the ListDialog example:

//In the constructor for a JDialog subclass:
getRootPane().setDefaultButton(setButton);
The exact implementation of the default button feature depends on the look and feel. For example, in the Windows look and feel, the default button changes to whichever button has the focus, so that pressing Enter clicks the focused button. When no button has the focus, the button you originally specified as the default button becomes the default button again.

How to Use Check Boxes
The JCheckBox class provides support for check box buttons. You can also put check boxes in menus, using the JCheckBoxMenuItem class. Because JCheckBox and JCheckBoxMenuItem inherit from AbstractButton, Swing check boxes have all the usual button characteristics, as discussed earlier in this section. For example, you can specify images to be used in check boxes.

Check boxes are similar to radio buttons but their selection model is different, by convention. Any number of check boxes in a group — none, some, or all — can be selected. A group of radio buttons, on the other hand, can have only one button selected. file:///home/mb40549/ws/tutorial/src/uiswing/components/buttongroup.html

Here is a picture of an application that uses four check boxes to customize a cartoon:

NOT a tutorial reader!

Try this:
  1. Click the Launch button to run the CheckBox Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ButtonDemo example

  2. Click the Chin button or press Alt-c.
    The Chin check box becomes unselected, and the chin disappears from the picture. The other check boxes remain selected. This application has one item listener that listens to all the check boxes. Each time the item listener receives an event, the application loads a new picture that reflects the current state of the check boxes.

A check box generates one item event and one action event per click. Usually, you listen only for item events, since they let you determine whether the click selected or deselected the check box. Below is the code from CheckBoxDemo.java that creates the check boxes in the previous example and reacts to clicks.

//In initialization code:
    chinButton = new JCheckBox("Chin");
    chinButton.setMnemonic(KeyEvent.VK_C);
    chinButton.setSelected(true);

    glassesButton = new JCheckBox("Glasses");
    glassesButton.setMnemonic(KeyEvent.VK_G);
    glassesButton.setSelected(true);

    hairButton = new JCheckBox("Hair");
    hairButton.setMnemonic(KeyEvent.VK_H);
    hairButton.setSelected(true);

    teethButton = new JCheckBox("Teeth");
    teethButton.setMnemonic(KeyEvent.VK_T);
    teethButton.setSelected(true);

    //Register a listener for the check boxes.
    chinButton.addItemListener(this);
    glassesButton.addItemListener(this);
    hairButton.addItemListener(this);
    teethButton.addItemListener(this);
...
public void itemStateChanged(ItemEvent e) {
    ...
    Object source = e.getItemSelectable();

    if (source == chinButton) {
        //...make a note of it...
    } else if (source == glassesButton) {
        //...make a note of it...
    } else if (source == hairButton) {
        //...make a note of it...
    } else if (source == teethButton) {
        //...make a note of it...
    }

    if (e.getStateChange() == ItemEvent.DESELECTED)
        //...make a note of it...
    ...
    updatePicture();
}

How to Use Radio Buttons
Radio buttons are groups of buttons in which, by convention, only one button at a time can be selected. The Swing release supports radio buttons with the JRadioButton and ButtonGroup classes. To put a radio button in a menu, use the JRadioButtonMenuItem class. Other ways of displaying one-of-many choices are combo boxes and lists. Radio buttons look similar to check boxes, but, by convention, check boxes place no limits on how many items can be selected at a time.

Because JRadioButton inherits from AbstractButton, Swing radio buttons have all the usual button characteristics, as discussed earlier in this section. For example, you can specify the image displayed in a radio button.

Here is a picture of an application that uses five radio buttons to let you choose which kind of pet is displayed:

A snapshot of RadioButtonDemo

Try this:
  1. Click the Launch button to run the RadioButton Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ButtonDemo example

  2. Click the Dog button or press Alt-d.
    The Dog button becomes selected, which makes the Bird button become unselected. The picture switches from a bird to a dog. This application has one action listener that listens to all the radio buttons. Each time the action listener receives an event, the application displays the picture for the radio button that was just clicked.

Each time the user clicks a radio button (even if it was already selected), the button fires an action event. One or two item events also occur — one from the button that was just selected, and another from the button that lost the selection (if any). Usually, you handle radio button clicks using an action listener.

Below is the code from RadioButtonDemo.java that creates the radio buttons in the previous example and reacts to clicks.

//In initialization code:
    //Create the radio buttons.
    JRadioButton birdButton = new JRadioButton(birdString);
    birdButton.setMnemonic(KeyEvent.VK_B);
    birdButton.setActionCommand(birdString);
    birdButton.setSelected(true);

    JRadioButton catButton = new JRadioButton(catString);
    catButton.setMnemonic(KeyEvent.VK_C);
    catButton.setActionCommand(catString);

    JRadioButton dogButton = new JRadioButton(dogString);
    dogButton.setMnemonic(KeyEvent.VK_D);
    dogButton.setActionCommand(dogString);

    JRadioButton rabbitButton = new JRadioButton(rabbitString);
    rabbitButton.setMnemonic(KeyEvent.VK_R);
    rabbitButton.setActionCommand(rabbitString);

    JRadioButton pigButton = new JRadioButton(pigString);
    pigButton.setMnemonic(KeyEvent.VK_P);
    pigButton.setActionCommand(pigString);

    //Group the radio buttons.
    ButtonGroup group = new ButtonGroup();
    group.add(birdButton);
    group.add(catButton);
    group.add(dogButton);
    group.add(rabbitButton);
    group.add(pigButton);

    //Register a listener for the radio buttons.
    birdButton.addActionListener(this);
    catButton.addActionListener(this);
    dogButton.addActionListener(this);
    rabbitButton.addActionListener(this);
    pigButton.addActionListener(this);
...
public void actionPerformed(ActionEvent e) {
    picture.setIcon(new ImageIcon("images/"
                                  + e.getActionCommand()
                                  + ".gif"));
}

For each group of radio buttons, you need to create a ButtonGroup instance and add each radio button to it. The ButtonGroup takes care of unselecting the previously selected button when the user selects another button in the group.

You should generally initialize a group of radio buttons so that one is selected. However, the API doesn't enforce this rule — a group of radio buttons can have no initial selection. Once the user has made a selection, exactly one button is selected from then on. There's no supported API for unselecting all the buttons.

The Button API

The following tables list the commonly used button-related API. Other methods you might call, such as setFont and setForeground, are listed in the API tables in The JComponent Class.

The API for using buttons falls into these categories:

  • Setting or Getting the Button's Contents
  • Fine Tuning the Button's Appearance
  • Implementing the Button's Functionality
  • Check Box Constructors
  • Radio Button Constructors
  • Toggle Button Constructors
  • Commonly Used Button Group Constructors/Methods

Setting or Getting the Button's Contents
Method or Constructor Purpose
JButton(Action)
JButton(String, Icon)
JButton(String)
JButton(Icon)
JButton() 		Create a JButton instance, initializing it to have the specified text/image/action.
void setAction(Action)
Action getAction()
Set or get the button's properties according to values from the Action instance.
void setText(String)
String getText()
Set or get the text displayed by the button. You can use HTML formatting, as described in Using HTML in Swing Components.
void setIcon(Icon)
Icon getIcon()
Set or get the image displayed by the button when the button isn't selected or pressed.
void setDisabledIcon(Icon)
Icon getDisabledIcon()
Set or get the image displayed by the button when it is disabled. If you do not specify a disabled image, then the look and feel creates one by manipulating the default image.
void setPressedIcon(Icon)
Icon getPressedIcon()
Set or get the image displayed by the button when it is being pressed.
void setSelectedIcon(Icon)
Icon getSelectedIcon()
void setDisabledSelectedIcon(Icon)
Icon getDisabledSelectedIcon()
Set or get the image displayed by the button when it is selected. If you do not specify a disabled selected image, then the look and feel creates one by manipulating the selected image.
setRolloverEnabled(boolean)
boolean isRolloverEnabled()
void setRolloverIcon(Icon)
Icon getRolloverIcon()
void setRolloverSelectedIcon(Icon)
Icon getRolloverSelectedIcon()
Use setRolloverIcon(someIcon) to make the button display the specified icon when the cursor passes over it. The setRolloverSelectedIcon method lets you specify the rollover icon when the button is selected — this is useful for two-state buttons such as toggle buttons. Setting the rollover icon automatically calls setRollover(true), enabling rollover.

Fine Tuning the Button's Appearance
Method or Constructor Purpose
void setHorizontalAlignment(int)
void setVerticalAlignment(int)
int getHorizontalAlignment()
int getVerticalAlignment() 		Set or get where in the button its contents should be placed. The AbstractButton class allows any one of the following values for horizontal alignment: RIGHT, LEFT, CENTER (the default), LEADING, and TRAILING. For vertical alignment: TOP, CENTER (the default), and BOTTOM.
void setHorizontalTextPosition(int)
void setVerticalTextPosition(int)
int getHorizontalTextPosition()
int getVerticalTextPosition() 		Set or get where the button's text should be placed, relative to the button's image. The AbstractButton class allows any one of the following values for horizontal position: LEFT, CENTER, RIGHT, LEADING, and TRAILING (the default). For vertical position: TOP, CENTER (the default), and BOTTOM.
void setMargin(Insets)
Insets getMargin() 		Set or get the number of pixels between the button's border and its contents.
void setFocusPainted(boolean)
boolean isFocusPainted() 		Set or get whether the button should look different when it has the focus.
void setBorderPainted(boolean)
boolean isBorderPainted() 		Set or get whether the border of the button should be painted.
void setIconTextGap(int)
int getIconTextGap()
Set or get the amount of space between the text and the icon displayed in this button.

Implementing the Button's Functionality
Method or Constructor Purpose
void setMnemonic(int)
char getMnemonic()
Set or get the keyboard alternative to clicking the button. One form of the setMnemonic method accepts a character argument; however, the Swing team recommends that you use an int argument instead, specifying a KeyEvent.VK_X constant.
void setDisplayedMnemonicIndex(int)
int getDisplayedMnemonicIndex()
Set or get a hint as to which character in the text should be decorated to represent the mnemonic. Note that not all look and feels may support this.
void setActionCommand(String)
String getActionCommand()
Set or get the name of the action performed by the button.
void addActionListener(ActionListener)
ActionListener removeActionListener()
Add or remove an object that listens for action events fired by the button.
void addItemListener(ItemListener)
ItemListener removeItemListener()
Add or remove an object that listens for item events fired by the button.
void setSelected(boolean)
boolean isSelected()
Set or get whether the button is selected. Makes sense only for buttons that have on/off state, such as check boxes.
About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Make Applets
Next page: How to Use the ButtonGroup Component


How to Use the ButtonGroup Component (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use the ButtonGroup Component

The ButtonGroup component manages the selected/unselected state for a set of buttons. For the group, the ButtonGroup instance guarantees that only one button can be selected at a time.

Initially, all buttons managed by a ButtonGroup instance are unselected.

How to Use ButtonGroup Features

You can use ButtonGroup with any set of objects that inherit from AbstractButton. Typically a button group contains instances of JRadioButton, JRadioButtonMenuItem, or JToggleButton. It would not make sense to put an instance of JButton or JMenuItem in a button group because JButton and JMenuItem do not implement the select/deselect button state.

In general, you will typically follow these steps to write code that uses a ButtonGroup component.
  1. Subclass JFrame
  2. Call ContextPane together with a layout manager
  3. Declare and configure a set of radio buttons or toggle buttons
  4. Instantiate a ButtonGroup object
  5. Call the add method on that buttongroup object in order to add each button to the group.

For details and a code example, see How to Use Radio Buttons. It shows how to use a ButtonGroup component to group a set of RadioButtons set into a JPanel.

The ButtonGroup API

Commonly Used Button Group Constructors/Methods
Constructor or Method | Purpose
ButtonGroup() | Create a ButtonGroup instance.
void add(AbstractButton)
void remove(AbstractButton) 		Add a button to the group, or remove a button from the group.
public ButtonGroup getGroup()
(in DefaultButtonModel) 		Get the ButtonGroup, if any, that controls a button. For example:
ButtonGroup group = ((DefaultButtonModel)button.getModel()).getGroup();
public ButtonGroup clearSelection() | Clears the state of selected buttons in the ButtonGroup. None of the buttons in the ButtonGroup are selected .

ButtonGroup Examples

The following demonstration application uses the ButtonGroup component to group radio buttons displaying on a Window.

Example | Where Described | Notes
RadioButtonDemo | How to Use Radio Buttons | Uses radio buttons to determine which of five images it should display.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Buttons, Check Boxes, and Radio Buttons
Next page: How to Use Color Choosers


How to Use Color Choosers (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Color Choosers
Use the JColorChooser class to provide users with a palette of colors to choose from. A color chooser is a component that you can place anywhere within your program GUI. The JColorChooser API also makes it easy to bring up a dialog (modal or not) that contains a color chooser.

Here is a picture of an application that uses a color chooser to set the text color in a banner:

A snapshot of ColorChooserDemo, which contains a standard color chooser.

Try this:
  • Click the Launch button to run the ColorChooser Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ButtonDemo example

The source code for the program is in ColorChooserDemo.java.

The color chooser consists of everything within the box labeled Choose Text Color. This is what a standard color chooser looks like in the Java Look & Feel. It contains two parts, a tabbed pane and a preview panel. The three tabs in the tabbed pane select chooser panels. The preview panel below the tabbed pane displays the currently selected color.

Here is the code from the example that creates a JColorChooser instance and adds it to a container:

public class ColorChooserDemo extends JPanel ... {
    public ColorChooserDemo() {
        super(new BorderLayout());
        banner = new JLabel("Welcome to the Tutorial Zone!",
                            JLabel.CENTER);
        banner.setForeground(Color.yellow);
        . . .
        tcc = new JColorChooser(banner.getForeground());
        . . .
        add(tcc, BorderLayout.PAGE_END);
    }
The JColorChooser constructor in the previous code snippet takes a Color argument, which specifies the chooser's initially selected color. If you do not specify the initial color, then the color chooser displays Color.white. See the Color API documentation for a list of color constants you can use.

A color chooser uses an instance of ColorSelectionModel to contain and manage the current selection. The color selection model fires a change event whenever the user changes the color in the color chooser. The example program registers a change listener with the color selection model so that it can update the banner at the top of the window. The following code registers and implements the change listener:

tcc.getSelectionModel().addChangeListener(this);
. . .
public void stateChanged(ChangeEvent e) {
    Color newColor = tcc.getColor();
    banner.setForeground(newColor);
}
See How to Write a Change Listener for general information about change listeners and change events.

A basic color chooser, like the one used in the example program, is sufficient for many programs. However, the color chooser API allows you to customize a color chooser by providing it with a preview panel of your own design, by adding your own chooser panels to it, or by removing existing chooser panels from the color chooser. Additionally, the JColorChooser class provides two methods that make it easy to use a color chooser within a dialog.

The rest of this section discusses these topics:

  • Another Example: ColorChooserDemo2
  • Showing a Color Chooser in a Dialog
  • Removing or Replacing the Preview Panel
  • Creating a Custom Chooser Panel
  • The Color Chooser API
  • Examples that Use Color Choosers

Another Example: ColorChooserDemo2
Now let's turn our attention to ColorChooserDemo2, a modified version of the previous demo program that uses more of the JColorChooser API.
Try this:
  • Click the Launch button to run the ColorChooser Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ButtonDemo example

Here is a picture of ColorChooserDemo2:

A snapshot of ColorChooserDemo, which contains a custom color chooser.

This program customizes the banner text color chooser in these ways:

  • Removes the preview panel
  • Removes all of the default chooser panels
  • Adds a custom chooser panel
Removing or Replacing the Preview Panel covers the first customization. Creating a Custom Chooser Panel discusses the last two.

This program also adds a button that brings up a color chooser in a dialog, which you can use to set the banner background color.

Showing a Color Chooser in a Dialog
The JColorChooser class provides two class methods to make it easy to use a color chooser in a dialog. ColorChooserDemo2 uses one of these methods, showDialog, to display the background color chooser when the user clicks the Show Color Chooser... button. Here is the single line of code from the example that brings up the background color chooser in a dialog:
Color newColor = JColorChooser.showDialog(
                     ColorChooserDemo2.this,
                     "Choose Background Color",
                     banner.getBackground());
The first argument is the parent for the dialog, the second is the dialog title, and the third is the initially selected color.

The dialog disappears under three conditions: the user chooses a color and clicks the OK button, the user cancels the operation with the Cancel button, or the user dismisses the dialog with a frame control. If the user chooses a color, the showDialog method returns the new color. If the user cancels the operation or dismisses the window, the method returns null. Here is the code from the example that updates the banner background color according to the value returned by showDialog:

if (newColor != null) {
    banner.setBackground(newColor);
}
The dialog created by showDialog is modal. If you want a non-modal dialog, you can use JColorChooser's createDialog method to create the dialog. This method also lets you specify action listeners for the OK and Cancel buttons in the dialog window. Use JDialog's show method to display the dialog created by this method. For an example that uses this method, see Specifying Other Editors in the How to Use Tables section.

Removing or Replacing the Preview Panel
By default, the color chooser displays a preview panel. ColorChooserDemo2 removes the text color chooser's preview panel with this line of code:
tcc.setPreviewPanel(new JPanel());
This effectively removes the preview panel because a plain JPanel has no size and no default view. To set the preview panel back to the default, use null as the argument to setPreviewPanel.

To provide a custom preview panel, you also use setPreviewPanel. The component you pass into the method should inherit from JComponent, specify a reasonable size, and provide a customized view of the current color. To get notified when the user changes the color in the color chooser, the preview panel must register as a change listener on the color chooser's color selection model as described previously.

Creating a Custom Chooser Panel
The default color chooser provides three chooser panels:
  • Swatches — for choosing a color from a collection of swatches.
  • HSB — for choosing a color using the Hue-Saturation-Brightness color model.
  • RGB — for choosing a color using the Red-Green-Blue color model.
You can extend the default color chooser by adding chooser panels of your own design with addChooserPanel, or you can limit it by removing chooser panels with removeChooserPanel.

If you want to remove all of the default chooser panels and add one or more of your own, you can do this with a single call to setChooserPanels. ColorChooserDemo2 uses this method to replace the default chooser panels with an instance of CrayonPanel, a custom chooser panel. Here is the call to setChooserPanels from that example:

//Override the chooser panels with our own.
AbstractColorChooserPanel panels[] = { new CrayonPanel() };
tcc.setChooserPanels(panels);
The code is straighforward: it creates an array containing the CrayonPanel. Next the code calls setChooserPanels to set the contents of the array as the color chooser's chooser panels.

CrayonPanel is a subclass of AbstractColorChooserPanel and overrides the five abstract methods defined in its superclass:

void buildChooser()
Creates the GUI that comprises the chooser panel. The example creates four toggle buttons — one for each crayon — and adds them to the chooser panel.
void updateChooser()
This method is called whenever the chooser panel is displayed. The implementation of this method selects the toggle button that represents the currently selected color.
public void updateChooser() {
    Color color = getColorFromModel();
    if (Color.red.equals(color)) {
        redCrayon.setSelected(true);
    } else if (Color.yellow.equals(color)) {
        yellowCrayon.setSelected(true);
    } else if (Color.green.equals(color)) {
        greenCrayon.setSelected(true);
    } else if (Color.blue.equals(color)) {
        blueCrayon.setSelected(true);
    }
}

String getDisplayName()
Returns the display name of the chooser panel. The name is used on the tab for the chooser panel. Here is the example getDisplayName method:
public String getDisplayName() {
    return "Crayons";
}
Icon getSmallDisplayIcon()
Returns a small icon to represent this chooser panel. This is currently unused. Future versions of the color chooser might use this icon or the large one to represent this chooser panel in the display. The example implementation of this method returns null.

Icon getLargeDisplayIcon()
Returns a large icon to represent this chooser panel. This is currently unused. Future versions of the color chooser might use this icon or the small one to represent this chooser panel in the display. The example implementation of this method returns null.

The Color Chooser API

The following tables list the commonly used JColorChooser constructors and methods. Other methods you might call are listed in the API tables in The JComponent Class. The API for using color choosers falls into these categories:
  • Creating and Displaying the Color Chooser
  • Customizing the Color Chooser GUI
  • Setting or Getting the Current Color

Creating and Displaying the Color Chooser
Method or Constructor | Purpose
JColorChooser()
JColorChooser(Color)
JColorChooser(ColorSelectionModel) 		Create a color chooser. The default constructor creates a color chooser with an initial color of Color.white. Use the second constructor to specify a different initial color. The ColorSelectionModel argument, when present, provides the color chooser with a color selection model.
Color showDialog(Component, String, Color) | Create and show a color chooser in a modal dialog. The Component argument is the parent of the dialog, the String argument specifies the dialog title, and the Color argument specifies the chooser's initial color.
JDialog createDialog(Component, String,
boolean, JColorChooser, ActionListener,
ActionListener) 		Create a dialog for the specified color chooser. As with showDialog, the Component argument is the parent of the dialog and the String argument specifies the dialog title. The other arguments are as follows: the boolean specifies whether the dialog is modal, the JColorChooser is the color chooser to display in the dialog, the first ActionListener is for the OK button, and the second is for the Cancel button.

Customizing the Color Chooser's GUI
Method Purpose
void setPreviewPanel(JComponent)
JComponent getPreviewPanel() 		Set or get the component used to preview the color selection. To remove the preview panel, use new JPanel() as an argument. To specify the default preview panel, use null.
void setChooserPanels(AbstractColorChooserPanel[])
AbstractColorChooserPanel[] getChooserPanels() 		Set or get the chooser panels in the color chooser.
void addChooserPanel(AbstractColorChooserPanel)
AbstractColorChooserPanel removeChooserPanel(AbstractColorChooserPanel) 		Add a chooser panel to the color chooser or remove a chooser panel from it.
void setDragEnabled(boolean)
boolean getDragEnabled() 		Set or get the dragEnabled property, which must be true to enable drag handling on this component. The default value is false. See Drag and Drop for more details.

Setting or Getting the Current Color
Method Purpose
void setColor(Color)
void setColor(int, int, int)
void setColor(int)
Color getColor() 		Set or get the currently selected color. The three integer version of the setColor method interprets the three integers together as an RGB color. The single integer version of the setColor method divides the integer into four 8-bit bytes and interprets the integer as an RGB color as follows: How color chooser interprets an int as an RGB value.
void setSelectionModel(ColorSelectionModel)
ColorSelectionModel getSelectionModel() 		Set or get the selection model for the color chooser. This object contains the current selection and fires change events to registered listeners whenever the selection changes.

Examples that Use Color Choosers

This table shows the examples that use JColorChooser and where those examples are described.

Example | Where Described | Notes
ColorChooserDemo | This section | Uses a standard color chooser.
ColorChooserDemo2 | This section | Uses one customized color chooser and one standard color chooser in a dialog created with showDialog.
TableDialogEditDemo | How to Use Tables | Shows how to use a color chooser as a custom cell editor in a table. The color chooser used by this example is created with createDialog.
BasicDnD | Introduction to DnD | Uses a color chooser that is not in a dialog; demonstrates default drag-and-drop capabilities of Swing components, including color choosers.
DragColorDemo | Introduction to DnD | Uses a color chooser without a dialog in a demonstration of importing Color data.
DragColorTextFieldDemo | Introduction to DnD | Similar to DragColorDemo, but demonstrates importing both Color and text data.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use the ButtonGroup Component
Next page: How to Use Combo Boxes


How to Use Combo Boxes (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Combo Boxes
A JComboBox, which lets the user choose one of several choices, can have two very different forms. The default form is the uneditable combo box, which features a button and a drop-down list of values. The second form, called the editable combo box, features a text field with a small button abutting it. The user can type a value in the text field or click the button to display a drop-down list. Here's what the two forms of combo boxes look like in the Java look and feel:

An uneditable combo box

An editable combo box

An uneditable combo box

An editable combo box

Uneditable combo box, before (top)
and after the button is clicked 		Editable combo box, before and after
the arrow button is clicked

Combo boxes require little screen space, and their editable (text field) form is useful for letting the user quickly choose a value without limiting the user to the displayed values. Other components that can display one-of-many choices are groups of radio buttons and lists. Groups of radio buttons are generally the easiest for users to understand, but combo boxes can be more appropriate when space is limited or more than a few choices are available. Lists are not terribly attractive, but they're more appropriate than combo boxes when the number of items is large (say, over 20) or when selecting multiple items might be valid.

Because editable and uneditable combo boxes are so different, this section treats them separately. This section covers these topics:

  • Using an Uneditable Combo Box
  • Handling Events on a Combo Box
  • Using an Editable Combo Box
  • Providing a Custom Renderer
  • The Combo Box API
  • Examples that Use Combo Boxes

Using an Uneditable Combo Box
The application shown here uses an uneditable combo box for choosing a pet picture:

An uneditable combo box

Try this:
  1. Click the Launch button to run the ComboBox Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ComboBoxDemo example

  2. Choose an animal name from the combo box to view its picture.
  3. Compare the operation and GUI of this program to one that uses radio buttons: run RadioButtonDemo (it requires release 6). You might want to compare the source code as well: ComboBoxDemo.java vs. RadioButtonDemo.java.
The following code, taken from ComboBoxDemo.java, creates an uneditable combo box and sets it up:
String[] petStrings = { "Bird", "Cat", "Dog", "Rabbit", "Pig" };

//Create the combo box, select item at index 4.
//Indices start at 0, so 4 specifies the pig.
JComboBox petList = new JComboBox(petStrings);
petList.setSelectedIndex(4);
petList.addActionListener(this);
This combo box contains an array of strings, but you could just as easily use icons instead. To put anything else into a combo box or to customize how the items in a combo box look, you need to write a custom renderer. An editable combo box would also need a custom editor. Refer to Providing a Custom Renderer for information and an example.

The preceding code registers an action listener on the combo box. To see the action listener implementation and learn about other types of listeners supported by combo box, refer to Handling Events on a Combo Box.

No matter which constructor you use, a combo box uses a combo box model to contain and manage the items in its menu. When you initialize a combo box with an array or a vector, the combo box creates a default model object for you. As with other Swing components, you can customize a combo box in part by implementing a custom model — an object that implements the ComboBoxModel interface.

Note: Be careful when implementing a custom model for a combo box. The JComboBox methods that change the items in the combo box's menu, such as insertItemAt, work only if the data model implements the MutableComboBoxModel interface (a subinterface of ComboBoxModel). Refer to the API tables to see which methods are affected.

Something else to watch out for — even for uneditable combo boxes — is ensuring that your custom model fires list data events when the combo box's data or state changes. Even immutable combo box models, whose data never changes, must fire a list data event (a CONTENTS_CHANGED event) when the selection changes. One way to get the list data event firing code for free is to make your combo box model a subclass of AbstractListModel.

Handling Events on a Combo Box
Here's the code from ComboBoxDemo.java that registers and implements an action listener on the combo box:
public class ComboBoxDemo ... implements ActionListener {
    . . .
        petList.addActionListener(this) {
    . . .
    public void actionPerformed(ActionEvent e) {
        JComboBox cb = (JComboBox)e.getSource();
        String petName = (String)cb.getSelectedItem();
        updateLabel(petName);
    }
    . . .
}
This action listener gets the newly selected item from the combo box, uses it to compute the name of an image file, and updates a label to display the image. The combo box fires an action event when the user selects an item from the combo box's menu. See How to Write an Action Listener, for general information about implementing action listeners.

Combo boxes also generate item events, which are fired when any of the items' selection state changes. Only one item at a time can be selected in a combo box, so when the user makes a new selection the previously selected item becomes unselected. Thus two item events are fired each time the user selects a different item from the menu. If the user chooses the same item, no item events are fired. Use addItemListener to register an item listener on a combo box. How to Write an Item Listener gives general information about implementing item listeners.

Although JComboBox inherits methods to register listeners for low-level events — focus, key, and mouse events, for example — we recommend that you don't listen for low-level events on a combo box. Here's why: A combo box is a compound component — it is comprised of two or more other components. The combo box itself fires high-level events such as action events. Its subcomponents fire low-level events such as mouse, key, and focus events. The low-level events and the subcomponent that fires them are look-and-feel-dependent. To avoid writing look-and-feel-dependent code, you should listen only for high-level events on a compound component such as a combo box. For information about events, including a discussion about high- and low-level events, refer to Writing Event Listeners.

Using an Editable Combo Box
Here's a picture of a demo application that uses an editable combo box to enter a pattern with which to format dates.

An editable combo box

Try this:
  1. Click the Launch button to run the ComboBox2 Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ComboBoxDemo2 example

  2. Enter a new pattern by choosing one from the combo box's menu. The program reformats the current date and time.
  3. Enter a new pattern by typing one in and pressing Enter. Again the program reformats the current date and time.

The following code, taken from ComboBoxDemo2.java, creates and sets up the combo box:

String[] patternExamples = {
         "dd MMMMM yyyy",
         "dd.MM.yy",
         "MM/dd/yy",
         "yyyy.MM.dd G 'at' hh:mm:ss z",
         "EEE, MMM d, ''yy",
         "h:mm a",
         "H:mm:ss:SSS",
         "K:mm a,z",
         "yyyy.MMMMM.dd GGG hh:mm aaa"
};
. . .
JComboBox patternList = new JComboBox(patternExamples);
patternList.setEditable(true);
patternList.addActionListener(this);
This code is very similar to the previous example, but warrants a few words of explanation. The bold line of code explicitly turns on editing to allow the user to type values in. This is necessary because, by default, a combo box is not editable. This particular example allows editing on the combo box because its menu does not provide all possible date formatting patterns, just shortcuts to frequently used patterns.

An editable combo box fires an action event when the user chooses an item from the menu and when the user types Enter. Note that the menu remains unchanged when the user enters a value into the combo box. If you want, you can easily write an action listener that adds a new item to the combo box's menu each time the user types in a unique value.

See Internationalization to learn more about formatting dates and other types of data.

Providing a Custom Renderer

A combo box uses a renderer to display each item in its menu. If the combo box is uneditable, it also uses the renderer to display the currently selected item. An editable combo box, on the other hand, uses an editor to display the selected item. A renderer for a combo box must implement the ListCellRenderer interface. A combo box's editor must implement ComboBoxEditor. This section shows how to provide a custom renderer for an uneditable combo box.

The default renderer knows how to render strings and icons. If you put other objects in a combo box, the default renderer calls the toString method to provide a string to display. You can customize the way a combo box renders itself and its items by implementing your own ListCellRenderer.

Here's a picture of an application that uses a combo box with a custom renderer:

A combo box with a custom renderer

You can run CustomComboBoxDemo ( download JDK 6). The full source code for this example is in CustomComboBoxDemo.java. To get the image files it requires, consult the example index.

The following statements from the example create an instance of ComboBoxRenderer (a custom class) and set up the instance as the combo box's renderer:

JComboBox petList = new JComboBox(intArray);
. . .
ComboBoxRenderer renderer = new ComboBoxRenderer();
renderer.setPreferredSize(new Dimension(200, 130));
petList.setRenderer(renderer);
petList.setMaximumRowCount(3);

The last line sets the combo box's maximum row count, which determines the number of items visible when the menu is displayed. If the number of items in the combo box is larger than its maximum row count, the menu has a scroll bar. The icons are pretty big for a menu, so our code limits the number of rows to 3. Here's the implementation of ComboBoxRenderer, a renderer that puts an icon and text side-by-side:

class ComboBoxRenderer extends JLabel
                       implements ListCellRenderer {
    . . .
    public ComboBoxRenderer() {
        setOpaque(true);
        setHorizontalAlignment(CENTER);
        setVerticalAlignment(CENTER);
    }

    /*
     * This method finds the image and text corresponding
     * to the selected value and returns the label, set up
     * to display the text and image.
     */
    public Component getListCellRendererComponent(
                                       JList list,
                                       Object value,
                                       int index,
                                       boolean isSelected,
                                       boolean cellHasFocus) {
        //Get the selected index. (The index param isn't
        //always valid, so just use the value.)
        int selectedIndex = ((Integer)value).intValue();

        if (isSelected) {
            setBackground(list.getSelectionBackground());
            setForeground(list.getSelectionForeground());
        } else {
            setBackground(list.getBackground());
            setForeground(list.getForeground());
        }

        //Set the icon and text.  If icon was null, say so.
        ImageIcon icon = images[selectedIndex];
        String pet = petStrings[selectedIndex];
        setIcon(icon);
        if (icon != null) {
            setText(pet);
            setFont(list.getFont());
        } else {
            setUhOhText(pet + " (no image available)",
                        list.getFont());
        }

        return this;
    }
    . . .
}
As a ListCellRenderer, ComboBoxRenderer implements a method called getListCellRendererComponent, which returns a component whose paintComponent method is used to display the combo box and each of its items. The easiest way to display an image and an icon is to use a label. So ComboBoxRenderer is a subclass of label and returns itself. The implementation of getListCellRendererComponent configures the renderer to display the currently selected icon and its description.

These arguments are passed to getListCellRendererComponent:

  • JList list — a list object used behind the scenes to display the items. The example uses this object's colors to set up foreground and background colors.
  • Object value — the object to render. An Integer in this example.
  • int index — the index of the object to render.
  • boolean isSelected — indicates whether the object to render is selected. Used by the example to determine which colors to use.
  • boolean cellHasFocus — indicates whether the object to render has the focus.
Note that combo boxes and lists use the same type of renderer — ListCellRenderer. You can save yourself some time by sharing renderers between combo boxes and lists, if it makes sense for your program.

The Combo Box API

The following tables list the commonly used JComboBox constructors and methods. Other methods you are most likely to invoke on a JComboBox object are those it inherits from its superclasses, such as setPreferredSize. See The JComponent API for tables of commonly used inherited methods.

The API for using combo boxes falls into two categories:

  • Setting or Getting the Items in the Combo Box's Menu
  • Customizing the Combo Box's Operation

Setting or Getting the Items in the Combo Boxes's Menu
Method | Purpose
JComboBox()
JComboBox(ComboBoxModel)
JComboBox(Object[])
JComboBox(Vector) 		Create a combo box with the specified items in its menu. A combo box created with the default constructor has no items in the menu initially. Each of the other constructors initializes the menu from its argument: a model object, an array of objects, or a Vector of objects.
void addItem(Object)
void insertItemAt(Object, int) 		Add or insert the specified object into the combo box's menu. The insert method places the specified object at the specified index, thus inserting it before the object currently at that index. These methods require that the combo box's data model be an instance of MutableComboBoxModel.
Object getItemAt(int)
Object getSelectedItem() 		Get an item from the combo box's menu.
void removeAllItems()
void removeItemAt(int)
void removeItem(Object) 		Remove one or more items from the combo box's menu. These methods require that the combo box's data model be an instance of MutableComboBoxModel.
int getItemCount() | Get the number of items in the combo box's menu.
void setModel(ComboBoxModel)
ComboBoxModel getModel() 		Set or get the data model that provides the items in the combo box's menu.
void setAction(Action)
Action getAction() 		Set or get the Action associated with the combo box. For further information, see How to Use Actions.

Customizing the Combo Box's Operation
Method or Constructor | Purpose
void addActionListener(ActionListener) | Add an action listener to the combo box. The listener's actionPerformed method is called when the user selects an item from the combo box's menu or, in an editable combo box, when the user presses Enter.
void addItemListener(ItemListener) | Add an item listener to the combo box. The listener's itemStateChanged method is called when the selection state of any of the combo box's items change.
void setEditable(boolean)
boolean isEditable() 		Set or get whether the user can type in the combo box.
void setRenderer(ListCellRenderer)
ListCellRenderer getRenderer() 		Set or get the object responsible for painting the selected item in the combo box. The renderer is used only when the combo box is uneditable. If the combo box is editable, the editor is used to paint the selected item instead.
void setEditor(ComboBoxEditor)
ComboBoxEditor getEditor() 		Set or get the object responsible for painting and editing the selected item in the combo box. The editor is used only when the combo box is editable. If the combo box is uneditable, the renderer is used to paint the selected item instead.

Examples that Use Combo Boxes

This table shows the examples that use JComboBox and where those examples are described.

Example | Where Described | Notes
ComboBoxDemo | This section | Uses an uneditable combo box.
ComboBoxDemo2 | This section | Uses an editable combo box.
CustomComboBoxDemo | This section | Provides a custom renderer for a combo box.
TableRenderDemo | How to Use Tables (Using a Combo Box as an Editor) | Shows how to use a combo box as a table cell editor.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Color Choosers
Next page: How to Make Dialogs


How to Make Dialogs (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Make Dialogs
A Dialog window is an independent subwindow meant to carry temporary notice apart from the main Swing Application Window. Most Dialogs present an error message or warning to a user, but Dialogs can present images, directory trees, or just about anything compatible with the main Swing Application that manages them.

For convenience, several Swing component classes can directly instantiate and display dialogs. To create simple, standard dialogs, you use the JOptionPane class. The ProgressMonitor class can put up a dialog that shows the progress of an operation. Two other classes, JColorChooser and JFileChooser, also supply standard dialogs. To bring up a print dialog, you can use the Printing API. To create a custom dialog, use the JDialog class directly.

The code for simple dialogs can be minimal. For example, here is an informational dialog:

An informational dialog requires minimal code

Here is the code that creates and shows it:

JOptionPane.showMessageDialog(frame, "Eggs are not supposed to be green.");
The rest of this section covers the following topics:
  • An Overview of Dialogs
  • The DialogDemo Example
  • JOptionPane Features
  • Creating and Showing Simple Dialogs
  • Customizing Button Text
  • Getting the User's Input from a Dialog
  • Stopping Automatic Dialog Closing
  • The Dialog API
  • Examples that Use Dialogs

An Overview of Dialogs

Every dialog is dependent on a Frame component. When that Frame is destroyed, so are its dependent Dialogs. When the frame is iconified, its dependent Dialogs also disappear from the screen. When the frame is deiconified, its dependent Dialogs return to the screen. A swing JDialog class inherits this behavior from the AWT Dialog class.

A Dialog can be modal. When a modal Dialog is visible, it blocks user input to all other windows in the program. JOptionPane creates JDialogs that are modal. To create a non-modal Dialog, you must use the JDialog class directly.

Starting with JDK6, you can modify Dialog window modality behavior using the new Modality API. See The New Modality API for details.

The JDialog class is a subclass of the AWT java.awt.Dialog class. It adds a root pane container and support for a default close operation to the Dialog object . These are the same features that JFrame has, and using JDialog directly is very similar to using JFrame. If you're going to use JDialog directly, then you should understand the material in Using Top-Level Containers and How to Make Frames, especially Responding to Window-Closing Events.

Even when you use JOptionPane to implement a dialog, you're still using a JDialog behind the scenes. The reason is that JOptionPane is simply a container that can automatically create a JDialog and add itself to the JDialog's content pane.

The DialogDemo Example

Here is a picture of an application that displays dialogs.

DialogDemo lets you bring up many kinds of dialogs

Try this::
  1. Click the Launch button to run the Dialog Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the DialogDemo example

  2. Click the Show it! button.
    A modal dialog will appear. Until you close it, the application will be unresponsive, although it will repaint itself if necessary. You can close the dialog either by clicking a button in the dialog or explicitly, such as by using the dialog window decorations.
  3. In the More Dialogs pane, click the bottom radio button and then the Show it! button.
    A non-modal dialog will appear. Note that the DialogDemo window remains fully functional while the non-modal dialog is up.
  4. While the non-modal dialog is showing, iconify the DialogDemo window.
    The dialog will disappear from the screen until you deiconify the DialogDemo window.

JOptionPane Features

Using JOptionPane, you can quickly create and customize several different kinds of dialogs. JOptionPane provides support for laying out standard dialogs, providing icons, specifying the dialog title and text, and customizing the button text. Other features allow you to customize the components the dialog displays and specify where the dialog should appear onscreen. You can even specify that an option pane put itself into an internal frame (JInternalFrame) instead of a JDialog.

When you create a JOptionPane, look-and-feel-specific code adds components to the JOptionPane and determines the layout of those components.

JOptionPane's icon support lets you easily specify which icon the dialog displays. You can use a custom icon, no icon at all, or any one of four standard JOptionPane icons (question, information, warning, and error). Each look and feel has its own versions of the four standard icons. The following figure shows the icons used in the Java (and Windows) look and feel.

Icons used by JOptionPane
(Java look and feel)
The Java look and feel icon for dialogs that ask questions | The Java look and feel icon for informational dialogs | The Java look and feel icon for warning dialogs | The Java look and feel icon for error dialogs
question | information | warning | error

(Windows look and feel)
The Windows look and feel icon for dialogs that ask questions | The Windows look and feel icon for informational dialogs | The Windows look and feel icon for warning dialogs | The Windows look and feel icon for error dialogs
question | information | warning | error

Creating and Showing Simple Dialogs

For most simple modal dialogs, you create and show the dialog using one of JOptionPane's showXxxDialog methods. If your dialog should be an internal frame, then add Internal after show — for example, showMessageDialog changes to showInternalMessageDialog. If you need to control the dialog window-closing behavior or if you do not want the dialog to be modal, then you should directly instantiate JOptionPane and add it to a JDialog instance. Then invoke setVisible(true) on the JDialog to make it appear.

The two most useful showXxxDialog methods are showMessageDialog and showOptionDialog. The showMessageDialog method displays a simple, one-button dialog. The showOptionDialog method displays a customized dialog — it can display a variety of buttons with customized button text, and can contain a standard text message or a collection of components.

The other two showXxxDialog methods are used less often. The showConfirmDialog method asks the user to confirm something, but presents standard button text (Yes/No or the localized equivalent, for example) rather than button text customized to the user situation (Start/Cancel, for example). A fourth method, showInputDialog, is designed to display a modal dialog that gets a string from the user, using either a text field, an uneditable combo box or a list.

Here are some examples, taken from DialogDemo.java, of using showMessageDialog, showOptionDialog, and the JOptionPane constructor. For more example code, see DialogDemo.java and the other programs listed in Examples that Use Dialogs.

showMessageDialog
Displays a modal dialog with one button, which is labeled "OK" (or the localized equivalent). You can easily specify the message, icon, and title that the dialog displays. Here are some examples of using showMessageDialog:

Informational dialog with default title and icon
//default title and icon
JOptionPane.showMessageDialog(frame,
    "Eggs are not supposed to be green.",
    "Message");
Informational dialog with custom title, warning icon
//custom title, warning icon
JOptionPane.showMessageDialog(frame,
    "Eggs are not supposed to be green.",
    "Inane warning",
    JOptionPane.WARNING_MESSAGE);
Informational dialog with custom title, error icon
//custom title, error icon
JOptionPane.showMessageDialog(frame,
    "Eggs are not supposed to be green.",
    "Inane error",
    JOptionPane.ERROR_MESSAGE);
Informational dialog with custom title, no icon
//custom title, no icon
JOptionPane.showMessageDialog(frame,
    "Eggs are not supposed to be green.",
    "A plain message",
    JOptionPane.PLAIN_MESSAGE);
Informational dialog with custom title, custom icon
//custom title, custom icon
JOptionPane.showMessageDialog(frame,
    "Eggs are not supposed to be green.",
    "Inane custom dialog",
    JOptionPane.INFORMATION_MESSAGE,
    icon);

showOptionDialog
Displays a modal dialog with the specified buttons, icons, message, title, and so on. With this method, you can change the text that appears on the buttons of standard dialogs. You can also perform many other kinds of customization.

Yes/No/Cancel (in different words); showOptionDialog
//Custom button text
Object[] options = {"Yes, please",
                    "No, thanks",
                    "No eggs, no ham!"};
int n = JOptionPane.showOptionDialog(frame,
    "Would you like some green eggs to go "
    + "with that ham?",
    "A Silly Question",
    JOptionPane.YES_NO_CANCEL_OPTION,
    JOptionPane.QUESTION_MESSAGE,
    null,
    options,
    options[2]);

JOptionPane (constructor)
Creates a JOptionPane with the specified buttons, icons, message, title, and so on. You must then add the option pane to a JDialog, register a property-change listener on the option pane, and show the dialog. See Stopping Automatic Dialog Closing for details.

Explicitly used the JOptionPane constructor
final JOptionPane optionPane = new JOptionPane(
    "The only way to close this dialog is by\n"
    + "pressing one of the following buttons.\n"
    + "Do you understand?",
    JOptionPane.QUESTION_MESSAGE,
    JOptionPane.YES_NO_OPTION);

The arguments to all of the showXxxDialog methods and JOptionPane constructors are standardized, though the number of arguments for each method and constructor varies. The following list describes each argument. To see the exact list of arguments for a particular method, see The Dialog API.
Component parentComponent
The first argument to each showXxxDialog method is always the parent component, which must be a Frame, a component inside a Frame, or null. If you specify a Frame or Dialog, then the Dialog will appear over the center of the Frame and follow the focus behavior of that Frame. If you specify a component inside a Frame, then the Dialog will appear over the center of that component and will follow the focus behavior of that component's Frame. If you specify null, then the look and feel will pick an appropriate position for the dialog — generally the center of the screen — and the Dialog will not necessarily follow the focus behavior of any visible Frame or Dialog.

The JOptionPane constructors do not include this argument. Instead, you specify the parent frame when you create the JDialog that contains the JOptionPane, and you use the JDialog setLocationRelativeTo method to set the dialog position.

Object message
This required argument specifies what the dialog should display in its main area. Generally, you specify a string, which results in the dialog displaying a label with the specified text. You can split the message over several lines by putting newline (\n) characters inside the message string. For example:
"Complete the sentence:\n \"Green eggs and...\""
String title
The title of the dialog.
int optionType
Specifies the set of buttons that appear at the bottom of the dialog. Choose from one of the following standard sets: DEFAULT_OPTION, YES_NO_OPTION, YES_NO_CANCEL_OPTION, OK_CANCEL_OPTION.
int messageType
This argument determines the icon displayed in the dialog. Choose from one of the following values: PLAIN_MESSAGE (no icon), ERROR_MESSAGE, INFORMATION_MESSAGE, WARNING_MESSAGE, QUESTION_MESSAGE.
Icon icon
The icon to display in the dialog.
Object[] options
Generally used to specify the string displayed by each button at the bottom of the dialog. See Customizing Button Text in a Standard Dialog for more information. Can also be used to specify icons to be displayed by the buttons or non-button components to be added to the button row.
Object initialValue
Specifies the default value to be selected.

You can either let the option pane display its default icon or specify the icon using the message type or icon argument. By default, an option pane created with showMessageDialog displays the information icon, one created with showConfirmDialog or showInputDialog displays the question icon, and one created with a JOptionPane constructor displays no icon. To specify that the dialog display a standard icon or no icon, specify the message type corresponding to the icon you desire. To specify a custom icon, use the icon argument. The icon argument takes precedence over the message type; as long as the icon argument has a non-null value, the dialog displays the specified icon.

Customizing Button Text

When you use JOptionPane to create a dialog, you can either use the standard button text (which might vary by look and feel and locale) or specify different text. By default, the option pane type determines how many buttons appear. For example, YES_NO_OPTION dialogs have two buttons, and YES_NO_CANCEL_OPTION dialogs have three buttons.

The following code, taken from DialogDemo.java, creates two Yes/No dialogs. The first dialog is implemented with showConfirmDialog, which uses the look-and-feel wording for the two buttons. The second dialog uses showOptionDialog so it can customize the wording. With the exception of wording changes, the dialogs are identical.

A yes/no dialog, in those words [but perhaps translated]
//default icon, custom title
int n = JOptionPane.showConfirmDialog(
    frame,
    "Would you like green eggs and ham?",
    "An Inane Question",
    JOptionPane.YES_NO_OPTION);
A yes/no dialog -- in other words
Object[] options = {"Yes, please",
                    "No way!"};
int n = JOptionPane.showOptionDialog(frame,
    "Would you like green eggs and ham?",
    "A Silly Question",
    JOptionPane.YES_NO_OPTION,
    JOptionPane.QUESTION_MESSAGE,
    null,     //do not use a custom Icon
    options,  //the titles of buttons
    options[0]); //default button title

As the previous code snippets showed, the showMessageDialog, showConfirmDialog, and showOptionDialog methods return an integer indicating the user's choice. The values for this integer are YES_OPTION, NO_OPTION, CANCEL_OPTION, OK_OPTION, and CLOSED_OPTION. Except for CLOSED_OPTION, each option corresponds to the button the user pressed. When CLOSED_OPTION is returned, it indicates that the user closed the dialog window explicitly, rather than by choosing a button inside the option pane.

Even if you change the strings that the standard dialog buttons display, the return value is still one of the pre-defined integers. For example, a YES_NO_OPTION dialog always returns one of the following values: YES_OPTION, NO_OPTION, or CLOSED_OPTION.

Getting the User's Input from a Dialog

The only form of showXxxDialog that does not return an integer is showInputDialog, which returns an Object instead. This Object is generally a String reflecting the user's choice. Here is an example of using showInputDialog to create a dialog that lets the user choose one of three strings:

An input dialog with a combo box

Object[] possibilities = {"ham", "spam", "yam"};
String s = (String)JOptionPane.showInputDialog(
                    frame,
                    "Complete the sentence:\n"
                    + "\"Green eggs and...\"",
                    "Customized Dialog",
                    JOptionPane.PLAIN_MESSAGE,
                    icon,
                    possibilities,
                    "ham");

//If a string was returned, say so.
if ((s != null) && (s.length() > 0)) {
    setLabel("Green eggs and... " + s + "!");
    return;
}

//If you're here, the return value was null/empty.
setLabel("Come on, finish the sentence!");
If you do not care to limit the user's choices, you can either use a form of the showInputDialog method that takes fewer arguments or specify null for the array of objects. In the Java look and feel, substituting null for possibilities results in a dialog that has a text field and looks like this:

An input dialog with a text field

Because the user can type anything into the text field, you might want to check the returned value and ask the user to try again if it is invalid. Another approach is to create a custom dialog that validates the user-entered data before it returns. See CustomDialog.java for an example of validating data.

If you're designing a custom dialog, you need to design your dialog's API so that you can query the dialog about what the user chose. For example, CustomDialog has a getValidatedText method that returns the text the user entered.

Stopping Automatic Dialog Closing

By default, when the user clicks a JOptionPane-created button, the dialog closes. But what if you want to check the user's answer before closing the dialog? In this case, you must implement your own property change listener so that when the user clicks a button, the dialog does not automatically close.

DialogDemo contains two dialogs that implement a property change listener. One of these dialogs is a custom modal dialog, implemented in CustomDialog, that uses JOptionPane both to get the standard icon and to get layout assistance. The other dialog, whose code is below, uses a standard Yes/No JOptionPane. Though this dialog is rather useless as written, its code is simple enough that you can use it as a template for more complex dialogs.

Besides setting the property change listener, the following code also calls the JDialog's setDefaultCloseOperation method and implements a window listener that handles the window close attempt properly. If you do not care to be notified when the user closes the window explicitly, then ignore the bold code.

final JOptionPane optionPane = new JOptionPane(
                "The only way to close this dialog is by\n"
                + "pressing one of the following buttons.\n"
                + "Do you understand?",
                JOptionPane.QUESTION_MESSAGE,
                JOptionPane.YES_NO_OPTION);

final JDialog dialog = new JDialog(frame,
                             "Click a button",
                             true);
dialog.setContentPane(optionPane);
dialog.setDefaultCloseOperation(
    JDialog.DO_NOTHING_ON_CLOSE);
dialog.addWindowListener(new WindowAdapter() {
    public void windowClosing(WindowEvent we) {
        setLabel("Thwarted user attempt to close window.");
    }
});
optionPane.addPropertyChangeListener(
    new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent e) {
            String prop = e.getPropertyName();

            if (dialog.isVisible()
             && (e.getSource() == optionPane)
             && (prop.equals(JOptionPane.VALUE_PROPERTY))) {
                //If you were going to check something
                //before closing the window, you'd do
                //it here.
                dialog.setVisible(false);
            }
        }
    });
dialog.pack();
dialog.setVisible(true);

int value = ((Integer)optionPane.getValue()).intValue();
if (value == JOptionPane.YES_OPTION) {
    setLabel("Good.");
} else if (value == JOptionPane.NO_OPTION) {
    setLabel("Try using the window decorations "
             + "to close the non-auto-closing dialog. "
             + "You can't!");
}

The Dialog API

The following tables list the commonly used JOptionPane and JDialog constructors and methods. Other methods you're likely to call are defined by the Dialog, Window and Component classes and include pack, setSize, and setVisible.

The API is listed as follows:

  • Showing Standard Modal Dialogs (using JOptionPane Class Methods)
  • Methods for Using JOptionPanes Directly
  • Frequently Used JDialog Constructors and Methods

Showing Standard Modal Dialogs (Using JOptionPane Class Methods)
Method | Purpose
static void showMessageDialog(Component, Object)
static void showMessageDialog(Component, Object, String, int)
static void showMessageDialog(Component, Object, String, int, Icon) 		Show a one-button, modal dialog that gives the user some information. The arguments specify (in order) the parent component, message, title, message type, and icon for the dialog. See Creating and Showing Simple Dialogs for a discussion of the arguments and their effects.
static int showOptionDialog(Component, Object, String, int, int, Icon, Object[], Object) | Show a customized modal dialog. The arguments specify (in order) the parent component, message, title, option type, message type, icon, options, and initial value for the dialog. See Creating and Showing Simple Dialogs for a discussion of the arguments and their effects.
static int showConfirmDialog(Component, Object)
static int showConfirmDialog(Component, Object, String, int)
static int showConfirmDialog(Component, Object, String, int, int)
static int showConfirmDialog(Component, Object, String, int, int, Icon) 		Show a modal dialog that asks the user a question. The arguments specify (in order) the parent component, message, title, option type, message type, and icon for the dialog. See Creating and Showing Simple Dialogs for a discussion of the arguments and their effects.
static String showInputDialog(Object)
static String showInputDialog(Component, Object)
static String showInputDialog(Component, Object, String, int)
static String showInputDialog(Component, Object, String, int, Icon, Object[], Object) 		Show a modal dialog that prompts the user for input. The single-argument version specifies just the message, with the parent component assumed to be null. The arguments for the other versions specify (in order) the parent component, message, title, message type, icon, options, and initial value for the dialog. See Creating and Showing Simple Dialogs for a discussion of the arguments and their effects.
static void showInternalMessageDialog(...)
static void showInternalOptionDialog(...)
static void showInternalConfirmDialog(...)
static String showInternalInputDialog(...) 		Implement a standard dialog as an internal frame. See the JOptionPane API documentation for the exact list of arguments.

Methods for Using JOptionPanes Directly
Method or Constructor Purpose
JOptionPane()
JOptionPane(Object)
JOptionPane(Object, int)
JOptionPane(Object, int, int)
JOptionPane(Object, int, int, Icon)
JOptionPane(Object, int, int, Icon, Object[])
JOptionPane(Object, int, int, Icon, Object[], Object) 		Creates a JOptionPane instance. See Creating and Showing Simple Dialogs for a discussion of the arguments and their effects.
static Frame getFrameForComponent(Component)
static JDesktopPane getDesktopPaneForComponent(Component) 		Handy JOptionPane class methods that find the frame or desktop pane, respectively, that the specified component is in.
int getMaxCharactersPerLineCount() Determines where line breaks will be automatically inserted in the option pane text. (The default is Integer.MAX_VALUE.) To use this method, you must create a JOptionPane subclass. For example, the following code results in an option pane with one word per line, due to the fact that each word in the string is 5 characters or less:
JOptionPane op = new JOptionPane("This is the text.") {
    public int getMaxCharactersPerLineCount() {
        return 5;
    }
};

Frequently Used JDialog Constructors and Methods
Method or Constructor | Purpose
JDialog()
JDialog(Dialog)
JDialog(Dialog, boolean)
JDialog(Dialog, String)
JDialog(Dialog, String, boolean)
JDialog(Dialog, String, boolean, GraphicsConfiguration)
JDialog(Frame)
JDialog(Frame, boolean)
JDialog(Frame, String)
JDialog(Frame, String, boolean)
JDialog(Frame, String, boolean, GraphicsConfiguration)
JDialog(Window owner)
JDialog(Window owner, Dialog.ModalityType modalityType)
JDialog(Window owner, String title)
JDialog(Window owner, String title, Dialog.ModalityType modalityType)
JDialog(Window owner, String title, Dialog.ModalityType modalityType, GraphicsConfiguration gc) 		Creates a JDialog instance. The Frame argument, if any, is the frame (usually a JFrame object) that the dialog depends on. Make the boolean argument true to specify a modal dialog, false or absent to specify a non-modal dialog. You can also specify the title of the dialog, using a string argument.
void setContentPane(Container)
Container getContentPane() 		Get and set the content pane, which is usually the container of all the dialog's components. See Using Top-Level Containers for more information.
void setDefaultCloseOperation(int)
int getDefaultCloseOperation() 		Get and set what happens when the user tries to close the dialog. Possible values: DISPOSE_ON_CLOSE, DO_NOTHING_ON_CLOSE, HIDE_ON_CLOSE (the default). See Responding to Window-Closing Events for more information.
void setLocationRelativeTo(Component) | Centers the dialog over the specified component.
static void setDefaultLookAndFeelDecorated(boolean)
static boolean isDefaultLookAndFeelDecorated() 		Set or get a hint as to whether the dialog's window decorations (such as borders, or widgets to close the window) should be provided by the current look and feel. Otherwise the dialog's decorations will be provided by the current window manager. See Specifying Window Decorations for more information.

Examples that Use Dialogs

This table lists examples that use JOptionPane or JDialog. To find other examples that use dialogs, see the example lists for progress bars, color choosers, and file choosers.

Example | Where Described | Notes
DialogDemo,
CustomDialog 		This section Creates many kinds of dialogs, using JOptionPane and JDialog.
Framework — Brings up a confirmation dialog when the user selects the Quit menu item.
ListDialog | How to Use BoxLayout | Implements a modal dialog containing a scrolling list and two buttons. Does not use JOptionPane, except for the utility method getFrameForComponent.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Combo Boxes
Next page: How to Use Editor Panes and Text Panes


How to Use Editor Panes and Text Panes (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Editor Panes and Text Panes
Two Swing classes support styled text: JEditorPane and its subclass JTextPane. The JEditorPane class is the foundation for Swing's styled text components and provides a mechanism through which you can add support for custom text formats. If you want unstyled text, use a text area instead.

You can see an editor pane and a text pane in use by running TextSamplerDemo. Here is a picture of the TextSamplerDemo example.

An application that provides a sample of each Swing text component

Click the Launch button to run TextSamplerDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the TextSamplerDemo Application

The TextSamplerDemo example barely begins to demonstrate the capabilities of editor panes and text panes. However, the top right editor pane illustrates a handy, easy-to-use feature: it displays uneditable help information loaded from a URL. The text pane at the lower right demonstrates that you can easily embed images and even components directly into text panes.
Note: If you need a fully-fledged help system, take a look at the JavaHelpTM system.

The Swing text API is powerful and immense, and we could devote an entire book just to using editor panes and text panes. This section introduces their capabilities, offers hints on which one you might want to use, and points to other sources of information.

  • Using an Editor Pane to Display Text From a URL
  • Editor Panes vs. Text Panes
  • An Example of Using a Text Pane
  • The Editor Pane and Text Pane API
  • Examples That Use Editor Panes and Text Panes

Using an Editor Pane to Display Text From a URL
One task that you can accomplish without knowing anything about the Swing text system is displaying text from a URL. Here is the code from TextSamplerDemo.java that creates an uneditable editor pane that displays text formatted with HTML tags.
JEditorPane editorPane = new JEditorPane();
editorPane.setEditable(false);
java.net.URL helpURL = TextSamplerDemo.class.getResource(
                                "TextSamplerDemoHelp.html");
if (helpURL != null) {
    try {
        editorPane.setPage(helpURL);
    } catch (IOException e) {
        System.err.println("Attempted to read a bad URL: " + helpURL);
    }
} else {
    System.err.println("Couldn't find file: TextSamplerDemoHelp.html");
}

//Put the editor pane in a scroll pane.
JScrollPane editorScrollPane = new JScrollPane(editorPane);
editorScrollPane.setVerticalScrollBarPolicy(
                JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
editorScrollPane.setPreferredSize(new Dimension(250, 145));
editorScrollPane.setMinimumSize(new Dimension(10, 10));
The code uses the default constructor to create the editor pane, then calls setEditable(false) so the user cannot edit the text. Next, the code creates the URL object, and calls the setPage method with it.

The setPage method opens the resource pointed to by the URL and figures out the format of the text (which is HTML in the example). If the text format is known, the editor pane initializes itself with the text found at the URL. A standard editor pane can understand plain text, HTML, and RTF. Note that the page might be loaded asynchronously, which keeps the GUI responsive but means that you should not count on the data being completely loaded after the call to setPage returns.

Editor Panes vs. Text Panes

In order to use editor panes and text panes, you need to understand the text system, which is described in Text Component Features. Several facts about editor panes and text panes are scattered throughout that section. Here we list the facts again and provide a bit more detail. The information here should help you understand the differences between editor panes and text panes, and when to use which.
  • An editor pane or a text pane can easily be loaded with text from a URL using the setPage method. The JEditorPane class also provides constructors that let you initialize an editor pane from a URL. The JTextPane class has no such constructors. See Using an Editor Pane to Display Text From a URL for an example that uses this feature to load an uneditable editor pane with HTML-formatted text.

    Be aware that the document and editor kit might change when using the setPage method. For example, if an editor pane contains plain text (the default), and you load it with HTML, the document will change to an HTMLDocument instance and the editor kit will change to an HTMLEditorKit instance. If your program uses the setPage method, make sure you adjust your code for possible changes to the pane's document and editor kit instances (re-register document listeners on the new document, and so on).

  • Editor panes, by default, know how to read, write, and edit plain, HTML, and RTF text. Text panes inherit this capability but impose certain limitations. A text pane insists that its document implement the StyledDocument interface. HTMLDocument and RTFDocument are both StyledDocuments so HTML and RTF work as expected within a text pane. If you load a text pane with plain text though, the text pane's document is not a PlainDocument as you might expect, but a DefaultStyledDocument.

  • To support a custom text format, implement an editor kit that can read, write, and edit text of that format. Then call the registerEditorKitForContentType method to register your kit with the JEditorPane class. By registering an editor kit in this way, all editor panes and text panes in your program will be able to read, write, and edit the new format. However, if the new editor kit is not a StyledEditorKit, text panes will not support the new format.

  • As mentioned previously, a text pane requires its document to implement the StyledDocument interface. The Swing text package provides a default implementation of this interface, DefaultStyledDocument, which is the document that text panes use by default. A text pane also requires that its editor kit be an instance of a StyledEditorKit (or a subclass). Be aware that the read and write methods for StyleEditorKit work with plain text.

  • Through their styled document and styled editor kit, text panes provide support for named styles and logical styles. The JTextPane class itself contains many methods for working with styles that simply call methods in its document or editor kit.

  • Through the API provided in the JTextPane class, you can embed images and components in a text pane. You can embed images in an editor pane, too, but only by including the images in an HTML or RTF file.

An Example of Using a Text Pane
Here is the code from the TextSamplerDemo example that creates and initializes a text pane.
String[] initString =
    { /* ...  fill array with initial text  ... */ };

String[] initStyles =
    { /* ...  fill array with names of styles  ... */ };

JTextPane textPane = new JTextPane();
StyledDocument doc = textPane.getStyledDocument();
addStylesToDocument(doc);

//Load the text pane with styled text.
try {
    for (int i=0; i < initString.length; i++) {
    doc.insertString(doc.getLength(), initString[i],
             doc.getStyle(initStyles[i]));
    }
} catch (BadLocationException ble) {
    System.err.println("Couldn't insert initial text into text pane.");
}
Briefly, this code hard-codes the initial text into an array and creates and hard-codes several styles — objects that represent different paragraph and character formats — into another array. Next, the code loops over the arrays, inserts the text into the text pane, and specifies the style to use for the inserted text.

Although this is an interesting example that concisely demonstrates several features of JTextPane, "real-world" programs aren't likely to initialize a text pane this way. Instead, a program would use a text pane to save a document which would then be used to initialize the text pane.

The Editor Pane and Text Pane API

This section lists some of the API related to text and editor panes. Many of the most useful methods for JEditorPane and its subclass JTextPane are inherited from the JTextComponent class. You can find the API tables for JTextComponent in The Text Component API. Also see The JComponent Class, which describes the API inherited from JComponent.

JEditorPane API for Displaying Text from a URL
Method or Constructor | Description
JEditorPane(URL)
JEditorPane(String) 		Creates an editor pane loaded with the text at the specified URL.
setPage(URL)
setPage(String) 		Loads an editor pane (or text pane) with the text at the specified URL.
URL getPage() | Gets the URL for the editor pane's (or text pane's) current page.

JTextPane API
Method or Constructor Description
JTextPane()
JTextPane(StyledDocument) 		Creates a text pane. The optional argument specifies the text pane's model.
StyledDocument getStyledDocument
setStyledDocument(StyledDocument) 		Gets or sets the text pane's model.

Examples That Use Text Panes and Editor Panes

To begin using text, you might want to run these programs and examine their code to find something similar to what you want to do.

Example | Where Described | Notes
TextSamplerDemo | Using Text Components | Uses each Swing text component.
TextComponentDemo | Text Component Features | Provides a customized text pane. Illustrates many text component features, such as undo and redo, document filters, document listeners, caret change listeners, and how to associate editing actions with menus and key strokes.
TreeDemo | How to Use Trees | Uses an editor pane to display help loaded from an HTML file.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Make Dialogs
Next page: How to Use File Choosers


How to Use File Choosers (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use File Choosers
File choosers provide a GUI for navigating the file system, and then either choosing a file or directory from a list, or entering the name of a file or directory. To display a file chooser, you usually use the JFileChooser API to show a modal dialog containing the file chooser. Another way to present a file chooser is to add an instance of JFileChooser to a container.

Note: If you intend to distribute your program as an unsigned Java™ Web Start application, then instead of using the JFileChooser API you should use the file services provided by the JNLP API. These services — FileOpenService and FileSaveService — not only provide support for choosing files in a restricted environment, but also take care of actually opening and saving them. An example of using these services is in JWSFileChooserDemo. Documentation for using the JNLP API can be found in the Java Web Start lesson.

Click the Launch button to run JWSFileChooserDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the JWSFileChooserDemo application

When working with the JWSFileChooserDemo example, be careful not to lose files that you need. Whenever you click the save button and select an existing file, this demo brings up the File Exists dialog box with a request to replace the file. Accepting the request overwrites the file.

The rest of this section discusses how to use the JFileChooser API. A JFileChooser object only presents the GUI for choosing files. Your program is responsible for doing something with the chosen file, such as opening or saving it. Refer to Basic I/O for information on how to read and write files.

The JFileChooser API makes it easy to bring up open and save dialogs. The type of look and feel determines what these standard dialogs look like and how they differ. In the Java look and feel, the save dialog looks the same as the open dialog, except for the title on the dialog's window and the text on the button that approves the operation. Here is a picture of a standard open dialog in the Java look and feel:

A standard open dialog shown in the Java look and feel

Here is a picture of an application called FileChooserDemo that brings up an open dialog and a save dialog.

A program that brings up an open or save dialog

Try this:
  1. Compile and run the example, consult the example index.
  2. Click the Open a File button. Navigate around the file chooser, choose a file, and click the dialog's Open button.
  3. Use the Save a File button to bring up a save dialog. Try to use all of the controls on the file chooser.
  4. In the source file FileChooserDemo.java, change the file selection mode to directories-only mode. (Search for DIRECTORIES_ONLY and uncomment the line that contains it.) Then compile and run the example again. You will only be able to see and select directories, not ordinary files.
Bringing up a standard open dialog requires only two lines of code:
//Create a file chooser
final JFileChooser fc = new JFileChooser();
...
//In response to a button click:
int returnVal = fc.showOpenDialog(aComponent);
The argument to the showOpenDialog method specifies the parent component for the dialog. The parent component affects the position of the dialog and the frame that the dialog depends on. For example, the Java look and feel places the dialog directly over the parent component. If the parent component is in a frame, then the dialog is dependent on that frame. This dialog disappears when the frame is minimized and reappears when the frame is maximized.

By default, a file chooser that has not been shown before displays all files in the user's home directory. You can specify the file chooser's initial directory by using one of JFileChooser's other constructors, or you can set the directory with the setCurrentDirectory method.

The call to showOpenDialog appears in the actionPerformed method of the Open a File button's action listener:

public void actionPerformed(ActionEvent e) {
    //Handle open button action.
    if (e.getSource() == openButton) {
        int returnVal = fc.showOpenDialog(FileChooserDemo.this);

        if (returnVal == JFileChooser.APPROVE_OPTION) {
            File file = fc.getSelectedFile();
            //This is where a real application would open the file.
            log.append("Opening: " + file.getName() + "." + newline);
        } else {
            log.append("Open command cancelled by user." + newline);
        }
   } ...
}
The showXxxDialog methods return an integer that indicates whether the user selected a file. Depending on how you use a file chooser, it is often sufficient to check whether the return value is APPROVE_OPTION and then not to change any other value. To get the chosen file (or directory, if you set up the file chooser to allow directory selections), call the getSelectedFile method on the file chooser. This method returns an instance of File.

The example obtains the name of the file and uses it in the log message. You can call other methods on the File object, such as getPath, isDirectory, or exists to obtain information about the file. You can also call other methods such as delete and rename to change the file in some way. Of course, you might also want to open or save the file by using one of the reader or writer classes provided by the Java platform. See Basic I/O for information about using readers and writers to read and write data to the file system.

The example program uses the same instance of the JFileChooser class to display a standard save dialog. This time the program calls showSaveDialog:

int returnVal = fc.showSaveDialog(FileChooserDemo.this);
By using the same file chooser instance to display its open and save dialogs, the program reaps the following benefits:
  • The chooser remembers the current directory between uses, so the open and save versions automatically share the same current directory.
  • You have to customize only one file chooser, and the customizations apply to both the open and save versions.
Finally, the example program has commented-out lines of code that let you change the file selection mode. For example, the following line of code makes the file chooser able to select only directories, and not files:
fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
Another possible selection mode is FILES_AND_DIRECTORIES. The default is FILES_ONLY. The following picture shows an open dialog with the file selection mode set to DIRECTORIES_ONLY. Note that, in the Java look and feel at least, only directories are visible — not files.

A file chooser in DIRECTORIES_ONLY mode

If you want to create a file chooser for a task other than opening or saving, or if you want to customize the file chooser, keep reading. We will discuss the following topics:

  • Another Example: FileChooserDemo2
  • Using a File Chooser for a Custom Task
  • Filtering the List of Files
  • Customizing the File View
  • Providing an Accessory Component
  • The File Chooser API
  • Examples that Use File Choosers

Another Example: FileChooserDemo2
Let us look at FileChooserDemo2 example, a modified version of the previous demo program that uses more of the JFileChooser API. This example uses a file chooser that has been customized in several ways. Like the original example, the user invokes a file chooser with the push of a button. Here is a picture of the file chooser:

A file chooser with various customizations

As the figure shows, this file chooser has been customized for a special task (Attach), provides a user-choosable file filter (Just Images), uses a special file view for image files, and has an accessory component that displays a thumbnail sketch of the currently selected image file.

The remainder of this section shows you the code that creates and customizes this file chooser. See the example index for links to all the files required by this example.

Using a File Chooser for a Custom Task
As you have seen, the JFileChooser class provides the showOpenDialog method for displaying an open dialog and the showSaveDialog method for displaying a save dialog.

The class has another method, showDialog, for displaying a file chooser for a custom task in a dialog. In the Java look and feel, the only difference between this dialog and the other file chooser dialogs is the title on the dialog window and the label on the approve button. Here is the code from FileChooserDemo2 that brings up the file chooser dialog for the Attach task:

JFileChooser fc = new JFileChooser();
int returnVal = fc.showDialog(FileChooserDemo2.this, "Attach");
The first argument to the showDialog method is the parent component for the dialog. The second argument is a String object that provides both the title for the dialog window and the label for the approve button.

Once again, the file chooser doesn't do anything with the selected file. The program is responsible for implementing the custom task for which the file chooser was created.

Filtering the List of Files
By default, a file chooser displays all of the files and directories that it detects, except for hidden files. A program can apply one or more file filters to a file chooser so that the chooser shows only some files. The file chooser calls the filter's accept method for each file to determine whether it should be displayed. A file filter accepts or rejects a file based on criteria such as file type, size, ownership, and so on. Filters affect the list of files displayed by the file chooser. The user can enter the name of any file even if it is not displayed.

JFileChooser supports three different kinds of filtering. The filters are checked in the order listed here. For example, an application-controlled filter sees only those files accepted by the built-in filtering.

Built-in filtering
Filtering is set up through specific method calls on a file chooser. Currently the only built-in filter available is for hidden files, such as those whose names begin with period (.) on UNIX systems. By default, hidden files are not shown. Call setFileHidingEnabled(false) to show hidden files.
Application-controlled filtering
The application determines which files are shown. Create a custom subclass of FileFilter, instantiate it, and use the instance as an argument to the setFileFilter method. The installed filter is displayed on the list of user-choosable filters. The file chooser shows only those files that the filter accepts.
User-choosable filtering
The file chooser GUI provides a list of filters that the user can choose from. When the user chooses a filter, the file chooser shows only those files accepted by that filter. FileChooserDemo2 adds a custom file filter to the list of user-choosable filters:
fc.addChoosableFileFilter(new ImageFilter());
By default, the list of user-choosable filters includes the Accept All filter, which enables the user to see all non-hidden files. This example uses the following code to disable the Accept All filter:
fc.setAcceptAllFileFilterUsed(false);
Our custom file filter is implemented in ImageFilter.java and is a subclass of FileFilter. The ImageFilter class implements the getDescription method to return "Just Images" — a string to put in the list of user-choosable filters. ImageFilter also implements the accept method so that it accepts all directories and any file that has a .png, .jpg, .jpeg, .gif, .tif, or .tiff filename extension.
public boolean accept(File f) {
    if (f.isDirectory()) {
    return true;
    }

    String extension = Utils.getExtension(f);
    if (extension != null) {
    if (extension.equals(Utils.tiff) ||
        extension.equals(Utils.tif) ||
        extension.equals(Utils.gif) ||
        extension.equals(Utils.jpeg) ||
        extension.equals(Utils.jpg) ||
        extension.equals(Utils.png)) {
            return true;
    } else {
        return false;
    }
    }

    return false;
}
By accepting all directories, this filter allows the user to navigate around the file system. If the bold lines were omitted from this method, the user would be limited to the directory with which the chooser was initialized.

The preceding code sample uses the getExtension method and several string constants from Utils.java, shown here:

public class Utils {

    public final static String jpeg = "jpeg";
    public final static String jpg = "jpg";
    public final static String gif = "gif";
    public final static String tiff = "tiff";
    public final static String tif = "tif";
    public final static String png = "png";

    /*
     * Get the extension of a file.
     */
    public static String getExtension(File f) {
        String ext = null;
        String s = f.getName();
        int i = s.lastIndexOf('.');

        if (i > 0 &&  i < s.length() - 1) {
            ext = s.substring(i+1).toLowerCase();
        }
        return ext;
    }
}

Customizing the File View
In the Java look and feel, the chooser's list shows each file's name and displays a small icon that represents whether the file is a true file or a directory. You can customize this file view by creating a custom subclass of FileView and using an instance of the class as an argument to the setFileView method. The example uses an instance of a custom class, implemented in ImageFileView.java, as the file chooser's file view.
fc.setFileView(new ImageFileView());
The ImageFileView class shows a different icon for each type of image accepted by the image filter described previously.

The ImageFileView class overrides the five abstract methods defined in the FileView as follows.

String getTypeDescription(File f)
Returns a description of the file type. Here is ImageFileView's implementation of this method:
public String getTypeDescription(File f) {
    String extension = Utils.getExtension(f);
    String type = null;

    if (extension != null) {
        if (extension.equals(Utils.jpeg) ||
            extension.equals(Utils.jpg)) {
            type = "JPEG Image";
        } else if (extension.equals(Utils.gif)){
            type = "GIF Image";
        } else if (extension.equals(Utils.tiff) ||
                   extension.equals(Utils.tif)) {
            type = "TIFF Image";
        } else if (extension.equals(Utils.png)){
            type = "PNG Image";
        }
    }
    return type;
}
Icon getIcon(File f)
Returns an icon representing the file or its type. Here is ImageFileView's implementation of this method:
public Icon getIcon(File f) {
    String extension = Utils.getExtension(f);
    Icon icon = null;

    if (extension != null) {
        if (extension.equals(Utils.jpeg) ||
            extension.equals(Utils.jpg)) {
            icon = jpgIcon;
        } else if (extension.equals(Utils.gif)) {
            icon = gifIcon;
        } else if (extension.equals(Utils.tiff) ||
                   extension.equals(Utils.tif)) {
            icon = tiffIcon;
        } else if (extension.equals(Utils.png)) {
            icon = pngIcon;
        }
    }
    return icon;
}
String getName(File f)
Returns the name of the file. Most implementations of this method should return null to indicate that the look and feel should figure it out. Another common implementation returns f.getName().

String getDescription(File f)
Returns a description of the file. The intent is to describe individual files more specifically. A common implementation of this method returns null to indicate that the look and feel should figure it out.

Boolean isTraversable(File f)
Returns whether a directory is traversable. Most implementations of this method should return null to indicate that the look and feel should figure it out. Some applications might want to prevent users from descending into a certain type of directory because it represents a compound document. The isTraversable method should never return true for a non-directory.

Providing an Accessory Component
The customized file chooser in FileChooserDemo2 has an accessory component. If the currently selected item is a PNG, JPEG, TIFF, or GIF image, the accessory component displays a thumbnail sketch of the image. Otherwise, the accessory component is empty. Aside from a previewer, probably the most common use for the accessory component is a panel with more controls on it such as checkboxes that toggle between features.

The example calls the setAccessory method to establish an instance of the ImagePreview class, implemented in ImagePreview.java, as the chooser's accessory component:

fc.setAccessory(new ImagePreview(fc));
Any object that inherits from the JComponent class can be an accessory component. The component should have a preferred size that looks good in the file chooser.

The file chooser fires a property change event when the user selects an item in the list. A program with an accessory component must register to receive these events to update the accessory component whenever the selection changes. In the example, the ImagePreview object itself registers for these events. This keeps all the code related to the accessory component together in one class.

Here is the example's implementation of the propertyChange method, which is the method called when a property change event is fired:

//where member variables are declared
File file = null;
...
public void propertyChange(PropertyChangeEvent e) {
    boolean update = false;
    String prop = e.getPropertyName();

    //If the directory changed, don't show an image.
    if (JFileChooser.DIRECTORY_CHANGED_PROPERTY.equals(prop)) {
        file = null;
        update = true;

    //If a file became selected, find out which one.
    } else if (JFileChooser.SELECTED_FILE_CHANGED_PROPERTY.equals(prop)) {
        file = (File) e.getNewValue();
        update = true;
    }

    //Update the preview accordingly.
    if (update) {
        thumbnail = null;
        if (isShowing()) {
            loadImage();
            repaint();
        }
    }
}
If SELECTED_FILE_CHANGED_PROPERTY is the property that changed, this method obtains a File object from the file chooser. The loadImage and repaint methods use the File object to load the image and repaint the accessory component.

The File Chooser API

The API for using file choosers falls into these categories:
  • Creating and Showing the File Chooser
  • Selecting Files and Directories
  • Navigating the File Chooser's List
  • Customizing the File Chooser

Creating and Showing the File Chooser
Method or Constructor Purpose
JFileChooser()
JFileChooser(File)
JFileChooser(String) 		Creates a file chooser instance. The File and String arguments, when present, provide the initial directory.
int showOpenDialog(Component)
int showSaveDialog(Component)
int showDialog(Component, String) 		Shows a modal dialog containing the file chooser. These methods return APPROVE_OPTION if the user approved the operation and CANCEL_OPTION if the user cancelled it. Another possible return value is ERROR_OPTION, which means an unanticipated error occurred.

Selecting Files and Directories
Method | Purpose
void setSelectedFile(File)
File getSelectedFile() 		Sets or obtains the currently selected file or (if directory selection has been enabled) directory.
void setSelectedFiles(File[])
File[] getSelectedFiles() 		Sets or obtains the currently selected files if the file chooser is set to allow multiple selection.
void setFileSelectionMode(int)
void getFileSelectionMode()
boolean isDirectorySelectionEnabled()
boolean isFileSelectionEnabled() 		Sets or obtains the file selection mode. Acceptable values are FILES_ONLY (the default), DIRECTORIES_ONLY, and FILES_AND_DIRECTORIES.
Interprets whether directories or files are selectable according to the current selection mode.
void setMultiSelectionEnabled(boolean)
boolean isMultiSelectionEnabled() 		Sets or interprets whether multiple files can be selected at once. By default, a user can choose only one file.
void setAcceptAllFileFilterUsed(boolean)
boolean isAcceptAllFileFilterUsed() 		Sets or obtains whether the AcceptAll file filter is used as an allowable choice in the choosable filter list; the default value is true.
Dialog createDialog(Component) | Given a parent component, creates and returns a new dialog that contains this file chooser, is dependent on the parent's frame, and is centered over the parent.

Navigating the File Chooser's List
Method | Purpose
void ensureFileIsVisible(File) | Scrolls the file chooser's list such that the indicated file is visible.
void setCurrentDirectory(File)
File getCurrentDirectory() 		Sets or obtains the directory whose files are displayed in the file chooser's list.
void changeToParentDirectory() | Changes the list to display the current directory's parent.
void rescanCurrentDirectory() | Checks the file system and updates the chooser's list.
void setDragEnabled(boolean)
boolean getDragEnabled() 		Sets or obtains the property that determines whether automatic drag handling is enabled. See Drag and Drop for more details.

Customizing the File Chooser
Method Purpose
void setAccessory(javax.swing.JComponent)
JComponent getAccessory() 		Sets or obtains the file chooser's accessory component.
void setFileFilter(FileFilter)
FileFilter getFileFilter() 		Sets or obtains the file chooser's primary file filter.
void setFileView(FileView)
FileView getFileView() 		Sets or obtains the chooser's file view.
FileFilter[] getChoosableFileFilters()
void addChoosableFileFilter(FileFilter)
boolean removeChoosableFileFilter(FileFilter)
void resetChoosableFileFilters()
FileFilter getAcceptAllFileFilter() 		Sets, obtains, or modifies the list of user-choosable file filters.
void setFileHidingEnabled(boolean)
boolean isFileHidingEnabled() 		Sets or obtains whether hidden files are displayed.
void setControlButtonsAreShown(boolean)
boolean getControlButtonsAreShown() 		Sets or obtains the property that indicates whether the Approve and Cancel buttons are shown in the file chooser. This property is true by default.

Examples That Use File Choosers

This table shows the examples that use file choosers and points to where those examples are described.

Example | Where Described | Notes
FileChooserDemo | This section | Displays an open dialog and a save dialog.
FileChooserDemo2 | This section | Uses a file chooser with custom filtering, a custom file view, and an accessory component.
DragFileDemo | Introduction to DnD | Uses a file chooser directly, without a dialog, and demonstrates dragging files.
JWSFileChooserDemo | This section | Uses the JNLP API to open and save files.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Editor Panes and Text Panes
Next page: How to Use Formatted Text Fields


How to Use Formatted Text Fields (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Formatted Text Fields
Formatted text fields provide a way for developers to specify the valid set of characters that can be typed in a text field. Specifically, the JFormattedTextField class adds a formatter and an object value to the features inherited from the JTextField class. The formatter translates the field's value into the text it displays, and the text into the field's value.

Using the formatters that Swing provides, you can set up formatted text fields to type dates and numbers in localized formats. Another kind of formatter enables you to use a character mask to specify the set of characters that can be typed at each position in the field. For example, you can specify a mask for typing phone numbers in a particular format, such as (XX) X-XX-XX-XX-XX.

If the possible values of a formatted text field have an obvious order, use a spinner instead. A spinner uses a formatted text field by default, but adds two buttons that enable the user to choose a value in a sequence.

Another alternative or adjunct to using a formatted text field is installing an input verifier on the field. A component's input verifier is called when the component nearly loses the keyboard focus. The input verifier enables you to check whether the value of the component is valid and optionally change it or stop the focus from being transferred.

This GUI uses formatted text fields to display numbers in four different formats.

A snapshot of FormattedTextFieldDemo

Try this:
  1. Click the Launch button to run FormattedTextFieldDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    2. Launches the FormattedTextFieldDemo Application

  2. Experiment with different loan amounts, annual percentage rates (APRs), and loan lengths.
    Note that as long as the text you type is valid, the Month Payment field is updated when you press Enter or move the focus out of the field that you are editing.
  3. Type invalid text such as "abcd" in the Loan Amount field and then press Enter.
    The Month Payment field remains the same. When you move the focus from the Loan Amount field, the text reverts to the field's last valid value.
  4. Type marginally valid text such as "2000abcd" in the Loan Amount field and press Enter.
    The Monthly Payment field is updated, though the Loan Amount field still displays 2000abcd. When you move the focus from the Loan Amount field, the text it displays is updated to a neatly formatted version of its value, for example, "2,000".
You can find the entire code for this program in FormattedTextFieldDemo.java. This code creates the first field.
amountField = new JFormattedTextField(amountFormat);
amountField.setValue(new Double(amount));
amountField.setColumns(10);
amountField.addPropertyChangeListener("value", this);
...
amountFormat = NumberFormat.getNumberInstance();

The constructor used to create the amountField object takes a java.text.Format argument. The Format object is used by the field's formatter to translate the field's value to text and the text to the field's value.

The remaining code sets up the amountField object. The setValue method sets the field's value property to a floating-point number represented as a Double object. The setColumns method, inherited from the JTextField class, hints about the preferred size of the field. The call to the addPropertyChangeListener method registers a listener for the value property of the field, so the program can update the Monthly Payment field whenever the user changes the loan amount.

The rest of this section covers the following topics:

  • Creating and Initializing Formatted Text Fields
  • Setting and Getting the Field's Value
  • Specifying Formats
  • Using MaskFormatter
  • Specifying Formatters and Using Formatter Factories

This section does not explain the API inherited from the JTextField class. That API is described in How to Use Text Fields.

Creating and Initializing Formatted Text Fields

The following code creates and initializes the remaining three fields in the FormattedTextFieldDemo example.

rateField = new JFormattedTextField(percentFormat);
rateField.setValue(new Double(rate));
rateField.setColumns(10);
rateField.addPropertyChangeListener("value", this);

numPeriodsField = new JFormattedTextField();
numPeriodsField.setValue(new Integer(numPeriods));
numPeriodsField.setColumns(10);
numPeriodsField.addPropertyChangeListener("value", this);

paymentField = new JFormattedTextField(paymentFormat);
paymentField.setValue(new Double(payment));
paymentField.setColumns(10);
paymentField.setEditable(false);
paymentField.setForeground(Color.red);

...
percentFormat = NumberFormat.getNumberInstance();
percentFormat.setMinimumFractionDigits(2);

paymentFormat = NumberFormat.getCurrencyInstance();

The code for setting up the rateField object is almost identical to the code listed previously for other fields. The only difference is that the format is slightly different, thanks to the code percentFormat.setMinimumFractionDigits(2).

The code that creates the numPeriodsField object does not explicitly set a format or formatter. Instead, it sets the value to an Integer and enables the field to use the default formatter for Integer objects. The code did not do this in the previous two fields because the default formatter is not being used for Double objects. The result was not what was needed. How to specify formats and formatters is covered later in this section.

The payment field is different from the other fields because it is uneditable, uses a different color for its text, and does not have a property change listener. Otherwise, it is identical to the other fields. We could have chosen to use a text field or label instead. Whatever the component, we could still use the paymentFormat method to parse the payment amount into the text to be displayed.

Setting and Getting the Field's Value

Keep the following in mind when using a formatted text field:

A formatted text field's text and its value are two different properties, and the value often lags behind the text.

The text property is defined by the JTextField class. This property always reflects what the field displays. The value property, defined by the JFormattedTextField class, might not reflect the latest text displayed in the field. While the user is typing, the text property changes, but the value property does not change until the changes are committed.

To be more precise, the value of a formatted text field can be set by using either the setValue method or the commitEdit method. The setValue method sets the value to the specified argument. The argument can technically be any Object, but the formatter needs to be able to convert it into a string. Otherwise, the text field does not display any substantive information.

The commitEdit method sets the value to whatever object the formatter determines is represented by the field's text. The commitEdit method is automatically called when either of the following happens:

  • When the user presses Enter while the field has the focus.
  • By default, when the field loses the focus, for example, when the user presses the Tab key to change the focus to another component. You can use the setFocusLostBehavior method to specify a different outcome when the field loses the focus.
Note: Some formatters might update the value constantly, rendering the loss of focus meaningless, as the value is always the same as what the text specifies.

When you set the value of a formatted text field, the field's text is updated to reflect the value. Exactly how the value is represented as text depends on the field's formatter.

Note that although the JFormattedTextField class inherits the setText method from the JTextField class, you do not usually call the setText method on a formatted text field. If you do, the field's display changes accordingly but the value is not updated (unless the field's formatter updates it constantly).

To obtain a formatted text field's current value, use the getValue method. If necessary, you can ensure that the value reflects the text by calling the commitEdit method before getValue. Because the getValue method returns an Object, you need to cast it to the type used for your field's value. For example:

Date enteredDate = (Date)dateField.getValue();

To detect changes in a formatted text field's value, you can register a property change listener on the formatted text field to listen for changes to the "value" property. The property change listener is taken from the FormattedTextFieldDemo example:

//The property change listener is registered on each
//field using code like this:
//    someField.addPropertyChangeListener("value", this);

/** Called when a field's "value" property changes. */
public void propertyChange(PropertyChangeEvent e) {
    Object source = e.getSource();
    if (source == amountField) {
        amount = ((Number)amountField.getValue()).doubleValue();
    } else if (source == rateField) {
        rate = ((Number)rateField.getValue()).doubleValue();
    } else if (source == numPeriodsField) {
        numPeriods = ((Number)numPeriodsField.getValue()).intValue();
    }

    double payment = computePayment(amount, rate, numPeriods);
    paymentField.setValue(new Double(payment));
}

Specifying Formats

The Format class provides a way to format locale-sensitive information such as dates and numbers. Formatters that descend from the InternationalFormatter class, such as the DateFormatter and NumberFormatter classes, use Format objects to translate between the field's text and value. You can obtain a Format object by calling one of the factory methods in the DateFormat or NumberFormat classes, or by using one of the SimpleDateFormat constructors.
Note: A third commonly used formatter class, MaskFormatter, does not descend from the InternationalFormatter class and does not use formats. The MaskFormatter is discussed in Using MaskFormatter.

You can customize certain format aspects when you create the Format object, and others through a format-specific API. For example, DecimalFormat objects, which inherit from NumberFormat and are often returned by its factory methods, can be customized by using the setMaximumFractionDigits and setNegativePrefix methods. For information about using Format objects, see the Formatting lesson of the Internationalization trail.

The easiest way to associate a customized format with a formatted text field is to create the field by using the JFormattedTextField constructor that takes a Format as an argument. You can see this association in the previous code examples that create amountField and rateField objects.

Using MaskFormatter

The MaskFormatter class implements a formatter that specifies exactly which characters are valid in each position of the field's text. For example, the following code creates a MaskFormatter that lets the user to type a five-digit zip code:
zipField = new JFormattedTextField(
                    createFormatter("#####"));
...
protected MaskFormatter createFormatter(String s) {
    MaskFormatter formatter = null;
    try {
        formatter = new MaskFormatter(s);
    } catch (java.text.ParseException exc) {
        System.err.println("formatter is bad: " + exc.getMessage());
        System.exit(-1);
    }
    return formatter;
}
You can try out the results of the preceding code by running TextInputDemo. Click the Launch button to run TextInputDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the TextInputDemo Application

The program's GUI is displayed.

A snapshot of TextInputDemo

The following table shows the characters that you can use in the formatting mask:

Character | Description
# Any valid number (Character.isDigit).
'
(single quote) 		Escape character, used to escape any of the special formatting characters.
U | Any character (Character.isLetter). All lowercase letters are mapped to uppercase.
L | Any character (Character.isLetter). All uppercase letters are mapped to lowercase.
A | Any character or number (Character.isLetter or Character.isDigit).
? Any character (Character.isLetter).
* Anything.
H | Any hex character (0-9, a-f or A-F).

Specifying Formatters and Using Formatter Factories

When specifying formatters, keep in mind that each formatter object can be used by at most one formatted text field at a time. Each field should have at least one formatter associated with it, of which exactly one is used at any time.

You can specify the formatters to be used by a formatted text field in several ways:

  • Use the JFormattedTextField constructor that takes a Format argument.
    A formatter for the field is automatically created that uses the specified format.

  • Use the JFormattedTextField constructor that takes a JFormattedTextField.AbstractFormatter argument.
    The specified formatter is used for the field.

  • Set the value of a formatted text field that has no format, formatter, or formatter factory specified.
    A formatter is assigned to the field by the default formatter factory, using the type of the field's value as a guide. If the value is a Date, the formatter is a DateFormatter. If the value is a Number, the formatter is a NumberFormatter. Other types result in an instance of DefaultFormatter.

  • Make the formatted text field use a formatter factory that returns customized formatter objects.
    This is the most flexible approach. It is useful when you want to associate more than one formatter with a field or add a new kind of formatter to be used for multiple fields. An example of the former use is a field that interprets the user typing in a certain way but displays the value (when the user is not typing) in another way. An example of the latter use is several fields with custom class values, for example, PhoneNumber. You can set up the fields to use a formatter factory that returns specialized formatters for phone numbers.

You can set a field's formatter factory either by creating the field using a constructor that takes a formatter factory argument, or by calling the setFormatterFactory method on the field. To create a formatter factory, you can often use an instance of DefaultFormatterFactory class. A DefaultFormatterFactory object enables you to specify the formatters returned when a value is being edited, is not being edited, or has a null value.

The following figures show an application based on the FormattedTextFieldDemo example that uses formatter factories to set multiple editors for the Loan Amount and APR fields. While the user is editing the Loan Amount, the $ character is not used so that the user is not forced to type it. Similarly, while the user is editing the APR field, the % character is not required.

Click the Launch button to run FormatterFactoryDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the FormatterFactoryDemo Application

FormatterFactoryDemo, with amount field being edited FormatterFactoryDemo, with no custom editors installed

The following code that creates the formatters and sets them up by using instances of the DefaultFormatterFactory class:

private double rate = .075;  //7.5 %
...
amountField = new JFormattedTextField(
                    new DefaultFormatterFactory(
                        new NumberFormatter(amountDisplayFormat),
                        new NumberFormatter(amountDisplayFormat),
                        new NumberFormatter(amountEditFormat)));
...
NumberFormatter percentEditFormatter =
        new NumberFormatter(percentEditFormat) {
    public String valueToString(Object o)
          throws ParseException {
        Number number = (Number)o;
        if (number != null) {
            double d = number.doubleValue() * 100.0;
            number = new Double(d);
        }
        return super.valueToString(number);
    }
    public Object stringToValue(String s)
           throws ParseException {
        Number number = (Number)super.stringToValue(s);
        if (number != null) {
            double d = number.doubleValue() / 100.0;
            number = new Double(d);
        }
        return number;
    }
};
rateField = new JFormattedTextField(
                     new DefaultFormatterFactory(
                        new NumberFormatter(percentDisplayFormat),
                        new NumberFormatter(percentDisplayFormat),
                        percentEditFormatter));
...
amountDisplayFormat = NumberFormat.getCurrencyInstance();
amountDisplayFormat.setMinimumFractionDigits(0);
amountEditFormat = NumberFormat.getNumberInstance();

percentDisplayFormat = NumberFormat.getPercentInstance();
percentDisplayFormat.setMinimumFractionDigits(2);
percentEditFormat = NumberFormat.getNumberInstance();
percentEditFormat.setMinimumFractionDigits(2);
The boldface code highlights the calls to DefaultFormatterFactory constructors. The first argument to the constructor specifies the default formatter to use for the formatted text field. The second argument specifies the display formatter, which is used when the field does not have the focus. The third argument specifies the edit formatter, which is used when the field has the focus. The code does not use a fourth argument, but if it did, the fourth argument would specify the null formatter, which is used when the field's value is null. Because no null formatter is specified, the default formatter is used when the value is null.

The code customizes the formatter that uses percentEditFormat by creating a subclass of the NumberFormatter class. This subclass overrides the valueToString and stringToValue methods of NumberFormatter so that they convert the displayed number to the value actually used in calculations, and convert the value to a number. Specifically, the displayed number is 100 times the actual value. The reason is that the percent format used by the display formatter automatically displays the text as 100 times the value, so the corresponding editor formatter must display the text at the same value. The FormattedTextFieldDemo example does not need to take care of this conversion because this demo uses only one format for both display and editing.

You can find the code for the entire program in FormatterFactoryDemo.java.

Formatted Text Field API

The following tables list some of the commonly used APIs for using formatted text fields.
  • Classes Related to Formatted Text Fields
  • JFormattedTextField Methods
  • DefaultFormatter Options

Classes Related to Formatted Text Fields
Class or Interface | Purpose
JFormattedTextField | Subclass of JTextField that supports formatting arbitrary values.
JFormattedTextField.AbstractFormatter | The superclass of all formatters for JFormattedTextField. A formatter enforces editing policies and navigation policies, handles string-to-object conversions, and manipulates the JFormattedTextField as necessary to enforce the desired policy.
JFormattedTextField.AbstractFormatterFactory | The superclass of all formatter factories. Each JFormattedTextField uses a formatter factory to obtain the formatter that best corresponds to the text field's state.
DefaultFormatterFactory | The formatter factory normally used. Provides formatters based on details such as the passed-in parameters and focus state.
DefaultFormatter | Subclass of JFormattedTextField.AbstractFormatter that formats arbitrary objects by using the toString method.
MaskFormatter | Subclass of DefaultFormatter that formats and edits strings using a specified character mask. (For example, seven-digit phone numbers can be specified by using "###-####".)
InternationalFormatter | Subclass of DefaultFormatter that uses an instance of java.text.Format to handle conversion to and from a String.
NumberFormatter | Subclass of InternationalFormatter that supports number formats by using an instance of NumberFormat.
DateFormatter | Subclass of InternationalFormatter that supports date formats by using an instance of DateFormat.

JFormattedTextField Methods
Method or Constructor | Purpose
JFormattedTextField()
JFormattedTextField(Object)
JFormattedTextField(Format)
JFormattedTextField(AbstractFormatter)
JFormattedTextField(AbstractFormatterFactory)
JFormattedTextField(AbstractFormatterFactory, Object) 		Creates a new formatted text field. The Object argument, if present, specifies the initial value of the field and causes an appropriate formatter factory to be created. The Format or AbstractFormatter argument specifies the format or formatter to be used for the field, and causes an appropriate formatter factory to be created. The AbstractFormatterFactory argument specifies the formatter factory to be used, which determines which formatters are used for the field.
void setValue(Object)
Object getValue() 		Sets or obtains the value of the formatted text field. You must cast the return type based on how the JFormattedTextField has been configured. If the formatter has not been set yet, calling setValue sets the formatter to one returned by the field's formatter factory.
void setFormatterFactory(AbstractFormatterFactory) | Sets the object that determines the formatters used for the formatted text field. The object is often an instance of the DefaultFormatterFactory class.
AbstractFormatter getFormatter() | Obtains the formatter of the formatted text field. The formatter is often an instance of the DefaultFormatter class.
void setFocusLostBehavior(int) | Specifies the outcome of a field losing the focus. Possible values are defined in JFormattedTextField as COMMIT_OR_REVERT (the default), COMMIT (commit if valid, otherwise leave everything the same), PERSIST (do nothing), and REVERT (change the text to reflect the value).
void commitEdit() | Sets the value to the object represented by the field's text, as determined by the field's formatter. If the text is invalid, the value remains the same and a ParseException is thrown.
boolean isEditValid() | Returns true if the formatter considers the current text to be valid, as determined by the field's formatter.

DefaultFormatter Options
Method Purpose
void setCommitsOnValidEdit(boolean)
boolean getCommitsOnValidEdit() 		Sets or obtains values when edits are pushed back to the JFormattedTextField. If true, commitEdit is called after every valid edit. This property is false by default.
void setOverwriteMode(boolean)
boolean getOverwriteMode() 		Sets or obtains the behavior when inserting characters. If true, new characters overwrite existing characters in the model as they are inserted. The default value of this property is true in DefaultFormatter (and thus in MaskFormatter) and false in InternationalFormatter (and thus in DateFormatter and NumberFormatter).
void setAllowsInvalid(boolean)
boolean getAllowsInvalid() 		Sets or interprets whether the value being edited is allowed to be invalid for a length of time. It is often convenient to enable the user to type invalid values until the commitEdit method is attempted. DefaultFormatter initializes this property to true. Of the standard Swing formatters, only MaskFormatter sets this property to false.

Examples That Use Formatted Text Fields

This table lists examples that use formatted text fields and points to where those examples are described.

Example | Where Described | Notes
FormattedTextFieldDemo | This section | Uses four formatted text fields.
SpinnerDemo | How to Use Spinners | Customizes the appearance of the formatted text fields used by two spinners.
SliderDemo3 | How to Use Sliders | Pairs a formatted text field with a slider to enable an integer value to be edited.
Converter | Using Models | Each ConversionPanel pairs a formatted text field with a slider.
TextInputDemo | This section | Shows how to use text fields, spinners, and formatted text fields together, and demonstrates how to use MaskFormatter. Includes code for selecting the text of the field that has just received the focus.
FormatterFactoryDemo | This section | A variation on FormattedTextFieldDemo that uses formatter factories to specify multiple formatters for two formatted text fields.
RegexFormatter | Regular Expression Based AbstractFormatter (in The Swing Connection | A regular expression formatter that includes source code and information about how it was implemented.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use File Choosers
Next page: How to Make Frames (Main Windows)


How to Make Frames (Main Windows) (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Make Frames (Main Windows)

A Frame is a top-level window with a title and a border. The size of the frame includes any area designated for the border. The dimensions of the border area may be obtained using the getInsets method. Since the border area is included in the overall size of the frame, the border effectively obscures a portion of the frame, constraining the area available for rendering and/or displaying subcomponents to the rectangle which has an upper-left corner location of (insets.left, insets.top), and has a size of width - (insets.left + insets.right) by height - (insets.top + insets.bottom).

A frame, implemented as an instance of the JFrame class, is a window that has decorations such as a border, a title, and supports button components that close or iconify the window. Applications with a GUI usually include at least one frame. Applets sometimes use frames, as well.

To make a window that is dependent on another window — disappearing when the other window is iconified, for example — use a dialog instead of frame.. To make a window that appears within another window, use an internal frame.

Creating and Showing Frames

Here is a picture of the extremely plain window created by the FrameDemo demonstration application. You can find the source code in FrameDemo.java. You can run FrameDemo ( download JDK 6).

A very boring frame

The following FrameDemo code shows how to create and set up a frame.

//1. Create the frame.
JFrame frame = new JFrame("FrameDemo");

//2. Optional: What happens when the frame closes?
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

//3. Create components and put them in the frame.
//...create emptyLabel...
frame.getContentPane().add(emptyLabel, BorderLayout.CENTER);

//4. Size the frame.
frame.pack();

//5. Show it.
frame.setVisible(true);
Here are some details about the code:

  1. The first line of code creates a frame using a constructor that lets you set the frame title. The other frequently used JFrame constructor is the no-argument constructor.

  2. Next the code specifies what happens when your user closes the frame. The EXIT_ON_CLOSE operation exits the program when your user closes the frame. This behavior is appropriate for this program because the program has only one frame, and closing the frame makes the program useless.

    See Responding to Window-Closing Events for more information.

  3. The next bit of code adds a blank label to the frame content pane. If you're not already familiar with content panes and how to add components to them, please read Adding Components to the Content Pane.

    For frames that have menus, you'd typically add the menu bar to the frame here using the setJMenuBar method. See How to Use Menus for details.

  4. The pack method sizes the frame so that all its contents are at or above their preferred sizes. An alternative to pack is to establish a frame size explicitly by calling setSize or setBounds (which also sets the frame location). In general, using pack is preferable to calling setSize, since pack leaves the frame layout manager in charge of the frame size, and layout managers are good at adjusting to platform dependencies and other factors that affect component size.

    This example does not set the frame location, but it is easy to do so using either the setLocationRelativeTo or setLocation method. For example, the following code centers a frame onscreen:

    frame.setLocationRelativeTo(null);

  5. Calling setVisible(true) makes the frame appear onscreen. Sometimes you might see the show method used instead. The two usages are equivalent, but we use setVisible(true) for consistency's sake.

Specifying Window Decorations

By default, window decorations are supplied by the native window system. However, you can request that the look-and-feel provide the decorations for a frame. You can also specify that the frame have no window decorations at all, a feature that can be used on its own, or to provide your own decorations, or with full-screen exclusive mode.

Besides specifying who provides the window decorations, you can also specify which icon is used to represent the window. Exactly how this icon is used depends on the window system or look and feel that provides the window decorations. If the window system supports minimization, then the icon is used to represent the minimized window. Most window systems or look and feels also display the icon in the window decorations. A typical icon size is 16x16 pixels, but some window systems use other sizes.

The following snapshots show three frames that are identical except for their window decorations. As you can tell by the appearance of the button in each frame, all three use the Java look and feel. The first uses decorations provided by the window system, which happen to be Microsoft Windows, but could as easily be any other system running the Java platform.The second and third use window decorations provided by the Java look and feel. The third frame uses Java look and feel window decorations, but has a custom icon.

A frame with decorations provided by the window system | A frame with decorations provided by the look and feel | A frame with a custom icon
Window decorations provided by the look and feel | Window decorations provided by the window system | Custom icon; window decorations provided by the look and feel

Here is an example of creating a frame with a custom icon and with window decorations provided by the look and feel:

//Ask for window decorations provided by the look and feel.
JFrame.setDefaultLookAndFeelDecorated(true);

//Create the frame.
JFrame frame = new JFrame("A window");

//Set the frame icon to an image loaded from a file.
frame.setIconImage(new ImageIcon(imgURL).getImage());

As the preceding code snippet implies, you must invoke the setDefaultLookAndFeelDecorated method before creating the frame whose decorations you wish to affect. The value you set with setDefaultLookAndFeelDecorated is used for all subsequently created JFrames. You can switch back to using window system decorations by invoking JFrame.setDefaultLookAndFeelDecorated(false). Some look and feels might not support window decorations; in this case, the window system decorations are used.

The full source code for the application that creates the frames pictured above is in FrameDemo2.java. Besides showing how to choose window decorations, FrameDemo2 also shows how to disable all window decorations and gives an example of positioning windows. It includes two methods that create the Image objects used as icons — one is loaded from a file, and the other is painted from scratch.

Try this::
  1. Click the Launch button to run the Frame Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the FrameDemo2 example

  2. Bring up two windows, both with look-and-feel-provided decorations, but with different icons.
    The Java look and feel displays the icons in its window decorations. Depending on your window system, the icon may be used elsewhere to represent the window, especially when the window is minimized.
  3. Bring up one or more windows with window system decorations.
    See if your window system treats these icons differently.
  4. Bring up one or more windows with no window decorations.
    Play with the various types of windows to see how the window decorations, window system, and frame icons interact.

Responding to Window-Closing Events

By default, when the user closes a frame onscreen, the frame is hidden. Although invisible, the frame still exists and the program can make it visible again. If you want different behavior, then you need to either register a window listener that handles window-closing events, or you need to specify default close behavior using the setDefaultCloseOperation method. You can even do both.

The argument to setDefaultCloseOperation must be one of the following values, the first three of which are defined in the WindowConstants interface (implemented by JFrame, JInternalPane, and JDialog):

DO_NOTHING_ON_CLOSE
Do not do anything when the user requests that the window close. Instead, the program should probably use a window listener that performs some other action in its windowClosing method.
HIDE_ON_CLOSE (the default for JDialog and JFrame)
Hide the window when the user closes it. This removes the window from the screen but leaves it displayable.
DISPOSE_ON_CLOSE (the default for JInternalFrame)
Hide and dispose of the window when the user closes it. This removes the window from the screen and frees up any resources used by it.
EXIT_ON_CLOSE (defined in the JFrame class)
Exit the application, using System.exit(0). This is recommended for applications only. If used within an applet, a SecurityException may be thrown.
Note: DISPOSE_ON_CLOSE can have results similar to EXIT_ON_CLOSE if only one window is onscreen. More precisely, when the last displayable window within the Java virtual machine (VM) is disposed of, the VM may terminate. See AWT Threading Issues for details.
The default close operation is executed after any window listeners handle the window-closing event. So, for example, assume that you specify that the default close operation is to dispose of a frame. You also implement a window listener that tests whether the frame is the last one visible and, if so, saves some data and exits the application. Under these conditions, when the user closes a frame, the window listener will be called first. If it does not exit the application, then the default close operation — disposing of the frame — will then be performed.

For more information about handling window-closing events, see How to Write Window Listeners. Besides handling window-closing events, window listeners can also react to other window state changes, such as iconification and activation.

The Frame API

The following tables list the commonly used JFrame constructors and methods. Other methods you might want to call are defined by the java.awt.Frame, java.awt.Window, and java.awt.Component classes, from which JFrame descends.

Because each JFrame object has a root pane, frames have support for interposing input and painting behavior in front of the frame children, placing children on different "layers", and for Swing menu bars. These topics are introduced in Using Top-Level Containers and explained in detail in How to Use Root Panes.

The API for using frames falls into these categories:

  • Creating and Setting Up a Frame
  • Setting the Window Size and Location
  • Methods Related to the Root Pane

Creating and Setting Up a Frame
Method or Constructor Purpose
JFrame()
JFrame(String) 		Create a frame that is initially invisible. The String argument provides a title for the frame. To make the frame visible, invoke setVisible(true) on it.
void setDefaultCloseOperation(int)
int getDefaultCloseOperation() 		Set or get the operation that occurs when the user pushes the close button on this frame. Possible choices are:
  • DO_NOTHING_ON_CLOSE
  • HIDE_ON_CLOSE
  • DISPOSE_ON_CLOSE
  • EXIT_ON_CLOSE
The first three constants are defined in the WindowConstants interface, which JFrame implements. The EXIT_ON_CLOSE constant is defined in the JFrame class.
void setIconImage(Image)
Image getIconImage()
(in Frame) 		Set or get the icon that represents the frame. Note that the argument is a java.awt.Image object, not a javax.swing.ImageIcon (or any other javax.swing.Icon implementation).
void setTitle(String)
String getTitle()
(in Frame) 		Set or get the frame title.
void setUndecorated(boolean)
boolean isUndecorated()
(in Frame) 		Set or get whether this frame should be decorated. Works only if the frame is not yet displayable (has not been packed or shown). Typically used with full-screen exclusive mode or to enable custom window decorations.
static void setDefaultLookAndFeelDecorated(boolean)
static boolean isDefaultLookAndFeelDecorated() 		Determine whether subsequently created JFrames should have their Window decorations (such as borders, and widgets for closing the window) provided by the current look-and-feel. Note that this is only a hint, as some look and feels may not support this feature.

Setting the Window Size and Location
Method Purpose
void pack()
(in Window) 		Size the window so that all its contents are at or above their preferred sizes.
void setSize(int, int)
void setSize(Dimension)
Dimension getSize()
(in Component) 		Set or get the total size of the window. The integer arguments to setSize specify the width and height, respectively.
void setBounds(int, int, int, int)
void setBounds(Rectangle)
Rectangle getBounds()
(in Component) 		Set or get the size and position of the window. For the integer version of setBounds, the window upper left corner is at the x, y location specified by the first two arguments, and has the width and height specified by the last two arguments.
void setLocation(int, int)
Point getLocation()
(in Component) 		Set or get the location of the upper left corner of the window. The parameters are the x and y values, respectively.
void setLocationRelativeTo(Component)
(in Window) 		Position the window so that it is centered over the specified component. If the argument is null, the window is centered onscreen. To properly center the window, you should invoke this method after the window size has been set.

Methods Related to the Root Pane
Method Purpose
void setContentPane(Container)
Container getContentPane() 		Set or get the frame content pane. The content pane contains the visible GUI components within the frame.
JRootPane createRootPane()
void setRootPane(JRootPane)
JRootPane getRootPane() 		Create, set, or get the frame root pane. The root pane manages the interior of the frame including the content pane, the glass pane, and so on.
void setJMenuBar(JMenuBar)
JMenuBar getJMenuBar() 		Set or get the frame menu bar to manage a set of menus for the frame.
void setGlassPane(Component)
Component getGlassPane() 		Set or get the frame glass pane. You can use the glass pane to intercept mouse events or paint on top of your program GUI.
void setLayeredPane(JLayeredPane)
JLayeredPane getLayeredPane() 		Set or get the frame layered pane. You can use the frame layered pane to put components on top of or behind other components.

Examples that Use Frames

All of the standalone applications in this trail use JFrame. The following table lists a few and tells you where each is discussed.

Example | Where Described | Notes
FrameDemo | The Example Explained | Displays a basic frame with one component.
FrameDemo2 | Specifying Window Decorations | Lets you create frames with various window decorations.
Framework — A study in creating and destroying windows, in implementing a menu bar, and in exiting an application.
LayeredPaneDemo | How to Use Layered Panes | Illustrates how to use a layered pane (but not the frame layered pane).
GlassPaneDemo | The Glass Pane | Illustrates the use of a frame glass pane.
MenuDemo | How to Use Menus | Shows how to put a JMenuBar in a JFrame.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Formatted Text Fields
Next page: How to Use Internal Frames


How to Use Internal Frames (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Internal Frames
With the JInternalFrame class you can display a JFrame-like window within another window. Usually, you add internal frames to a desktop pane. The desktop pane, in turn, might be used as the content pane of a JFrame. The desktop pane is an instance of JDesktopPane, which is a subclass of JLayeredPane that has added API for managing multiple overlapping internal frames.

You should consider carefully whether to base your program's GUI around frames or internal frames. Switching from internal frames to frames or vice versa is not necessarily a simple task. By experimenting with both frames and internal frames, you can get an idea of the tradeoffs involved in choosing one over the other.

Here is a picture of an application that has two internal frames (one of which is iconified) inside a regular frame:

InternalFrameDemo has multiple internal frames, managed by a desktop pane

Try this:
  1. Click the Launch button to run InternalFrameDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.
    Launches the InternalFrameDemo example

  2. Create new internal frames using the Create item in the Document menu.
    Each internal frame comes up 30 pixels lower and to the right of the place where the previous internal frame first appeared. This functionality is implemented in the MyInternalFrame class, which is the custom subclass of JInternalFrame.

The following code, taken from InternalFrameDemo.java, creates the desktop and internal frames in the previous example.

...//In the constructor of InternalFrameDemo, a JFrame subclass:
    desktop = new JDesktopPane();
    createFrame(); //Create first window
    setContentPane(desktop);
    ...
    //Make dragging a little faster but perhaps uglier.
    desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);
...
protected void createFrame() {
    MyInternalFrame frame = new MyInternalFrame();
    frame.setVisible(true);
    desktop.add(frame);
    try {
        frame.setSelected(true);
    } catch (java.beans.PropertyVetoException e) {}
}

...//In the constructor of MyInternalFrame, a JInternalFrame subclass:
static int openFrameCount = 0;
static final int xOffset = 30, yOffset = 30;

public MyInternalFrame() {
    super("Document #" + (++openFrameCount),
          true, //resizable
          true, //closable
          true, //maximizable
          true);//iconifiable
    //...Create the GUI and put it in the window...
    //...Then set the window size or call pack...
    ...
    //Set the window's location.
    setLocation(xOffset*openFrameCount, yOffset*openFrameCount);
}

Internal Frames vs. Regular Frames

The code for using internal frames is similar in many ways to the code for using regular Swing frames. Because internal frames have root panes, setting up the GUI for a JInternalFrame is very similar to setting up the GUI for a JFrame. JInternalFrame also provides other API, such as pack, that makes it similar to JFrame.
Note: Just as for a regular frame, you must invoke setVisible(true) or show() on an internal frame to display it. The internal frame does not appear until you explicitly make it visible.

Internal frames are not windows or top-level containers, however, which makes them different from frames. For example, you must add an internal frame to a container (usually a JDesktopPane); an internal frame cannot be the root of a containment hierarchy. Also, internal frames do not generate window events. Instead, the user actions that would cause a frame to fire window events cause an internal frame to fire internal frame events.

Because internal frames are implemented with platform-independent code, they add some features that frames cannot give you. One such feature is that internal frames give you more control over their state and capabilities than frames do. You can programatically iconify or maximize an internal frame. You can also specify what icon goes in the internal frame's title bar. You can even specify whether the internal frame has the window decorations to support resizing, iconifying, closing, and maximizing.

Another feature is that internal frames are designed to work within desktop panes. The JInternalFrame API contains methods such as moveToFront that work only if the internal frame's container is a layered pane such as a JDesktopPane.

Rules of Using Internal Frames

If you have built any programs using JFrame and the other Swing components, then you already know a lot about how to use internal frames. The following list summarizes the rules for using internal frames. For additional information, see How to Make Frames and The JComponent Class.
You must set the size of the internal frame.
If you do not set the size of the internal frame, it will have zero size and thus never be visible. You can set the size using one of the following methods: setSize, pack, or setBounds.
As a rule, you should set the location of the internal frame.
If you do not set the location of the internal frame, it will come up at 0,0 (the upper left of its container). You can use the setLocation or setBounds method to specify the upper left point of the internal frame, relative to its container.
To add components to an internal frame, you add them to the internal frame's content pane.
This is exactly like the JFrame situation. See Adding Components to the Content Pane for details.
Dialogs that are internal frames should be implemented using JOptionPane or JInternalFrame, not JDialog.
To create a simple dialog, you can use the JOptionPane showInternalXxxDialog methods, as described in How to Make Dialogs.
You must add an internal frame to a container.
If you do not add the internal frame to a container (usually a JDesktopPane), the internal frame will not appear.
You need to call show or setVisible on internal frames.
Internal frames are invisible by default. You must invoke setVisible(true) or show() to make them visible.
Internal frames fire internal frame events, not window events.
Handling internal frame events is almost identical to handling window events. See How to Write an Internal Frame Listener for more information.
Performance tip: When a desktop has many internal frames, the user might notice that moving them seems slow. Outline dragging is one way to avoid this problem. With outline dragging, only the outline of the internal frame is painted at the current mouse position while the internal frame's being dragged. The internal frame's innards are not repainted at a new position until dragging stops. The default behavior (called live dragging) is to reposition and repaint some or all of internal frame continuously while it is being moved; this can be slow if the desktop has many internal frames.

Use the JDesktopPane method setDragMode* to specify outline dragging. For example:

desktop.setDragMode(JDesktopPane.OUTLINE_DRAG_MODE);

The Internal Frame API

The following tables list the commonly used JInternalFrame constructors and methods, as well as a few methods that JDesktopPane provides. Besides the API listed in this section, JInternalFrame inherits useful API from its superclasses, JComponent, Component, and Container. See The JComponent Class for lists of methods from those classes.

Like JInternalFrame, JDesktopPane descends from JComponent, and thus provides the methods described in The JComponent Class. Because JDesktopPane extends JLayeredPane, it also supports the methods described in The Layered Pane API.

The API for using internal frames falls into these categories:

  • Creating the internal frame
  • Adding components to the internal frame
  • Specifying the internal frame's visibility, size, and location
  • Performing window operations on the internal frame
  • Controlling window decorations and capabilities
  • Using the JDesktopPane API

Creating the Internal Frame
Constructor or Method Purpose
JInternalFrame()
JInternalFrame(String)
JInternalFrame(String, boolean)
JInternalFrame(String, boolean, boolean)
JInternalFrame(String, boolean, boolean, boolean)
JInternalFrame(String, boolean, boolean, boolean, boolean) 		Create a JInternalFrame instance. The first argument specifies the title (if any) to be displayed by the internal frame. The rest of the arguments specify whether the internal frame should contain decorations allowing the user to resize, close, maximize, and iconify the internal frame (specified in that order). The default value for each boolean argument is false, which means that the operation is not allowed.
static int showInternalConfirmDialog(Component, Object)
static String showInternalInputDialog(Component, Object)
static Object showInternalMessageDialog(Component, Object)
static int showInternalOptionDialog(Component, Object, String, int, int, Icon, Object[], Object) 		Create a JInternalFrame that simulates a dialog. See How to Make Dialogs for details.

Adding Components to the Internal Frame
Method Purpose
void setContentPane(Container)
Container getContentPane() 		Set or get the internal frame's content pane, which generally contains all of the internal frame's GUI, with the exception of the menu bar and window decorations.
void setJMenuBar(JMenuBar)
JMenuBar getJMenuBar() 		Set or get the internal frame's menu bar.
void setLayeredPane(JLayeredPane)
JLayeredPane getLayeredPane() 		Set or get the internal frame's layered pane.

Specifying the Internal Frame's Visibility, Size, and Location
Method | Purpose
void setVisible(boolean) | Make the internal frame visible (if true) or invisible (if false). You should invoke setVisible(true) on each JInternalFrame before adding it to its container. (Inherited from Component).
void pack() | Size the internal frame so that its components are at their preferred sizes.
void setLocation(Point)
void setLocation(int, int) 		Set the position of the internal frame. (Inherited from Component).
void setBounds(Rectangle)
void setBounds(int, int, int, int) 		Explicitly set the size and location of the internal frame. (Inherited from Component).
void setSize(Dimension)
void setSize(int, int) 		Explicitly set the size of the internal frame. (Inherited from Component).

Performing Window Operations on the Internal Frame
Method Purpose
void setDefaultCloseOperation(int)
int getDefaultCloseOperation() 		Set or get what the internal frame does when the user attempts to "close" the internal frame. The default value is DISPOSE_ON_CLOSE. Other possible values are DO_NOTHING_ON_CLOSE and HIDE_ON_CLOSE See Responding to Window-Closing Events for details.
void addInternalFrameListener(InternalFrameListener)
void removeInternalFrameListener(InternalFrameListener) 		Add or remove an internal frame listener (JInternalFrame's equivalent of a window listener). See How to Write an Internal Frame Listener for more information.
void moveToFront()
void moveToBack() 		If the internal frame's parent is a layered pane such as a desktop pane, moves the internal frame to the front or back (respectively) of its layer.
void setClosed(boolean)
boolean isClosed() 		Set or get whether the internal frame is currently closed. The argument to setClosed must be true. When reopening a closed internal frame, you make it visible and add it to a container (usually the desktop pane you originally added it to).
void setIcon(boolean)
boolean isIcon() 		Iconify or deiconify the internal frame, or determine whether it is currently iconified.
void setMaximum(boolean)
boolean isMaximum() 		Maximize or restore the internal frame, or determine whether it is maximized.
void setSelected(boolean)
boolean isSelected() 		Set or get whether the internal frame is the currently "selected" (activated) internal frame.

Controlling Window Decorations and Capabilities
Method Purpose
void setFrameIcon(Icon)
Icon getFrameIcon() 		Set or get the icon displayed in the title bar of the internal frame (usually in the top-left corner).
void setClosable(boolean)
boolean isClosable() 		Set or get whether the user can close the internal frame.
void setIconifiable(boolean)
boolean isIconifiable() 		Set or get whether the internal frame can be iconified.
void setMaximizable(boolean)
boolean isMaximizable() 		Set or get whether the user can maximize this internal frame.
void setResizable(boolean)
boolean isResizable() 		Set or get whether the internal frame can be resized.
void setTitle(String)
String getTitle() 		Set or get the window title.

Using the JDesktopPane API
Constructor or Method | Purpose
JDesktopPane() | Creates a new instance of JDesktopPane.
JInternalFrame[] getAllFrames() | Returns all JInternalFrame objects that the desktop contains.
JInternalFrame[] getAllFramesInLayer(int) | Returns all JInternalFrame objects that the desktop contains that are in the specified layer. See How to Use Layered Panes for information about layers.
void setDragMode(int)
int getDragMode() 		Set or get the drag mode used for internal frames in this desktop. The integer can be either JDesktopPane.LIVE_DRAG_MODE or JDesktopPane.OUTLINE_DRAG_MODE. The default for the Java look and feel is live-drag mode.

Examples that Use Internal Frames

The following examples use internal frames. Because internal frames are similar to regular frames, you should also look at Examples that Use Frames.

Example | Where Described | Notes
MyInternalFrame | This page. | Implements an internal frame that appears at an offset to the previously created internal frame.
InternalFrameDemo | This page. | Lets you create internal frames (instances of MyInternalFrame) that go into the application's JDesktopPane.
InternalFrameEventDemo | How to Write an Internal Frame Listener | Demonstrates listening for internal frame events. Also demonstrates positioning internal frames within a desktop pane.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Make Frames (Main Windows)
Next page: How to Use Labels


How to Use Labels (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Labels
With the JLabel class, you can display unselectable text and images. If you need to create a component that displays a string, an image, or both, you can do so by using or extending JLabel. If the component is interactive and has a certain state, use a button instead of a label.

By specifying HTML code in a label's text, you can give the label various characteristics such as multiple lines, multiple fonts or multiple colors. If the label uses just a single color or font, you can avoid the overhead of HTML processing by using the setForeground or setFont method instead. See Using HTML in Swing Components for details.

Note that labels are not opaque by default. If you need to paint the label's background, it is recommended that you turn its opacity property to "true". The following code snippet shows how to do this.

label.setOpaque(true);

The following picture introduces an application that displays three labels. The window is divided into three rows of equal height; the label in each row is as wide as possible.

A snapshot of LabelDemo, which uses labels with text and icons.

Try this:
  1. Click the Launch button to run LabelDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    2. Launches the LabelDemo Application

  2. Resize the window so you can see how the labels' contents are placed within the labels' drawing area.
    All the label contents have default vertical alignment — that is, the label contents are centered vertically in the label's drawing area. The top label, which contains both an image and text, has horizontal center alignment. The second label, which contains just text, has left (leading) alignment, which is the default for text-only labels in left-to-right languages. The third label, which contains just an image, has horizontal center alignment, which is the default for image-only labels.

Below is the code from LabelDemo.java that creates the labels in the previous example.

ImageIcon icon = createImageIcon("images/middle.gif");
. . .
label1 = new JLabel("Image and Text",
                    icon,
                    JLabel.CENTER);
//Set the position of the text, relative to the icon:
label1.setVerticalTextPosition(JLabel.BOTTOM);
label1.setHorizontalTextPosition(JLabel.CENTER);

label2 = new JLabel("Text-Only Label");
label3 = new JLabel(icon);
The code for the createImageIcon method is similar to that used throughout this tutorial. You can find it in How to Use Icons.

Often, a label describes another component. When this occurs, you can improve your program's accessibility by using the setLabelFor method to identify the component that the label describes. For example:

amountLabel.setLabelFor(amountField);
The preceding code, taken from the FormattedTextFieldDemo example discussed in How to Use Formatted Text Fields, lets assistive technologies know that the label (amountLabel) provides information about the formatted text field (amountField). For more information about assistive technologies, see How to Support Assistive Technologies.

The Label API

The following tables list the commonly used JLabel constructors and methods. Other methods you are likely to call are defined by the Component and JComponent classes. They include setFont, setForeground, setBorder, setOpaque, and setBackground. See The JComponent Class for details. The API for using labels falls into three categories:
  • Setting or Getting the Label's Contents
  • Fine Tuning the Label's Appearance
  • Supporting Accessibility
Note: In the following API, do not confuse label alignment with X and Y alignment. X and Y alignment are used by layout managers and can affect the way any component — not just a label — is sized or positioned. Label alignment, on the other hand, has no effect on a label's size or position. Label alignment simply determines where, inside the label's painting area, the label's contents are positioned. Typically, the label's painting area is exactly the size needed to paint on the label and thus label alignment is irrelevant. For more information about X and Y alignment, see How to Use BoxLayout.

Setting or Getting the Label's Contents
Method or Constructor Purpose
JLabel(Icon)
JLabel(Icon, int)
JLabel(String)
JLabel(String, Icon, int)
JLabel(String, int)
JLabel() 		Creates a JLabel instance, initializing it to have the specified text/image/alignment. The int argument specifies the horizontal alignment of the label's contents within its drawing area. The horizontal alignment must be one of the following constants defined in the SwingConstants interface (which JLabel implements): LEFT, CENTER, RIGHT, LEADING, or TRAILING. For ease of localization, we strongly recommend using LEADING and TRAILING, rather than LEFT and RIGHT.
void setText(String)
String getText() 		Sets or gets the text displayed by the label. You can use HTML tags to format the text, as described in Using HTML in Swing Components.
void setIcon(Icon)
Icon getIcon() 		Sets or gets the image displayed by the label.
void setDisplayedMnemonic(char)
char getDisplayedMnemonic() 		Sets or gets the letter that should look like a keyboard alternative. This is helpful when a label describes a component (such as a text field) that has a keyboard alternative but cannot display it. If the labelFor property is also set (using setLabelFor), then when the user activates the mnemonic, the keyboard focus is transferred to the component specified by the labelFor property.
void setDisplayedMnemonicIndex(int)
int getDisplayedMnemonicIndex() 		Sets or gets a hint as to which character in the text should be decorated to represent the mnemonic. This is useful when you have two instances of the same character and wish to decorate the second instance. For example, setDisplayedMnemonicIndex(5) decorates the character that is at position 5 (that is, the 6th character in the text). Not all types of look and feel may support this feature.
void setDisabledIcon(Icon)
Icon getDisabledIcon() 		Sets or gets the image displayed by the label when it is disabled. If you do not specify a disabled image, then the look and feel creates one by manipulating the default image.

Fine Tuning the Label's Appearance
Method Purpose
void setHorizontalAlignment(int)
void setVerticalAlignment(int)
int getHorizontalAlignment()
int getVerticalAlignment() 		Sets or gets the area on the label where its contents should be placed. The SwingConstants interface defines five possible values for horizontal alignment: LEFT, CENTER (the default for image-only labels), RIGHT, LEADING (the default for text-only labels), TRAILING. For vertical alignment: TOP, CENTER (the default), and BOTTOM.
void setHorizontalTextPosition(int)
void setVerticalTextPosition(int)
int getHorizontalTextPosition()
int getVerticalTextPosition() 		Sets or gets the location where the button's text will be placed, relative to the button's image. The SwingConstants interface defines five possible values for horizontal position: LEADING, LEFT, CENTER, RIGHT, and TRAILING (the default). For vertical position: TOP, CENTER (the default), and BOTTOM.
void setIconTextGap(int)
int getIconTextGap() 		Sets or gets the number of pixels between the label's text and its image.

Supporting Accessibility
Method Purpose
void setLabelFor(Component)
Component getLabelFor() 		Sets or gets which component the label describes.

Examples That Use Labels

The following table lists some of the many examples that use labels.

Example | Where Described | Notes
LabelDemo | This section | Shows how to specify horizontal and vertical alignment as well as how to align a label's text and image.
HtmlDemo | Using HTML in Swing Components | Lets you experiment with specifying HTML text for a label.
BoxAlignmentDemo | Fixing Alignment Problems | Demonstrates possible alignment problems when using a label in a vertical box layout. Shows how to solve the problem.
DialogDemo | How to Use Dialogs | Uses a changeable label to display instructions and provide feedback.
SplitPaneDemo | How to Use Split Panes and How to Use Lists | Displays an image using a label inside of a scroll pane.
SliderDemo2 | How to Use Sliders | Uses JLabel to provide labels for a slider.
TableDialogEditDemo | How to Use Tables | Implements a label subclass, ColorRenderer, to display colors in table cells.
FormattedTextFieldDemo | How to Use Formatted Text Fields | Has four rows, each containing a label and the formatted text field it describes.
TextComponentDemo | Text Component Features | TextComponentDemo has an inner class (CaretListenerLabel) that extends JLabel to provide a label that listens for events, updating itself based on the events.
ColorChooserDemo | How to Use Color Choosers | Uses an opaque label to display the currently chosen color against a fixed-color background.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Internal Frames
Next page: How to Use Layered Panes


How to Use Layered Panes (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Layered Panes

A layered pane is a Swing container that provides a third dimension for positioning components: depth, also known as Z order. When adding a component to a layered pane, you specify its depth as an integer. The higher the number, closer the component is to the "top" position within the container. If components overlap, the "closer" components are drawn on top of components at a lower depth. The relationship between components at the same depth is determined by their positions within the depth.

Note: The AWT Container has an API that allows you to manipulate component Z order. For more information, see the AWT Focus Specification.

Every Swing container that has a root pane — such as JFrame, JApplet, JDialog, or JInternalFrame — automatically has a layered pane. Most programs do not explicitly use the root pane's layered pane, so this section will not discuss it. You can find information about it in The Root Pane, which provides an overview, and The Layered Pane, which has further details. This section tells you how to create your own layered pane and use it anywhere you can use a regular Swing container.

Swing provides two layered pane classes. The first, JLayeredPane, is the class that root panes use and is the class used by the example in this section. The second, JDesktopPane, is a JLayeredPane subclass that is specialized for the task of holding internal frames. For examples of using JDesktopPane, see How to Use Internal Frames.

Here is a picture of an application that creates a layered pane and places overlapping, colored labels at different depths:

A snapshot of LayeredPaneDemo

Try this::
  1. Click the Launch button to run the LayeredPane Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TreeDemo example

  2. Move the mouse around in the lower part of the window. The image of Duke drags behind the green and red labels, but in front of the other three labels.
  3. Use the combo box at the top of the window to change Duke's depth. Use the check box to set whether Duke is in the top position — position 0 — within the current depth.
Here is the code from LayeredPaneDemo.java that creates the layered pane:
layeredPane = new JLayeredPane();
layeredPane.setPreferredSize(new Dimension(300, 310));
layeredPane.setBorder(BorderFactory.createTitledBorder(
                                    "Move the Mouse to Move Duke"));
layeredPane.addMouseMotionListener(new MouseMotionAdapter() {
    ...
});
The code uses JLayeredPane's only constructor — the no-argument constructor — to create the layered pane. The rest of the code uses methods inherited from superclasses to give the layered pane a preferred size and a border, and add a mouse-motion listener to it. The mouse-motion listener just moves the Duke image around in response to mouse movement. Although we do not show the code here, the example adds the layered pane to the frame's content pane.

As we will show you a bit later, you add components to a layered pane using an add method. When adding a component to a layered pane, you specify the component depth, and optionally, its position within its depth. The layered pane in the demo program contains six labels — the five colored labels and a sixth one that displays the Duke image. As the program demonstrates, both the depth of a component and its position within that depth can change dynamically.

The rest of this section covers these topics:

  • Adding Components and Setting Component Depth
  • Setting a Component Position Within Its Depth
  • Laying Out Components in a Layered Pane
  • The Layered Pane API
  • Examples that Use Layered Panes

Adding Components and Setting Component Depth
Here is the code from the sample program that adds the colored labels to the layered pane:
for (int i = 0; i < ...number of labels...; i++) {
    JLabel label = createColoredLabel(...);
    layeredPane.add(label, new Integer(i));
    ...
}
You can find the implementation of the createColoredLabel method in the source code for the program. It just creates an opaque JLabel initialized with a background color, a border, some text, and a size.

The example program uses a two-argument version of the add method. The first argument is the component to add, the second is an Integer object, specifying the depth. This program uses the for loop iteration variable to specify depths. The actual values do not matter much. What matters is the relative value of the depths and that you are consistent within your program in how you use each depth.

Note: If you use the root pane's layered pane, be sure to use its depth conventions. Refer to The Layered Pane for details. That section shows you how to modify LayeredPaneDemo to use the root pane's layered pane. With the modifications, you can see how the dragging Duke image relates to the combo box in the control panel.

As you can see from the example program, if components overlap, components at a higher depth are on top of components at a lower depth. To change a component depth dynamically, use the setLayer method. In the example, the user can change Duke's layer by making a selection from the combo box. Here is the actionPerformed method of the action listener registered on the combo box:

public void actionPerformed(ActionEvent e) {
    int position = onTop.isSelected() ? 0 : 1;
    layeredPane.setLayer(dukeLabel,
                         layerList.getSelectedIndex(),
                         position);
}
The setLayer method used here takes three arguments: the component whose depth is to be set, the new depth, and the position within the depth. JLayeredPane has a two-argument version of setLayer that takes only the component and the new depth. That method puts the component at the bottom position in its depth.
A note of caution: When adding a component to a layered pane you specify the layer with an Integer. When using setLayer to change a component's layer, you use an int. You might think that if you use an int instead of an Integer with the add method, the compiler would complain or your program would throw an illegal argument exception. But the compiler says nothing, which results in a common layered pane problem. You can use the API tables at the end of this section to check the types of the arguments and return values for methods that deal with layers.

Setting a Component's Position Within Its Depth
The following code creates the label that displays Duke's image, and then adds the label to the layered pane.
final ImageIcon icon = createImageIcon("images/dukeWaveRed.gif");
...
dukeLabel = new JLabel(icon);
...
dukeLabel.setBounds(15, 225,
                    icon.getIconWidth(),
                    icon.getIconHeight());
...
layeredPane.add(dukeLabel, new Integer(2), 0);
This code uses the three-argument version of the add method. The third argument specifies the Duke label position within its depth, which determines the component's relationship with other components at the same depth.

Positions are specified with an int between -1 and (n - 1), where n is the number of components at the depth. Unlike layer numbers, the smaller the position number, the higher the component within its depth. Using -1 is the same as using n - 1; it indicates the bottom-most position. Using 0 specifies that the component should be in the top-most position within its depth. As the following figure shows, with the exception of -1, a lower position number indicates a higher position within a depth.

How positions affect layering

A component's position within its layer can change dynamically. In the example, you can use the check box to determine whether Duke label is in the top position at its depth. Here's the actionPerformed method for the action listener registered on the check box:
public void actionPerformed(ActionEvent e) {
    if (onTop.isSelected())
        layeredPane.moveToFront(dukeLabel);
    else
        layeredPane.moveToBack(dukeLabel);
}
When the user selects the check box, the moveToFront method moves Duke to the front (position 0). And when the user deselects check box, Duke gets moved to the back with the moveToBack method. You can also use the setPosition method or the three-argument version of setLayer to change a component's position.

Laying Out Components in a Layered Pane
By default a layered pane has no layout manager. This means that you typically have to write the code that positions and sizes the components you put in a layered pane.

The example uses the setBounds method to set the size and position of each of the labels:

dukeLabel.setBounds(15, 225,
                    icon.getIconWidth(),
                    icon.getIconHeight());
...
label.setBounds(origin.x, origin.y, 140, 140);
When the user moves the mouse around, the program calls setPosition to change Duke's position:
dukeLabel.setLocation(e.getX()-XFUDGE, e.getY()-YFUDGE);
Although a layered pane has no layout manager by default, you can still assign a layout manager to the layered pane. All of the layout managers provided by the Java platform arrange the components as if they were all on one layer. Here is a version of the previous demo that sets the layered pane's layout manager to an instance of GridLayout, using that layout manager to lay out six colored labels.

A snapshot of LayeredPaneDemo2

You can find the code for this program in LayeredPaneDemo2.java. You can run LayeredPaneDemo2 ( download JDK 6). If you want to compile the example, consult the example index for a list of all necessary files.

Many programs use intermediate containers (such as panels) and their layout managers to lay out components on the same layer, but use absolute positioning to lay out components on different layers. For more information about absolute positioning, see Doing Without a Layout Manager (Absolute Positioning).

The Layered Pane API

The following tables list the commonly used JLayeredPane constructors and methods. Other methods you are most likely to invoke on a JLayeredPane object are those it inherits from its superclasses, such as setBorder, setPreferredSize, and so on. See The JComponent API for tables of commonly used inherited methods.

The API for using layered pane falls into these categories:

  • Creating or Getting a Layered Pane
  • Layering Components
  • Setting Component's Intra-Layer Positions

Creating or Getting a Layered Pane
Method or Constructor | Purpose
JLayeredPane() | Create a layered pane.
JLayeredPane getLayeredPane()
(in JApplet, JDialog, JFrame, and JInternalFrame) 		Get the automatic layered pane in an applet, dialog, frame, or internal frame.

Layering Components
Method | Purpose
void add(Component)
void add(Component, Object)
void add(Component, Object, int) 		Add the specified component to the layered pane. The second argument, when present, is an Integer that indicates the layer. The third argument, when present, indicates the component's position within its layer. If you use the one-argument version of this method, the component is added to layer 0. If you use the one- or two-argument version of this method, the component is placed underneath all other components currently in the same layer.
void setLayer(Component, int)
void setLayer(Component, int, int) 		Change the component's layer. The second argument indicates the layer. The third argument, when present, indicates the component's position within its layer.
int getLayer(Component)
int getLayer(JComponent) 		Get the layer for the specified component.
int getComponentCountInLayer(int) | Get the number of components in the specified layer. The value returned by this method can be useful for computing position values.
Component[] getComponentsInLayer(int) | Get an array of all the components in the specified layer.
int highestLayer()
int lowestLayer() 		Compute the highest or lowest layer currently in use.

Setting Components' Intra-Layer Positions
Method Purpose
void setPosition(Component, int)
int getPosition(Component) 		Set or get the position for the specified component within its layer.
void moveToFront(Component)
void moveToBack(Component) 		Move the specified component to the front or back of its layer.

Examples that Use Layered Panes

This table shows the examples that use JLayeredPane and where those examples are described.

Example | Where Described | Notes
LayeredPaneDemo | This section | Illustrates layers and intra-layer positions of a JLayeredPane.
LayeredPaneDemo2 | This section | Uses a layout manager to help lay out the components in a layered pane.
RootLayeredPaneDemo | The Layered Pane | A version of LayeredPaneDemo modified to use the root pane's layered pane.
InternalFrameDemo | How to Use Internal Frames | Uses a JDesktopFrame to manage internal frames.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Labels
Next page: How to Use Lists


How to Use Lists (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Lists
A JList presents the user with a group of items, displayed in one or more columns, to choose from. Lists can have many items, so they are often put in scroll panes.

In addition to lists, the following Swing components present multiple selectable items to the user: combo boxes, menus, tables, and groups of check boxes or radio buttons. To display hierarchical data, use a tree.

The following figures shows two applications that use lists. This section uses these examples as a basis for the discussions that follow.

A snapshot of ListDialog, which displays a simple list A snapshot of ListDemo, which lets you add and remove list items
ListDialog
(used by ListDialogRunner) 		ListDemo

Try this:
  1. Click the Launch button to run ListDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ListDemo example

  2. Click the Launch button to run ListDialogRunner. Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ListDialogRunner example

  3. To bring up the ListDialog, click the Pick a new name... button in the window titled Name That Baby.
    The resulting dialog is a ListDialog instance that has been customized to have the title Name Chooser.
  4. In ListDemo, try adding (hiring) and removing (firing) a few items.
This rest of this section discusses the following topics:

  • Creating a Model
  • Initializing a List
  • Selecting Items in a List
  • Adding Items to and Removing Items from a List
  • Writing a Custom Cell Renderer
  • The List API
  • Examples that Use Lists

Creating a Model
There are three ways to create a list model:
  • DefaultListModel — everything is pretty much taken care of for you. The examples in this page use DefaultListModel.
  • AbstractListModel — you manage the data and invoke the "fire" methods. For this approach, you must subclass AbstractListModel and implement the getSize and getElementAt methods inherited from the ListModel interface.
  • ListModel — you manage everything.

Initializing a List
Here is the code from ListDialog.java that creates and sets up its list:
list = new JList(data); //data has type Object[]
list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
list.setLayoutOrientation(JList.HORIZONTAL_WRAP);
list.setVisibleRowCount(-1);
...
JScrollPane listScroller = new JScrollPane(list);
listScroller.setPreferredSize(new Dimension(250, 80));
The code passes an array to the list's constructor. The array is filled with strings that were passed in from another object. In our example, the strings happen to be boys' names.

Other JList constructors let you initialize a list from a Vector or from an object that adheres to the ListModel interface. If you initialize a list with an array or vector, the constructor implicitly creates a default list model. The default list model is immutable — you cannot add, remove, or replace items in the list. To create a list whose items can be changed individually, set the list's model to an instance of a mutable list model class, such as an instance of DefaultListModel. You can set a list's model when you create the list or by calling the setModel method. See Adding Items to and Removing Items from a List for an example.

The call to setSelectionMode specifies how many items the user can select, and whether they must be contiguous; the next section tells you more about selection modes.

The call to setLayoutOrientation lets the list display its data in multiple columns. The value JList.HORIZONTAL_WRAP specifies that the list should display its items from left to right before wrapping to a new row. Another possible value is JList.VERTICAL_WRAP, which specifies that the data be displayed from top to bottom (as usual) before wrapping to a new column. The following figures show these two wrapping possibilities, together with the default, JList.VERTICAL.

VERTICAL
HORIZONTAL_WRAP VERTICAL_WRAP VERTICAL

In combination with the call to setLayoutOrientation, invoking setVisibleRowCount(-1) makes the list display the maximum number of items possible in the available space onscreen. Another common use of setVisibleRowCount is to specify to the lists's scroll pane how many rows the list prefers to display.

Selecting Items in a List
A list uses an instance of ListSelectionModel to manage its selection. By default, a list selection model allows any combination of items to be selected at a time. You can specify a different selection mode by calling the setSelectionMode method on the list. For example, both ListDialog and ListDemo set the selection mode to SINGLE_SELECTION (a constant defined by ListSelectionModel) so that only one item in the list can be selected. The following table describes the three list selection modes:

Mode Description
SINGLE_SELECTION
Single selection means only one item can be selected at once

Only one item can be selected at a time. When the user selects an item, any previously selected item is deselected first.
SINGLE_INTERVAL_SELECTION
Single interval selection means multiple, contiguous items can be selected at once

Multiple, contiguous items can be selected. When the user begins a new selection range, any previously selected items are deselected first.
MULTIPLE_INTERVAL_SELECTION
Multiple interval selection means any combination of items can be selected at once

The default. Any combination of items can be selected. The user must explicitly deselect items.

No matter which selection mode your list uses, the list fires list selection events whenever the selection changes. You can process these events by adding a list selection listener to the list with the addListSelectionListener method. A list selection listener must implement one method: valueChanged. Here is the valueChanged method for the listener in ListDemo:

public void valueChanged(ListSelectionEvent e) {
    if (e.getValueIsAdjusting() == false) {

        if (list.getSelectedIndex() == -1) {
        //No selection, disable fire button.
            fireButton.setEnabled(false);

        } else {
        //Selection, enable the fire button.
            fireButton.setEnabled(true);
        }
    }
}
Many list selection events can be generated from a single user action such as a mouse click. The getValueIsAdjusting method returns true if the user is still manipulating the selection. This particular program is interested only in the final result of the user's action, so the valueChanged method does something only if getValueIsAdjusting returns false.

Because the list is in single-selection mode, this code can use getSelectedIndex to get the index of the just-selected item. JList provides other methods for setting or getting the selection when the selection mode allows more than one item to be selected. If you want, you can listen for events on the list's list selection model rather than on the list itself. ListSelectionDemo is an example that shows how to listen for list selection events on the list selection model and lets you change the selection mode of a list dynamically.

Adding Items to and Removing Items from a List
The ListDemo example that we showed previously features a list whose contents can change. You can find the source code for ListDemo in ListDemo.java. Here is the ListDemo code that creates a mutable list model object, puts the initial items in it, and uses the list model to create a list:
listModel = new DefaultListModel();
listModel.addElement("Debbie Scott");
listModel.addElement("Scott Hommel");
listModel.addElement("Alan Sommerer");

list = new JList(listModel);
This particular program uses an instance of DefaultListModel, a class provided by Swing. In spite of the class name, a list does not have a DefaultListModel unless your program explicitly makes it so. If DefaultListModel does not suit your needs, you can write a custom list model, which must adhere to the ListModel interface.

The following code snippet shows the actionPerformed method for the action listener registered on the Fire button. The bold line of code removes the selected item in the list. The remaining lines in the method disable the fire button if the list is now empty, and make another selection if it is not.

public void actionPerformed(ActionEvent e) {
    int index = list.getSelectedIndex();
    listModel.remove(index);

    int size = listModel.getSize();

    if (size == 0) { //Nobody's left, disable firing.
        fireButton.setEnabled(false);

    } else { //Select an index.
        if (index == listModel.getSize()) {
            //removed item in last position
            index--;
        }

        list.setSelectedIndex(index);
        list.ensureIndexIsVisible(index);
    }
}

Here is the actionPerformed method for the action listener shared by the Hire button and the text field:

public void actionPerformed(ActionEvent e) {
    String name = employeeName.getText();

    //User did not type in a unique name...
    if (name.equals("") || alreadyInList(name)) {
        Toolkit.getDefaultToolkit().beep();
        employeeName.requestFocusInWindow();
        employeeName.selectAll();
        return;
    }

    int index = list.getSelectedIndex(); //get selected index
    if (index == -1) { //no selection, so insert at beginning
        index = 0;
    } else {           //add after the selected item
        index++;
    }

    listModel.insertElementAt(employeeName.getText(), index);

    //Reset the text field.
    employeeName.requestFocusInWindow();
    employeeName.setText("");

    //Select the new item and make it visible.
    list.setSelectedIndex(index);
    list.ensureIndexIsVisible(index);
}
This code uses the list model's insertElementAt method to insert the new name after the current selection or, if no selection exists, at the beginning of the list. If you just wish to add to the end of the list, you can use DefaultListModel's addElement method instead.

Whenever items are added to, removed from, or modified in a list, the list model fires list data events. Refer to How to Write a List Data Listener for information about listening for these events. That section contains an example that is similar to ListDemo, but adds buttons that move items up or down in the list.

Writing a Custom Cell Renderer
A list uses an object called a cell renderer to display each of its items. The default cell renderer knows how to display strings and icons and it displays Objects by invoking toString. If you want to change the way the default renderer display icons or strings, or if you want behavior different than what is provided by toString, you can implement a custom cell renderer. Take these steps to provide a custom cell renderer for a list:
  • Write a class that implements the ListCellRenderer interface.
  • Create an instance of your class and call the list's setCellRenderer using the instance as an argument.
We do not provide an example of a list with a custom cell renderer, but we do have an example of a combo box with a custom renderer — and combo boxes use the same type of renderer as lists. See the example described in Providing a Custom Renderer.

The List API

The following tables list the commonly used JList constructors and methods. Other methods you are most likely to invoke on a JList object are those such as setPreferredSize that its superclasses provide. See The JComponent API for tables of commonly used inherited methods.

Much of the operation of a list is managed by other objects. The items in the list are managed by a list model object, the selection is managed by a list selection model object, and most programs put a list in a scroll pane to handle scrolling. For the most part, you do not need to worry about the models because JList creates them as necessary and you interact with them implicitly with JList's convenience methods.

That said, the API for using lists falls into these categories:

  • Initializing List Data
  • Displaying the List
  • Managing the List's Selection
  • Managing List Data

Initializing List Data
Method or Constructor Purpose
JList(ListModel)
JList(Object[])
JList(Vector)
JList() 		Create a list with the initial list items specified. The second and third constructors implicitly create an immutable ListModel; you should not subsequently modify the passed-in array or Vector.
void setModel(ListModel)
ListModel getModel() 		Set or get the model that contains the contents of the list.
void setListData(Object[])
void setListData(Vector) 		Set the items in the list. These methods implicitly create an immutable ListModel.

Displaying the List
Method | Purpose
void setVisibleRowCount(int)
int getVisibleRowCount() 		Set or get the visibleRowCount property. For a VERTICAL layout orientation, this sets or gets the preferred number of rows to display without requiring scrolling. For the HORIZONTAL_WRAP or VERTICAL_WRAP layout orientations, it defines how the cells wrap. See the setLayoutOrientation(int) for more information. The default value of this property is VERTICAL.
void setLayoutOrientation(int)
int getLayoutOrientation() 		Set or get the way list cells are laid out. The possible layout formats are specified by the JList-defined values VERTICAL (a single column of cells; the default), HORIZONTAL_WRAP ("newspaper" style with the content flowing horizontally then vertically), and VERTICAL_WRAP ("newspaper" style with the content flowing vertically then horizontally).
int getFirstVisibleIndex()
int getLastVisibleIndex() 		Get the index of the first or last visible item.
void ensureIndexIsVisible(int) | Scroll so that the specified index is visible within the viewport that this list is in.

Managing the List's Selection
Method | Purpose
void addListSelectionListener(ListSelectionListener) | Register to receive notification of selection changes.
void setSelectedIndex(int)
void setSelectedIndices(int[])
void setSelectedValue(Object, boolean)
void setSelectionInterval(int, int) 		Set the current selection as indicated. Use setSelectionMode to set what ranges of selections are acceptable. The boolean argument specifies whether the list should attempt to scroll itself so that the selected item is visible.
int getAnchorSelectionIndex()
int getLeadSelectionIndex()
int getSelectedIndex()
int getMinSelectionIndex()
int getMaxSelectionIndex()
int[] getSelectedIndices()
Object getSelectedValue()
Object[] getSelectedValues() 		Get information about the current selection as indicated.
void setSelectionMode(int)
int getSelectionMode() 		Set or get the selection mode. Acceptable values are: SINGLE_SELECTION, SINGLE_INTERVAL_SELECTION, or MULTIPLE_INTERVAL_SELECTION (the default), which are defined in ListSelectionModel.
void clearSelection()
boolean isSelectionEmpty() 		Set or get whether any items are selected.
boolean isSelectedIndex(int) | Determine whether the specified index is selected.

Managing List Data
Class or Method | Purpose
int getNextMatch(String, int, javax.swing.text.Position.Bias) | Given the starting index, search through the list for an item that starts with the specified string and return that index (or -1 if the string is not found). The third argument, which specifies the search direction, can be either Position.Bias.Forward or Position.Bias.Backward. For example, if you have a 6-item list, getNextMatch("Matisse", 5, javax.swing.text.Position.Bias.Forward) searches for the string "Matisse" in the item at index 5, then (if necessary) at index 0, index 1, and so on.
void setDragEnabled(boolean)
boolean getDragEnabled() 		Set or get the property that determines whether automatic drag handling is enabled. See Drag and Drop for more details.

Examples that Use Lists

This table shows the examples that use JList and where those examples are described.

Example | Where Described | Notes
SplitPaneDemo | How to Use Split Panes | Contains a single-selection, immutable list.
ListDemo | This section | Demonstrates how to add and remove items from a list at runtime.
ListDialog | This section, How to Use BoxLayout | Implements a modal dialog with a single-selection list.
ListDataEventDemo | How to Write a List Data Listener | Demonstrates listening for list data events on a list model.
ListSelectionDemo | How to Write a List Selection Listener | Contains a list and a table that share the same selection model. You can dynamically choose the selection mode.
SharedModelDemo | Using Models | Modifies ListSelectionDemo so that the list and table share the same data model.
CustomComboBoxDemo | Providing a Custom Renderer | Shows how to provide a custom renderer for a combo box. Because lists and combo boxes use the same type of renderer, you can use what you learn there an apply it to lists. In fact, a list and a combo box can share a renderer.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Layered Panes
Next page: How to Use Menus


How to Use Menus (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Menus
A menu provides a space-saving way to let the user choose one of several options. Other components with which the user can make a one-of-many choice include combo boxes, lists, radio buttons, spinners, and tool bars. If any of your menu items performs an action that is duplicated by another menu item or by a tool-bar button, then in addition to this section you should read How to Use Actions.

Menus are unique in that, by convention, they aren't placed with the other components in the UI. Instead, a menu usually appears either in a menu bar or as a popup menu. A menu bar contains one or more menus and has a customary, platform-dependent location — usually along the top of a window. A popup menu is a menu that is invisible until the user makes a platform-specific mouse action, such as pressing the right mouse button, over a popup-enabled component. The popup menu then appears under the cursor.

The following figure shows many menu-related components: a menu bar, menus, menu items, radio button menu items, check box menu items, and separators. As you can see, a menu item can have either an image or text, or both. You can also specify other properties, such as font and color.

The rest of this section teaches you about the menu components and tells you how to use various menu features:

  • The menu component hierarchy
  • Creating menus
  • Handling events from menu items
  • Enabling keyboard operation
  • Bringing up a popup menu
  • Customizing menu layout
  • The Menu API
  • Examples that use menus

The Menu Component Hierarchy

Here is a picture of the inheritance hierarchy for the menu-related classes:

The inheritance hierarchy for menu classes

As the figure shows, menu items (including menus) are simply buttons. You might be wondering how a menu, if it's only a button, shows its menu items. The answer is that when a menu is activated, it automatically brings up a popup menu that displays the menu items.

Creating Menus

The following code creates the menus shown near the beginning of this menu section. The bold lines of code create and connect the menu objects; the other code sets up or customizes the menu objects. You can find the entire program in MenuLookDemo.java. Other required files are listed in the example index.
Try this:
  • Click the Launch button to run the MenuLook Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ButtonDemo example

Because this code has no event handling, the menus do nothing useful except to look as they should. If you run the example, you'll notice that despite the lack of custom event handling, menus and submenus appear when they should, and the check boxes and radio buttons respond appropriately when the user chooses them.
//Where the GUI is created:
JMenuBar menuBar;
JMenu menu, submenu;
JMenuItem menuItem;
JRadioButtonMenuItem rbMenuItem;
JCheckBoxMenuItem cbMenuItem;

//Create the menu bar.
menuBar = new JMenuBar();

//Build the first menu.
menu = new JMenu("A Menu");
menu.setMnemonic(KeyEvent.VK_A);
menu.getAccessibleContext().setAccessibleDescription(
        "The only menu in this program that has menu items");
menuBar.add(menu);

//a group of JMenuItems
menuItem = new JMenuItem("A text-only menu item",
                         KeyEvent.VK_T);
menuItem.setAccelerator(KeyStroke.getKeyStroke(
        KeyEvent.VK_1, ActionEvent.ALT_MASK));
menuItem.getAccessibleContext().setAccessibleDescription(
        "This doesn't really do anything");
menu.add(menuItem);

menuItem = new JMenuItem("Both text and icon",
                         new ImageIcon("images/middle.gif"));
menuItem.setMnemonic(KeyEvent.VK_B);
menu.add(menuItem);

menuItem = new JMenuItem(new ImageIcon("images/middle.gif"));
menuItem.setMnemonic(KeyEvent.VK_D);
menu.add(menuItem);

//a group of radio button menu items
menu.addSeparator();
ButtonGroup group = new ButtonGroup();
rbMenuItem = new JRadioButtonMenuItem("A radio button menu item");
rbMenuItem.setSelected(true);
rbMenuItem.setMnemonic(KeyEvent.VK_R);
group.add(rbMenuItem);
menu.add(rbMenuItem);

rbMenuItem = new JRadioButtonMenuItem("Another one");
rbMenuItem.setMnemonic(KeyEvent.VK_O);
group.add(rbMenuItem);
menu.add(rbMenuItem);

//a group of check box menu items
menu.addSeparator();
cbMenuItem = new JCheckBoxMenuItem("A check box menu item");
cbMenuItem.setMnemonic(KeyEvent.VK_C);
menu.add(cbMenuItem);

cbMenuItem = new JCheckBoxMenuItem("Another one");
cbMenuItem.setMnemonic(KeyEvent.VK_H);
menu.add(cbMenuItem);

//a submenu
menu.addSeparator();
submenu = new JMenu("A submenu");
submenu.setMnemonic(KeyEvent.VK_S);

menuItem = new JMenuItem("An item in the submenu");
menuItem.setAccelerator(KeyStroke.getKeyStroke(
        KeyEvent.VK_2, ActionEvent.ALT_MASK));
submenu.add(menuItem);

menuItem = new JMenuItem("Another item");
submenu.add(menuItem);
menu.add(submenu);

//Build second menu in the menu bar.
menu = new JMenu("Another Menu");
menu.setMnemonic(KeyEvent.VK_N);
menu.getAccessibleContext().setAccessibleDescription(
        "This menu does nothing");
menuBar.add(menu);

...
frame.setJMenuBar(theJMenuBar);

As the code shows, to set the menu bar for a JFrame, you use the setJMenuBar method. To add a JMenu to a JMenuBar, you use the add(JMenu) method. To add menu items and submenus to a JMenu, you use the add(JMenuItem) method.

Note: Menu items, like other components, can be in at most one container. If you try to add a menu item to a second menu, the menu item will be removed from the first menu before being added to the second. For a way of implementing multiple components that do the same thing, see How to Use Actions.

Other methods in the preceding code include setAccelerator and setMnemonic, which are discussed a little later in Enabling Keyboard Operation. The setAccessibleDescription method is discussed in How to Support Assistive Technologies.

Handling Events from Menu Items

To detect when the user chooses a JMenuItem, you can listen for action events (just as you would for a JButton). To detect when the user chooses a JRadioButtonMenuItem, you can listen for either action events or item events, as described in How to Use Radio Buttons. For JCheckBoxMenuItems, you generally listen for item events, as described in How to Use Check Boxes.

Try this:
  • Click the Launch button to run the Menu Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ButtonDemo example

The text area shows the action and item events our listeners detected.

Here is the code that implements the event handling:

public class MenuDemo ... implements ActionListener,
                                     ItemListener {
    ...
    public MenuDemo() {
        //...for each JMenuItem instance:
        menuItem.addActionListener(this);
        ...
        //for each JRadioButtonMenuItem:
        rbMenuItem.addActionListener(this);
        ...
        //for each JCheckBoxMenuItem:
        cbMenuItem.addItemListener(this);
        ...
    }

    public void actionPerformed(ActionEvent e) {
        //...Get information from the action event...
        //...Display it in the text area...
    }

    public void itemStateChanged(ItemEvent e) {
        //...Get information from the item event...
        //...Display it in the text area...
    }
For examples of handling action and item events, see the button, radio button, and check box sections, as well as the list of examples at the end of this section.

Enabling Keyboard Operation

Menus support two kinds of keyboard alternatives: mnemonics and accelerators. Mnemonics offer a way to use the keyboard to navigate the menu hierarchy, increasing the accessibility of programs. Accelerators, on the other hand, offer keyboard shortcuts to bypass navigating the menu hierarchy. Mnemonics are for all users; accelerators are for power users.

A mnemonic is a key that makes an already visible menu item be chosen. For example, in MenuDemo the first menu has the mnemonic A, and its second menu item has the mnemonic B. This means that, when you run MenuDemo with the Java look and feel, pressing the Alt and A keys makes the first menu appear. While the first menu is visible, pressing the B key (with or without Alt) makes the second menu item be chosen. A menu item generally displays its mnemonic by underlining the first occurrence of the mnemonic character in the menu item's text, as the following snapshot shows.

B is the mnemonic character for this menu item

An accelerator is a key combination that causes a menu item to be chosen, whether or not it's visible. For example, pressing the Alt and 2 keys in MenuDemo makes the first item in the first menu's submenu be chosen, without bringing up any menus. Only leaf menu items — menus that don't bring up other menus — can have accelerators. The following snapshot shows how the Java look and feel displays a menu item that has an accelerator.

Alt+2 advertises this menu item's accelerator

You can specify a mnemonic either when constructing the menu item or with the setMnemonic method. To specify an accelerator, use the setAccelerator method. Here are examples of setting mnemonics and accelerators:

//Setting the mnemonic when constructing a menu item:
menuItem = new JMenuItem("A text-only menu item",
                         KeyEvent.VK_T);

//Setting the mnemonic after creation time:
menuItem.setMnemonic(KeyEvent.VK_T);

//Setting the accelerator:
menuItem.setAccelerator(KeyStroke.getKeyStroke(
        KeyEvent.VK_T, ActionEvent.ALT_MASK));
As you can see, you set a mnemonic by specifying the KeyEvent constant corresponding to the key the user should press. To specify an accelerator you must use a KeyStroke object, which combines a key (specified by a KeyEvent constant) and a modifier-key mask (specified by an ActionEvent constant).
Note: Because popup menus, unlike regular menus, aren't always contained by a component, accelerators in popup menu items don't work unless the popup menu is visible.

Bringing Up a Popup Menu

To bring up a popup menu ( JPopupMenu), you must register a mouse listener on each component that the popup menu should be associated with. The mouse listener must detect user requests that the popup menu be brought up.

The exact gesture that should bring up a popup menu varies by look and feel. In Microsoft Windows, the user by convention brings up a popup menu by releasing the right mouse button while the cursor is over a component that is popup-enabled. In the Java look and feel, the customary trigger is either pressing the right mouse button (for a popup that goes away when the button is released) or clicking it (for a popup that stays up).

Try this:
  • Click the Launch button to run the PopupMenu Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the PopupMenuDemo example

//...where instance variables are declared:
JPopupMenu popup;

    //...where the GUI is constructed:
    //Create the popup menu.
    popup = new JPopupMenu();
    menuItem = new JMenuItem("A popup menu item");
    menuItem.addActionListener(this);
    popup.add(menuItem);
    menuItem = new JMenuItem("Another popup menu item");
    menuItem.addActionListener(this);
    popup.add(menuItem);

    //Add listener to components that can bring up popup menus.
    MouseListener popupListener = new PopupListener();
    output.addMouseListener(popupListener);
    menuBar.addMouseListener(popupListener);
...
class PopupListener extends MouseAdapter {
    public void mousePressed(MouseEvent e) {
        maybeShowPopup(e);
    }

    public void mouseReleased(MouseEvent e) {
        maybeShowPopup(e);
    }

    private void maybeShowPopup(MouseEvent e) {
        if (e.isPopupTrigger()) {
            popup.show(e.getComponent(),
                       e.getX(), e.getY());
        }
    }
}

Popup menus have a few interesting implementation details. One is that every menu has an associated popup menu. When the menu is activated, it uses its associated popup menu to show its menu items.

Another detail is that a popup menu itself uses another component to implement the window containing the menu items. Depending on the circumstances under which the popup menu is displayed, the popup menu might implement its "window" using a lightweight component (such as a JPanel), a "mediumweight" component (such as a Panel), or a heavyweight window (something that inherits from Window).

Lightweight popup windows are more efficient than heavyweight windows, but they don't work well if you have any heavyweight components inside your GUI. Specifically, when the lightweight popup's display area intersects the heavyweight component's display area, the heavyweight component is drawn on top. This is one of the reasons we recommend against mixing heavyweight and lightweight components. If you absolutely need to use a heavyweight component in your GUI, then you can invoke JPopupMenu.setLightWeightPopupEnabled(false) to disable lightweight popup windows. For details, see Mixing Heavy and Light Components, an article in The Swing Connection.

Customizing Menu Layout

Because menus are made up of ordinary Swing components, you can easily customize them. For example, you can add any lightweight component to a JMenu or JMenuBar. And because JMenuBar uses BoxLayout, you can customize a menu bar's layout just by adding invisible components to it. Here is an example of adding a glue component to a menu bar, so that the last menu is at the right edge of the menu bar:

//...create and add some menus...
menuBar.add(Box.createHorizontalGlue());
//...create the rightmost menu...
menuBar.add(rightMenu);
Try this:
  • Click the Launch button to run the MenuGlue Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ButtonDemo example

Here's the modified menu layout that MenuGlueDemo displays:

Another way of changing the look of menus is to change the layout managers used to control them. For example, you can change a menu bar's layout manager from the default left-to-right BoxLayout to something such as GridLayout.

Try this:
  • Click the Launch button to run the MenuLayout Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the MenuLayoutDemo example

Here's a picture of the menu layout that MenuLayoutDemo creates:

The Menu API

The following tables list the commonly used menu constructors and methods. The API for using menus falls into these categories:
  • Creating and Setting Up Menu Bars
  • Creating and Populating Menus
  • Creating, Populating, and Controlling Popup Menus
  • Implementing Menu Items

Creating and Setting Up Menu Bars
Constructor or Method | Purpose
JMenuBar() | Creates a menu bar.
JMenu add(JMenu) | Creates a menu bar.
void setJMenuBar(JMenuBar)
JMenuBar getJMenuBar()
(in JApplet, JDialog, JFrame, JInternalFrame, JRootPane) 		Sets or gets the menu bar of an applet, dialog, frame, internal frame, or root pane.

Creating and Populating Menus
Constructor or Method | Purpose
JMenu()
JMenu(String)
JMenu(Action) 		Creates a menu. The string specifies the text to display for the menu. The Action specifies the text and other properties of the menu (see How to Use Actions).
JMenuItem add(JMenuItem)
JMenuItem add(String) 		Adds a menu item to the current end of the menu. If the argument is a string, then the menu automatically creates a JMenuItem object that displays the specified text.

Version Note: Before 1.3, the only way to associate an Action with a menu item was to use menu's add(Action) method to create the menu item and add it to the menu. As of 1.3, that method is no longer recommended. You can instead associate a menu item with an Action using the setAction method.

void addSeparator() | Adds a separator to the current end of the menu.
JMenuItem insert(JMenuItem, int)
void insert(String, int)
void insertSeparator(int) 		Inserts a menu item or separator into the menu at the specified position. The first menu item is at position 0, the second at position 1, and so on. The JMenuItem and String arguments are treated the same as in the corresponding add methods.
void remove(JMenuItem)
void remove(int)
void removeAll() 		Removes the specified item(s) from the menu. If the argument is an integer, then it specifies the position of the menu item to be removed.

Creating, Populating, and Controlling Popup Menus
Constructor or Method | Purpose
JPopupMenu()
JPopupMenu(String) 		Creates a popup menu. The optional string argument specifies the title that a look and feel might display as part of the popup window.
JMenuItem add(JMenuItem)
JMenuItem add(String) 		Adds a menu item to the current end of the popup menu. If the argument is a string, then the menu automatically creates a JMenuItem object that displays the specified text.

Version Note: Before 1.3, the only way to associate an Action with an item in a popup menu was to use the popup menu's add(Action) method to create the menu item and add it to the popup menu. As of 1.3, that method is no longer recommended. You can instead associate a menu item with an Action using the setAction method.

void addSeparator() | Adds a separator to the current end of the popup menu.
void insert(Component, int) | Inserts a menu item into the menu at the specified position. The first menu item is at position 0, the second at position 1, and so on. The Component argument specifies the menu item to add.
void remove(int)
void removeAll() 		Removes the specified item(s) from the menu. If the argument is an integer, then it specifies the position of the menu item to be removed.
static void setLightWeightPopupEnabled(boolean) | By default, Swing implements a menu's window using a lightweight component. This can cause problems if you use any heavyweight components in your Swing program, as described in Bringing Up a Popup Menu. (This is one of several reasons to avoid using heavyweight components.) As a workaround, invoke JPopupMenu.setLightWeightPopupEnabled(false).
void show(Component, int, int) | Display the popup menu at the specified x,y position (specified in that order by the integer arguments) in the coordinate system of the specified component.

Implementing Menu Items
Constructor or Method | Purpose
JMenuItem()
JMenuItem(String)
JMenuItem(Icon)
JMenuItem(String, Icon)
JMenuItem(String, int)
JMenuItem(Action) 		Creates an ordinary menu item. The icon argument, if present, specifies the icon that the menu item should display. Similarly, the string argument specifies the text that the menu item should display. The integer argument specifies the keyboard mnemonic to use. You can specify any of the relevant VK constants defined in the KeyEvent class. For example, to specify the A key, use KeyEvent.VK_A.

The constructor with the Action parameter, which was introduced in 1.3, sets the menu item's Action, causing the menu item's properties to be initialized from the Action. See How to Use Actions for details.

JCheckBoxMenuItem()
JCheckBoxMenuItem(String)
JCheckBoxMenuItem(Icon)
JCheckBoxMenuItem(String, Icon)
JCheckBoxMenuItem(String, boolean)
JCheckBoxMenuItem(String, Icon, boolean) 		Creates a menu item that looks and acts like a check box. The string argument, if any, specifies the text that the menu item should display. If you specify true for the boolean argument, then the menu item is initially selected (checked). Otherwise, the menu item is initially unselected.
JRadioButtonMenuItem()
JRadioButtonMenuItem(String)
JRadioButtonMenuItem(Icon)
JRadioButtonMenuItem(String, Icon)
JRadioButtonMenuItem(String, boolean)
JRadioButtonMenuItem(Icon, boolean)
JRadioButtonMenuItem(String, Icon, boolean) 		Creates a menu item that looks and acts like a radio button. The string argument, if any, specifies the text that the menu item should display. If you specify true for the boolean argument, then the menu item is initially selected. Otherwise, the menu item is initially unselected.
void setState(boolean)
boolean getState()
(in JCheckBoxMenuItem) 		Set or get the selection state of a check box menu item.
void setEnabled(boolean) | If the argument is true, enable the menu item. Otherwise, disable the menu item.
void setMnemonic(int) | Set the mnemonic that enables keyboard navigation to the menu or menu item. Use one of the VK constants defined in the KeyEvent class.
void setAccelerator(KeyStroke) | Set the accelerator that activates the menu item.
void setActionCommand(String) | Set the name of the action performed by the menu item.
void addActionListener(ActionListener)
void addItemListener(ItemListener) 		Add an event listener to the menu item. See Handling Events from Menu Items for details.
void setAction(Action) | Set the Action associated with the menu item. See How to Use Actions for details.
Many of the preceding methods are inherited from AbstractButton. See The Button API for information about other useful methods that AbstractButton provides.

Examples that Use Menus

Menus are used in a few of our examples.

Example | Where Described | Notes
MenuLookDemo | This section (Creating Menus) | A simple example that creates all kinds of menus except popup menus, but doesn't handle events from the menu items.
MenuDemo | This section (Handling Events from Menu Items) | Adds event handling to MenuLookDemo.
PopupMenuDemo | This section (Bringing Up a Popup Menu) | Adds popup menus to MenuDemo.
MenuGlueDemo | This section (Customizing Menu Layout) | Demonstrates affecting menu layout by adding an invisible components to the menu bar.
MenuLayoutDemo | This section (Customizing Menu Layout) | Implements sideways-opening menus arranged in a vertical menu bar.
MenuSelectionManagerDemo — Adds highlight detection to MenuDemo. To see this feature, click a menu and then move the mouse over any menu item or submenu. Once per second, the text area will be updated with information about the currently highlighted menu item, not to be confused with the menu item that the user eventually chooses. This demo uses the default MenuSelectionManager, which tracks the state of the menu hierarchy.
ActionDemo | How to Use Actions | Uses Action objects to implement menu items that duplicate functionality provided by tool bar buttons.
Framework — Brings up multiple identical frames, each with a menu in its menu bar.
InternalFrameDemo | How to Use Internal Frames | Uses a menu item to create windows.
DragColorTextFieldDemo | Introduction to DnD | Sets up menu items for cut/copy/paste.
DragPictureDemo | Introduction to DnD | Sets up menu items for cut/copy/paste with a non-text component.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Lists
Next page: How to Use Panels


How to Use Panels (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Panels
The JPanel class provides general-purpose containers for lightweight components. By default, panels do not add colors to anything except their own background; however, you can easily add borders to them and otherwise customize their painting. Details can be found in Performing Custom Painting.

In many types of look and feel, panels are opaque by default. Opaque panels work well as content panes and can help with painting efficiently, as described in Using Top-Level Containers. You can change a panel's transparency by invoking the setOpaque method. A transparent panel draws no background, so that any components underneath show through.

An Example

The following picture shows a colored version of the Converter application, which is discussed in more detail in Using Models.

The Converter example uses panels in several ways:
  • One JPanel instance — colored red in the preceding snapshot — serves as a content pane for the application's frame. This content pane uses a top-to-bottom BoxLayout to lay out its contents, and an empty border to put 5 pixels of space around them. See Using Top-Level Containers for information about content panes.
  • Two instances of a custom JPanel subclass named ConversionPanel — colored cyan — are used to contain components and coordinate communication between components. These ConversionPanel panels also have titled borders, which describe their contents and enclose the contents with a line. Each ConversionPanel panel uses a left-to-right BoxLayout object to lay out its contents.
  • In each ConversionPanel, a JPanel instance — colored magenta — is used to ensure the proper size and position of the combo box. Each of these JPanel instances uses a top-to-bottom BoxLayout object (helped by an invisible space-filling component) to lay out the combo box.
  • In each ConversionPanel, an instance of an unnamed JPanel subclass — colored blue — groups two components (a text field and a slider) and restricts their size. Each of these JPanel instances uses a top-to-bottom BoxLayout object to lay out its contents.
Here is what the Converter application normally looks like.

As the Converter example demonstrates, panels are useful for grouping components, simplifying component layout, and putting borders around groups of components. The rest of this section gives hints on grouping and laying out components. For information about using borders, see How to Use Borders.

Setting the Layout Manager

Like other containers, a panel uses a layout manager to position and size its components. By default, a panel's layout manager is an instance of FlowLayout, which places the panel's contents in a row. You can easily make a panel use any other layout manager by invoking the setLayout method or by specifying a layout manager when creating the panel. The latter approach is preferable for performance reasons, since it avoids the unnecessary creation of a FlowLayout object.

Here is an example of how to set the layout manager when creating the panel.

JPanel p = new JPanel(new BorderLayout()); //PREFERRED!

This approach does not work with BoxLayout, since the BoxLayout constructor requires a pre-existing container. Here is an example that uses BoxLayout.

JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));

Adding Components

When you add components to a panel, you use the add method. Exactly which arguments you specify to the add method depend on which layout manager the panel uses. When the layout manager is FlowLayout, BoxLayout, GridLayout, or SpringLayout, you will typically use the one-argument add method, like this:
aFlowPanel.add(aComponent);
aFlowPanel.add(anotherComponent);
When the layout manager is BorderLayout, you need to provide an argument specifying the added component's position within the panel. For example:
aBorderPanel.add(aComponent, BorderLayout.CENTER);
aBorderPanel.add(anotherComponent, BorderLayout.PAGE_END);
With GridBagLayout you can use either add method, but you must somehow specify grid bag constraints for each component.

For information about choosing and using the standard layout managers, see Using Layout Managers.

The Panel API

The API in the JPanel class itself is minimal. The methods you are most likely to invoke on a JPanel object are those it inherits from its superclasses — JComponent, Container, and Component. The following tables list the API you are most likely to use, with the exception of methods related to borders and layout hints. For more information about the API that all JComponent objects can use, see The JComponent Class.

  • Creating a JPanel
  • Managing a Container's Components
  • Setting or Getting the Layout Manager
Creating a JPanel
Constructor Purpose
JPanel()
JPanel(LayoutManager) 		Creates a panel. The LayoutManager parameter provides a layout manager for the new panel. By default, a panel uses a FlowLayout to lay out its components.

Managing a Container's Components
Method | Purpose
void add(Component)
void add(Component, int)
void add(Component, Object)
void add(Component, Object, int)
void add(String, Component) 		Adds the specified component to the panel. When present, the int parameter is the index of the component within the container. By default, the first component added is at index 0, the second is at index 1, and so on. The Object parameter is layout manager dependent and typically provides information to the layout manager regarding positioning and other layout constraints for the added component. The String parameter is similar to the Object parameter.
int getComponentCount() | Gets the number of components in this panel.
Component getComponent(int)
Component getComponentAt(int, int)
Component getComponentAt(Point)
Component[] getComponents() 		Gets the specified component or components. You can get a component based on its index or x, y position.
void remove(Component)
void remove(int)
void removeAll() 		Removes the specified component(s).

Setting or Getting the Layout Manager
Method Purpose
void setLayout(LayoutManager)
LayoutManager getLayout() 		Sets or gets the layout manager for this panel. The layout manager is responsible for positioning the panel's components within the panel's bounds according to some philosophy.

Examples That Use Panels

Many examples contained in this lesson use JPanel objects. The following table lists a few.

Example | Where Described | Notes
Converter | This section | Uses five panels, four of which use BoxLayout and one of which uses GridLayout. The panels use borders and, as necessary, size and alignment hints to affect layout.
ListDemo | How to Use Lists | Uses a panel, with its default FlowLayout manager, to center three components in a row.
ToolBarDemo | How to Use Tool Bars | Uses a panel as a content pane. The panel contains three components, laid out by BorderLayout.
BorderDemo | How to Use Borders | Contains many panels that have various kinds of borders. Several panels use BoxLayout.
BoxLayoutDemo | How to Use BoxLayout | Illustrates the use of a panel with Swing's BoxLayout manager.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Menus
Next page: How to Use Password Fields


How to Use Password Fields (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Password Fields
The JPasswordField class, a subclass of JTextField, provides specialized text fields for password entry. For security reasons, a password field does not show the characters that the user types. Instead, the field displays a character different from the one typed, such as an asterisk '*'. As another security precaution, a password field stores its value as an array of characters, rather than as a string. Like an ordinary text field, a password field fires an action event when the user indicates that text entry is complete, for example by pressing the Enter button.

Here is a picture of a demo that opens a small window and prompts the user to type in a password.

A snapshot of PasswordDemo, which uses a password field

Click the Launch button to run PasswordDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the PasswordDemo Application

The password is "bugaboo". You can find the entire code for this program in PasswordDemo.java. Here is the code that creates and sets up the password field:
passwordField = new JPasswordField(10);
passwordField.setActionCommand(OK);
passwordField.addActionListener(this);
The argument passed into the JPasswordField constructor indicates the preferred size of the field, which is at least 10 columns wide in this case. By default a password field displays a dot for each character typed. If you want to change the echo character, call the setEchoChar method. The code then adds an action listener to the password field, which checks the value typed in by the user. Here is the implementation of the action listener's actionPerformed method:
public void actionPerformed(ActionEvent e) {
    String cmd = e.getActionCommand();

    if (OK.equals(cmd)) { //Process the password.
        char[] input = passwordField.getPassword();
        if (isPasswordCorrect(input)) {
            JOptionPane.showMessageDialog(controllingFrame,
                "Success! You typed the right password.");
        } else {
            JOptionPane.showMessageDialog(controllingFrame,
                "Invalid password. Try again.",
                "Error Message",
                JOptionPane.ERROR_MESSAGE);
        }

        //Zero out the possible password, for security.
        Arrays.fill(input, '0');

        passwordField.selectAll();
        resetFocus();
    } else ...//handle the Help button...
}
Security note: Although the JPasswordField class inherits the getText method, you should use the getPassword method instead. Not only is getText less secure, but in the future it might return the visible string (for example, "******") instead of the typed string.

To further enhance security, once you are finished with the character array returned by the getPassword method, you should set each of its elements to zero. The preceding code snippet shows how to do this.

A program that uses a password field typically validates the password before completing any actions that require the password. This program calls a private method, isPasswordCorrect, that compares the value returned by the getPassword method to a value stored in a character array. Here is its code:

private static boolean isPasswordCorrect(char[] input) {
    boolean isCorrect = true;
    char[] correctPassword = { 'b', 'u', 'g', 'a', 'b', 'o', 'o' };

    if (input.length != correctPassword.length) {
        isCorrect = false;
    } else {
        isCorrect = Arrays.equals (input, correctPassword);
    }

    //Zero out the password.
    Arrays.fill(correctPassword,'0');

    return isCorrect;
}

The Password Field API

The following tables list the commonly used JPasswordField constructors and methods. For information on the API that password fields inherit, see How to Use Text Fields.

Commonly Used JPasswordField Constructors and Methods
Constructor or Method | Purpose
JPasswordField()
JPasswordField(String)
JPasswordField(String, int)
JPasswordField(int)
JPasswordField(Document, String, int) 		Creates a password field. When present, the int argument specifies the desired width in columns. The String argument contains the field's initial text. The Document argument provides a custom model for the field.
char[] getPassword() | Returns the password as an array of characters.
void setEchoChar(char)
char getEchoChar() 		Sets or gets the echo character which is displayed instead of the actual characters typed by the user.
void addActionListener(ActionListener)
void removeActionListener(ActionListener)
(defined in JTextField) 		Adds or removes an action listener.
void selectAll()
(defined in JTextComponent) 		Selects all characters in the password field.

Examples That Use Password Fields

PasswordDemo is the Tutorial's only example that uses a JPasswordField object. However, the Tutorial has many examples that use JTextField objects, whose API is inherited by JPasswordField. See Examples That Use Text Fields for further information.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Panels
Next page: How to Use Progress Bars


How to Use Progress Bars (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Progress Bars
Sometimes a task running within a program might take a while to complete. A user-friendly program provides some indication to the user that the task is occurring, how long the task might take, and how much work has already been done. One way of indicating work, and perhaps the amount of progress, is to use an animated image.

Another way of indicating work is to set the wait cursor, using the Cursor class and the Component-defined setCursor method. For example, the following code makes the wait cursor be displayed when the cursor is over container (including any components it contains that have no cursor specified):

container.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
To convey how complete a task is, you can use a progress bar like this one: -->

A typical progress bar

Sometimes you can't immediately determine the length of a long-running task, or the task might stay stuck at the same state of completion for a long time. You can show work without measurable progress by putting the progress bar in indeterminate mode. A progress bar in indeterminate mode displays animation to indicate that work is occurring. As soon as the progress bar can display more meaningful information, you should switch it back into its default, determinate mode. In the Java look and feel, indeterminate progress bars look like this:

An indeterminate progress bar

Swing provides three classes to help you use progress bars:

JProgressBar
A visible component to graphically display how much of a total task has completed. See Using Determinate Progress Bars for information and an example of using a typical progress bar. The section Using Indeterminate Mode tells you how to animate a progress bar to show activity before the task's scope is known.
ProgressMonitor
Not a visible component. Instead, an instance of this class monitors the progress of a task and pops up a dialog if necessary. See How to Use Progress Monitors for details and an example of using a progress monitor.
ProgressMonitorInputStream
An input stream with an attached progress monitor, which monitors reading from the stream. You use an instance of this stream like any of the other input streams described in Basic I/O. You can get the stream's progress monitor with a call to getProgressMonitor and configure it as described in How to Use Progress Monitors.
After you see a progress bar and a progress monitor in action, Deciding Whether to Use a Progress Bar or a Progress Monitor can help you figure out which is appropriate for your application.

Using Determinate Progress Bars
Here's a picture of a small demo application that uses a progress bar to measure the progress of a task that runs in its own thread:

A snapshot of ProgressBarDemo, which uses a progress bar

Try this:
  • Click the Launch button to run the ProgressBar Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ProgressBar Demo example

Below is the code from ProgressBarDemo.java that creates and sets up the progress bar:
//Where member variables are declared:
JProgressBar progressBar;
...
//Where the GUI is constructed:
progressBar = new JProgressBar(0, task.getLengthOfTask());
progressBar.setValue(0);
progressBar.setStringPainted(true);
The constructor that creates the progress bar sets the progress bar's minimum and maximum values. You can also set these values with setMinimum and setMaximum. The minimum and maximum values used in this program are 0 and the length of the task, which is typical of many programs and tasks. However, a progress bar's minimum and maximum values can be any value, even negative. The code snippet also sets the progress bar's current value to 0.

The call to setStringPainted causes the progress bar to display, within its bounds, a textual indication of the percentage of the task that has completed. By default, the progress bar displays the value returned by its getPercentComplete method formatted as a percent, such as 33%. Alternatively, you can replace the default with a different string by calling setString. For example,

if (/*...half way done...*/)
    progressBar.setString("Half way there!");

When the user clicks Start, an instance of the inner class Task is created and executed.

public void actionPerformed(ActionEvent evt) {
    startButton.setEnabled(false);
    setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
    done = false;
    task = new Task();
    task.addPropertyChangeListener(this);
    task.execute();
}
Task is a subclass of javax.swing.SwingWorker. The Task instance does three important things for ProgressBarDemo:
  1. The instance invokes the doInBackground in a separate thread. This is where the long-running task is actually executed. Using a background thread instead of the event-dispatching thread prevents the user interface from freezing while the task is running.
  2. When the background task is complete, the instance invokes the done method in the event-dispatching thread.
  3. The instance maintains a bound property, progress, that is updated to indicate the progress of the task. The propertyChange method is invoked each time progress changes.
See Worker Threads and SwingWorker in Concurrency in Swing for more information about SwingWorker.

The background task in ProgressBarDemo simulates a real task by reporting random amounts of progress at random intervals. The propertyChange method responds to changes in the the task's progress property by updating the progress bar:

public void propertyChange(PropertyChangeEvent evt) {
    if (!done) {
        int progress = task.getProgress();
        progressBar.setValue(progress);
        taskOutput.append(String.format(
                "Completed %d%% of task.\n", progress));
    }

When the background task is complete, the task's done method resets the progress bar:

public void done() {
    //Tell progress listener to stop updating progress bar.
    done = true;
    Toolkit.getDefaultToolkit().beep();
    startButton.setEnabled(true);
    setCursor(null); //turn off the wait cursor
    progressBar.setValue(progressBar.getMinimum());
    taskOutput.append("Done!\n");
}
Note that the done method sets the done field to true, preventing propertyChange from making further updates to the progress bar. This is necessary because the final updates to the progress property may occcur after done is invoked.

Using Indeterminate Mode
In ProgressBarDemo2 indeterminate mode is set until actual progress begins:
public void propertyChange(PropertyChangeEvent evt) {
    if (!done) {
        int progress = task.getProgress();
        if (progress == 0) {
            progressBar.setIndeterminate(true);
            taskOutput.append("No progress yet\n");
        } else {
            progressBar.setIndeterminate(false);
            progressBar.setString(null);
            progressBar.setValue(progress);
            taskOutput.append(String.format(
                    "Completed %d%% of task.\n", progress));
        }
    }
}

The other changes in the code are related to string display. A progress bar that displays a string is likely to be taller than one that doesn't, and, as the demo designers, we've arbitarily decided that this progress bar should display a string only when it's in the default, determinate mode. However, we want to avoid the layout ugliness that might result if the progress bar changed height when it changed modes. Thus, the code leaves in the call to setStringPainted(true) but adds a call to setString("") so that no text will be displayed. Later, when the progress bar switches from indeterminate to determinate mode, invoking setString(null) makes the progress bar display its default string.

One change we did not make was removing the call to progressBar.setValue from the progress event handler. The call doesn't do any harm because an indeterminate progress bar doesn't use its value property, except perhaps to display it in the status string. In fact, keeping the progress bar's data as up-to-date as possible is a good practice, since some look and feels might not support indeterminate mode.

Try this:
  1. Click the Launch button to run the ProgressBar2 Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ProgressBar2 Demo example
  2. Push the Start button. Note that the progress bar starts animating as soon as the button is pressed, and then switches back into determinate mode (like ProgressBarDemo).

How to Use Progress Monitors
Now let's rewrite ProgressBarDemo to use a progress monitor instead of a progress bar. Here's a picture of the new demo program, ProgressMonitorDemo:

A snapshot of ProgressMonitorDemo and a dialog brought up by a progress monitor

Try this:
  1. Click the Launch button to run the ProgressMonitor Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ProgressMonitor Demo example
  2. Push the Start button. After a certain amount of time, the program displays a progress dialog.
  3. Click the OK button. Note that the task continues even though the dialog is gone.
  4. Start another task. After the dialog pops up, click the Cancel button. The dialog goes away and the task stops.

A progress monitor cannot be used again, so a new one must be created each time a new task is started. This program creates a progress monitor each time the user starts a new task with the Start button.

Here's the statement that creates the progress monitor:

progressMonitor = new ProgressMonitor(ProgressMonitorDemo.this,
                                      "Running a Long Task",
                                      "", 0, task.getLengthOfTask());
This code uses ProgressMonitor's only constructor to create the monitor and initialize several arguments:
  • The first argument provides the parent component to the dialog popped up by the progress monitor.
  • The second argument is a string that describes the nature of the task being monitored. This string is displayed on the dialog. see The Progress Monitoring API for details about this argument.
  • The third argument is another string that provides a changeable status note. The example uses an empty string to indicate that the dialog should make space for a changeable status note, but that the note is initially empty. If you provide null for this argument, the note is omitted from the dialog. The example updates the note each time the progress property changes. It updates the monitor's current value at the same time:
    int progress = task.getProgress();
String message = String.format("Completed %d%%.\n", progress);
progressMonitor.setNote(message);
progressMonitor.setProgress(progress);
taskOutput.append(message);
  • The last two arguments provide the minimum and maximum values, respectively, for the progress bar displayed in the dialog.
By default, a progress monitor waits a minium of 500 milliseconds before deciding whether to pop up the dialog. It also waits for the progress to become more than the minimum value. If it calculates that the task will take more than 2000 milliseconds to complete, the progress dialog appears. To adjust the minimum waiting period, invoke setMillisToDecidedToPopup. To adjust the minimum progress time required for a dialog to appear, invoke setMillisToPopup.

By the simple fact that this example uses a progress monitor, it adds a feature that wasn't present in the version of the program that uses a progress bar: The user can cancel the task by clicking the Cancel button on the dialog. Here's the code in the example that checks to see if the user canceled the task or if the task exited normally:

if (progressMonitor.isCanceled() || task.isDone()) {
    progressMonitor.close();
    Toolkit.getDefaultToolkit().beep();
    if (progressMonitor.isCanceled()) {
        task.cancel(true);
        taskOutput.append("Task canceled.\n");
    } else {
        taskOutput.append("Task completed.\n");
    }
    startButton.setEnabled(true);
}
Note that the progress monitor doesn't itself cancel the task. It provides the GUI and API to allow the program to do so easily.

Deciding Whether to Use a Progress Bar or a Progress Monitor
Use a progress bar if:
  • You want more control over the configuration of the progress bar. If you are working directly with a progress bar, you can set it to be indeterminate, make it display vertically, provide a string for it to display, register change listeners on it, and provide it with a bounded range model to control the progress bar's minimum, maximum, and current values.
  • The program needs to display other components along with the progress bar.
  • You need more than one progress bar. With some tasks, you need to monitor more than one parameter. For example, an installation program might monitor disk space usage in addition to how many files have been successfully installed.
  • You need to reuse the progress bar. A progress bar can be reused; a progress monitor cannot. Once the progress monitor has decided to display a dialog (or not), the progress monitor cannot do it again.

Use a progress monitor if:

  • You want an easy way to display progress in a dialog.
  • The running task is secondary and the user might not be interested in the progress of the task. Progress monitor provides a way for the user to dismiss the dialog while the task is still running.
  • You want an easy way for the task to be cancelled. Progress monitor provides a GUI for the user to cancel the task. All you have to do is call progress monitor's isCanceled method to find out if the user pressed the Cancel button.
  • Your task displays a short message periodically while running. The progress monitor dialog provides the setNote method so that the task can provide further information about what it's doing. For example, an installation task might report the name of each file as it's installed.
  • The task might not take a long time to complete. You decide at what point a running task is taking long enough to warrant letting the user know about it. Progress monitor won't pop up a dialog if the task completes within the timeframe you set.
If you decide to use a progress monitor and the task you are monitoring is reading from an input stream, use the ProgressMonitorInputStream class.

The Progress Monitoring API

The following tables list the commonly used API for using progress bars and progress monitors. Because JProgressBar is a subclass of JComponent, other methods you are likely to call on a JProgressBar are listed in The JComponent Class. Note that ProgressMonitor is a subclass of Object and is not a visual component.

The API for monitoring progress falls into these categories:

  • Creating the Progress Bar
  • Setting or Getting the Progress Bar's Constraints/Values
  • Controlling the Progress Bar's Appearance
  • Creating the Progress Monitor
  • Configuring the Progress Monitor
  • Terminating the Progress Monitor

Creating the Progress Bar
Constructor | Purpose
JProgressBar()
JProgressBar(int, int) 		Create a horizontal progress bar. The no-argument constructor initializes the progress bar with a minimum and initial value of 0 and a maximum of 100. The constructor with two integer arguments specifies the minimum and maximum values.
JProgressBar(int)
JProgressBar(int, int, int) 		Create a progress bar with the specified orientation, which can be either JProgressBar.HORIZONTAL or JProgressBar.VERTICAL. The optional second and third arguments specify minimum and maximum values.
JProgressBar(BoundedRangeModel) | Create a horizontal progress bar with the specified range model.

Setting or Getting the Progress Bar's Constraints/Values
Method | Purpose
void setValue(int)
int getValue() 		Set or get the current value of the progress bar. The value is constrained by the minimum and maximum values.
double getPercentComplete() | Get the percent complete for the progress bar.
void setMinimum(int)
int getMinimum() 		Set or get the minimum value of the progress bar.
void setMaximum(int)
int getMaximum() 		Set or get the maximum value of the progress bar.
void setModel(BoundedRangeModel)
BoundedRangeModel getModel() 		Set or get the model used by the progress bar. The model establishes the progress bar's constraints and values, so you can use it directly as an alternative to using the individual set/get methods listed above.

Controlling the Progress Bar's Appearance
Method | Purpose
void setIndeterminate(boolean) | By specifying true, put the progress bar into indeterminate mode. Specifying false puts the progress bar back into its default, determinate mode.
void setOrientation(int)
int getOrientation() 		Set or get whether the progress bar is vertical or horizontal. Acceptable values are JProgressBar.VERTICAL or JProgressBar.HORIZONTAL.
void setBorderPainted(boolean)
boolean isBorderPainted() 		Set or get whether the progress bar has a border.
void setStringPainted(boolean)
boolean isStringPainted() 		Set or get whether the progress bar displays a percent string. By default, the value of the percent string is the value returned by getPercentComplete formatted as a percent. You can set the string to be displayed with setString.
void setString(String)
String getString() 		Set or get the percent string.

Creating the Progress Monitor
Method or Constructor | Purpose
ProgressMonitor(Component, Object, String, int, int) | Create a progress monitor. The Component argument is the parent for the monitor's dialog. The Object argument is a message to put on the option pane within the dialog. The value of this object is typically a String. The String argument is a changeable status note. The final two int arguments set the minimum and maximum values, respectively, for the progress bar used in the dialog.
ProgressMonitor getProgressMonitor()
(in ProgressMonitorInputStream) 		Gets a progress monitor that monitors reading from an input stream.

Configuring the Progress Monitor
Method | Purpose
void setMinimum(int)
int getMinimum() 		Set or get the minimum value of the progress monitor. This value is used by the monitor to set up the progress bar in the dialog.
void setMaximum(int)
int getMaximum() 		Set or get the maximum value of the progress monitor. This value is used by the monitor to set up the progress bar in the dialog.
void setProgress(int) | Update the monitor's progress.
void setNote(String)
String getNote() 		Set or get the status note. This note is displayed on the dialog. To omit the status note from the dialog, provide null as the third argument to the monitor's constructor.
void setMillisToDecideToPopup(int)
int getMillisToDecideToPopup() 		Set or get the time after which the monitor should decide whether to popup a dialog.

Terminating the Progress Monitor
Method | Purpose
void close() | Close the progress monitor. This disposes of the dialog.
boolean isCanceled() | Determine whether the user pressed the Cancel button.

Examples that Monitor Progress

This following examples use JProgressBar or ProgressMonitor.

Example | Where Described | Notes
ProgressBarDemo | This section | Uses a basic progress bar to show progress on a task running in a separate thread.
ProgressBarDemo2 | This section | Uses a basic progress bar to show progress on a task running in a separate thread.
ProgressMonitorDemo | This section | Modification of the previous example that uses a progress monitor instead of a progress bar.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Password Fields
Next page: How to Use Root Panes


How to Use Root Panes (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Root Panes
In general, you don't directly create a JRootPane object. Instead, you get a JRootPane (whether you want it or not!) when you instantiate JInternalFrame or one of the top-level Swing containers, such as JApplet, JDialog, and JFrame.

Using Top-Level Containers tells you the basics of using root panes — getting the content pane, setting its layout manager, and adding Swing components to it. This section tells you more about root panes, including the components that make up a root pane and how you can use them.

A root pane manages four other panes: a layered pane, a menu bar, a content pane, and a glass pane.

As the preceding figure shows, a root pane has four parts:
The glass pane
Hidden, by default. If you make the glass pane visible, then it's like a sheet of glass over all the other parts of the root pane. It's completely transparent unless you implement the glass pane's paintComponent method so that it does something, and it can intercept input events for the root pane. In the next section, you'll see an example of using a glass pane.
The layered pane
Serves to position its contents, which consist of the content pane and the optional menu bar. Can also hold other components in a specified Z order. For information, see The Layered Pane.
The content pane
The container of the root pane's visible components, excluding the menu bar. For information on using the content pane, see Using Top-Level Containers.
The optional menu bar
The home for the root pane's container's menus. If the container has a menu bar, you generally use the container's setJMenuBar method to put the menu bar in the appropriate place. For more information on using menus and menu bars, see How to Use Menus.

The Glass Pane

The glass pane is useful when you want to be able to catch events or paint over an area that already contains one or more components. For example, you can deactivate mouse events for a multi-component region by having the glass pane intercept the events. Or you can display an image over multiple components using the glass pane.

Here's a picture of an application that demonstrates glass pane features. It contains a check box that lets you set whether the glass pane is "visible" — whether it can get events and paint itself onscreen. When the glass pane is visible, it blocks all input events from reaching the components in the content pane. It also paints a red dot in the place where it last detected a mouse-pressed event.

A snapshot of GlassPaneDemo

Try this:
  1. Click the Launch button to run GlassPaneDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the GlassPaneDemo example

  2. Click Button 1.
    The button's appearance changes to show that it's been clicked.
  3. Click the check box so that the glass pane becomes "visible," and then click Button 1 again.
    The button does not act clicked because the glass pane intercepts all the mouse events. The glass pane paints a red circle where you release the mouse.
  4. Click the check box again so that the glass pane is hidden.
    When the glass pane detects an event over the check box, it forwards it to the check box. Otherwise, the check box would not respond to clicks.

The following code from GlassPaneDemo.java shows and hides the glass pane. This program happens to create its own glass pane. However, if a glass pane doesn't do any painting, the program might simply attach listeners to the default glass pane, as returned by getGlassPane.

myGlassPane = new MyGlassPane(...);
changeButton.addItemListener(myGlassPane);
frame.setGlassPane(myGlassPane);
...
class MyGlassPane extends JComponent
                  implements ItemListener {
    ...
    //React to change button clicks.
    public void itemStateChanged(ItemEvent e) {
        setVisible(e.getStateChange() == ItemEvent.SELECTED);
    }
...
}

The next code snippet implements the mouse-event handling for the glass pane. If a mouse event occurs over the check box, then the glass pane redispatches the event so that the check box receives it.

...//In the implementation of the glass pane's mouse listener:
public void mouseMoved(MouseEvent e) {
    redispatchMouseEvent(e, false);
}

.../* The mouseDragged, mouseClicked, mouseEntered,
    * mouseExited, and mousePressed methods have the same
    * implementation as mouseMoved. */...

public void mouseReleased(MouseEvent e) {
    redispatchMouseEvent(e, true);
}

private void redispatchMouseEvent(MouseEvent e,
                                  boolean repaint) {
    Point glassPanePoint = e.getPoint();
    Container container = contentPane;
    Point containerPoint = SwingUtilities.convertPoint(
                                    glassPane,
                                    glassPanePoint,
                                    contentPane);

    if (containerPoint.y < 0) { //we're not in the content pane
        //Could have special code to handle mouse events over
        //the menu bar or non-system window decorations, such as
        //the ones provided by the Java look and feel.
    } else {
        //The mouse event is probably over the content pane.
        //Find out exactly which component it's over.
        Component component =
            SwingUtilities.getDeepestComponentAt(
                                    container,
                                    containerPoint.x,
                                    containerPoint.y);

        if ((component != null)
            && (component.equals(liveButton))) {
            //Forward events over the check box.
            Point componentPoint = SwingUtilities.convertPoint(
                                        glassPane,
                                        glassPanePoint,
                                        component);
            component.dispatchEvent(new MouseEvent(component,
                                                 e.getID(),
                                                 e.getWhen(),
                                                 e.getModifiers(),
                                                 componentPoint.x,
                                                 componentPoint.y,
                                                 e.getClickCount(),
                                                 e.isPopupTrigger()));
        }
    }

    //Update the glass pane if requested.
    if (repaint) {
        glassPane.setPoint(glassPanePoint);
        glassPane.repaint();
    }
}
Here is the code in MyGlassPane that implements the painting.
protected void paintComponent(Graphics g) {
    if (point != null) {
        g.setColor(Color.red);
        g.fillOval(point.x - 10, point.y - 10, 20, 20);
    }
}

The Layered Pane

A layered pane is a container with depth such that overlapping components can appear one on top of the other. General information about layered panes is in How to Use Layered Panes. This section discusses the particulars of how root panes use layered panes.

Each root pane places its menu bar and content pane in an instance of JLayeredPane. The Z ordering that the layered pane provides enables behavior such as displaying popup menus above other components.

You can choose to put components in the root pane's layered pane. If you do, then you should be aware that certain depths are defined to be used for specific functions, and you should use the depths as intended. Otherwise, your components might not play well with the others. Here's a diagram that shows the functional layers and their relationship:

Layers defined by JLayeredPane

The table below describes the intended use for each layer and lists the JLayeredPane constant that corresponds to each layer:
Layer Name | Value | Description
FRAME_CONTENT_LAYER | new Integer(-30000) | The root pane adds the menu bar and content pane to its layered pane at this depth.
DEFAULT_LAYER | new Integer(0) | If you don't specify a component's depth when adding it to a layered pane, the layered pane puts it at this depth.
PALETTE_LAYER | new Integer(100) | This layer is useful for floating tool bars and palettes.
MODAL_LAYER | new Integer(200) | Modal internal-frame dialogs would belong in this layer.
POPUP_LAYER | new Integer(300) | Popups go in this layer because they need to appear above just about everything.
DRAG_LAYER | new Integer(400) | Intended to be used when a component is being dragged. The component should return to its regular layer when dropped.

Here is a picture of RootLayeredPaneDemo, which is a version of LayeredPaneDemo that uses the root pane's layered pane, rather than creating a new layered pane.

LayeredPaneDemo modified to use the root pane's layered pane

Try this:
  1. Click the Launch button to run RootLayeredPaneDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the RootLayeredPaneDemo

  2. Move the cursor around in the window, so that Duke moves on top of other components.
    Note that when the cursor is on top of non-label components — whether it's in the content pane or in the Java-look-and-feel provided title bar — Duke's movement is temporarily stopped. This is because mouse-motion events go to the component that's deepest in the containment hierarchy and is interested in mouse events. The mouse-motion listener that moves Duke is registered on the layered pane, and most of the components in that pane (with the exception of the labels) happen to have mouse-motion listeners. When the mouse moves over an interested component in the layered pane, the layered pane doesn't get the event and the interested component does.
  3. Making sure the Top Position in Layer check box is selected, change Duke's layer to Yellow (-30000).
    As before, he appears on top of other components, except for the Magenta (0) and Cyan (301) rectangles.
  4. Keeping Duke in the Yellow layer, click the check box to send Duke to the back of layer -30000.
    Duke disappears because the content pane and all the components in it are now above him.
  5. Change Duke's layer to Cyan (301), move Duke down a bit so he's standing on the top edge of the Yellow rectangle, and then press Space to bring up the combo box's drop-down list.
    If the look and feel implements the drop-down list as a lightweight popup, Duke appears on top of the drop-down list.

The Root Pane API

The tables that follow list the API for using root panes, glass panes, and content panes. For more information on using content panes, go to Using Top-Level Containers. Here are the tables in this section:
  • Using a Root Pane
  • Setting or Getting the Root Pane's Contents

The API for using other parts of the root pane is described elsewhere:

  • The Layered Pane API
  • The Menu API

Using a Root Pane
Method Purpose
JRootPane getRootPane()
(in JApplet, JDialog, JFrame, JInternalFrame, and JWindow) 		Get the root pane of the applet, dialog, frame, internal frame, or window.
static JRootPane getRootPane(Component)
(in SwingUtilities) 		If the component contains a root pane, return that root pane. Otherwise, return the root pane (if any) that contains the component.
JRootPane getRootPane()
(in JComponent) 		Invoke the SwingUtilities getRootPane method for the JComponent.
void setDefaultButton(JButton)
JButton getDefaultButton() 		Set or get which button (if any) is the default button in the root pane. A look-and-feel-specific action, such as pressing Enter, causes the button's action to be performed.

Setting or Getting the Root Pane's Contents
The following methods are defined in JApplet, JDialog, JFrame, JInternalFrame, JRootPane, and JWindow, unless noted otherwise.
Method Purpose
void setGlassPane(Component)
Component getGlassPane() 		Set or get the glass pane.
void setLayeredPane(JLayeredPane)
Container getLayeredPane() 		Set or get the layered pane.
void setContentPane(Container)
Container getContentPane() 		Set or get the content pane.
void setJMenuBar(JMenuBar)
JMenuBar getJMenuBar()
(not defined in JWindow) 		Set or get the menu bar.

Examples that Use Root Panes

Every Swing program has a root pane, but few reference it directly. The examples in the following list illustrate how to use features of JRootPane or the glass pane. Also see these lists:
  • Examples that Use Layered Panes
  • Examples that Use Menus
  • Examples that Use Frames (for examples of using content panes)

Example | Where Described | Notes
GlassPaneDemo | This section | Uses a glass pane that paints a bit and redispatches events.
RootLayeredPaneDemo | This section | Adapts LayeredPaneDemo to use the root pane's layered pane.
ListDialog | How to Use Lists | Sets the default button for a JDialog.
FrameDemo2 | How to Make Frames | Sets the default button for a JFrame.
DragFileDemo | Introduction to DnD | Sets the default button for whatever root pane contains an instance of a particular JPanel subclass. Uses the getRootPane method inherited from JComponent.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Progress Bars
Next page: How to Use Scroll Panes


How to Use Scroll Panes (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Scroll Panes
A JScrollPane provides a scrollable view of a component. When screen real estate is limited, use a scroll pane to display a component that is large or one whose size can change dynamically. Other containers used to save screen space include split panes and tabbed panes.

The code to create a scroll pane can be minimal. For example, here's a picture of a demo program that puts a text area in a scroll pane because the text area's size grows dynamically as text is appended to it:

A snapshot of ToolBarDemo

Here's the code that creates the text area, makes it the scroll pane's client, and adds the scroll pane to a container:

//In a container that uses a BorderLayout:
textArea = new JTextArea(5, 30);
...
JScrollPane scrollPane = new JScrollPane(textArea);
...
setPreferredSize(new Dimension(450, 110));
...
add(scrollPane, BorderLayout.CENTER);
The boldface line of code creates the JScrollPane, specifying the text area as the scroll pane's client. The program doesn't invoke any methods on the JScrollPane object, since the scroll pane handles everything automatically: creating the scroll bars when necessary, redrawing the client when the user moves the scroll knobs, and so on.

You might have noticed that the preceding code sets the preferred size of the scroll pane's container. In the Java look and feel, this preferred size happens to be a bit less tall than required for the text area to display the 5 rows that we requested when creating it, so the scroll bar initially displays a vertical scroll bar. If we didn't restrict the size of the scroll pane's container, the scroll pane would be big enough for the text area to display the full 5 rows and 30 columns specified with the JTextArea constructor. Refer to Sizing a Scroll Pane for information about techniques for making a scroll pane the size you want.

The rest of this section discusses the following topics:

  • How a Scroll Pane Works
  • Setting the Scroll Bar Policy
  • Providing Custom Decorations
  • Implementing a Scrolling-Savvy Client
  • Sizing a Scroll Pane
  • Dynamically Changing the Client's Size
  • The Scroll Pane API
  • Examples that Use Scroll Panes

How a Scroll Pane Works
Here is a snapshot of an application that uses a customized scroll pane to view a large photograph:

A snapshot of ScrollDemo

The scroll pane in this application looks very different from the one in the previous demo program. Rather than displaying text, this scroll pane contains a large image. The scroll pane also has two scroll bars, a row header, a column header, and four corners, three of which have been customized.
Try this::
  1. Click the Launch button to run ScrollDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ScrollDemo example

  2. Move the knobs on the scroll bars. Watch the image scroll and the horizontal and vertical rulers scroll along.
  3. If you have a mouse with a wheel (which is generally between the mouse buttons) use the mouse wheel to scroll the image vertically.
  4. Click the cm toggle in the upper left corner of the scroll pane. The units on the row and column headers change to inches (or back to centimeters).
  5. Click the arrow buttons on the scroll bars. Also, try clicking on the track above or below the knob on the vertical scroll bar, or to the left or right of the horizontal one.
  6. Move the cursor over the image and press the cursor. Continuing to press the cursor, drag to a point outside the image and pause. The visible area of the image moves toward the cursor. This scroll-by-dragging functionality is enabled by the scroll pane, and with the JComponent API, but it is implemented by the custom component that displays the image.
  7. Resize the window. Notice that the scroll bars disappear when the scroll pane is large enough to display the entire image and reappear again when the scroll pane is too small to show the entire image.
The ScrollDemo program establishes the scroll pane's client when creating the scroll pane:
//Where the member variables are declared:
private ScrollablePicture picture;
...
//Where the GUI is created:
picture = new ScrollablePicture( ... );
JScrollPane pictureScrollPane = new JScrollPane(picture);
The scroll pane's client is also known as the view or viewport view. You can change the client dynamically by calling the setViewportView method. Note that JScrollPane has no corresponding getViewportView method. If you need to refer to the client object again, you can either cache it in a variable or invoke getViewport().getViewportView() on the scroll pane.

When the user manipulates the scroll bars in a scroll pane, the area of the client that is visible changes accordingly. This picture shows the relationship between the scroll pane and its client and indicates the classes that the scroll pane commissions to help:

The architecture of a scroll pane

A scroll pane uses a JViewport instance to manage the visible area of the client. The viewport is responsible for positioning and sizing the client, based on the positions of the scroll bars, and displaying it.

A scroll pane may use two separate instances of JScrollBar for the scroll bars. The scroll bars provide the interface for the user to manipulate the visible area. The following figure shows the three areas of a scroll bar: the knob (sometimes called the thumb), the (arrow) buttons, and the track.

The parts of a scroll bar

When the user moves the knob on the vertical scroll bar up and down, the visible area of the client moves up and down. Similarly, when the user moves the knob on the horizontal scroll bar to the right and left, the visible area of the client moves back and forth accordingly. The position of the knob relative to its track is proportionally equal to the position of the visible area relative to the client. In the Java look and feel and some others, the size of the knob gives a visual clue as to how much of the client is visible.

By clicking a arrow button, the user can scroll by a unit increment. By clicking within the track, the user can scroll by a block increment. If the user has a mouse with a wheel, then the user can scroll vertically using the mouse wheel. The amount that the mouse wheel scrolls is platform dependent. For example, by default on Windows XP, the mouse wheel scrolls three unit increments; the Mouse control panel allows you to specify a different number of unit increments or to use a block increment instead. More information about unit and block increments is in Implementing a Scrolling-Savvy Client.

Typical programs don't directly instantiate or call methods on a viewport or scroll bar. Instead, programs achieve their scrolling behavior using the JScrollPane API and the API discussed in Implementing a Scrolling-Savvy Client. Some scrolling-savvy components such as JList, JTable, and JTree also provide additional API to help you affect their scrolling behavior.

Setting the Scroll Bar Policy
On startup, the scroll pane in the ScrollDemo application has two scroll bars. If you make the window very large, both scroll bars disappear because they are no longer needed. If you then shrink the height of the window without changing its width, the vertical scroll bar reappears. Further experimentation will show that in this application both scroll bars disappear and reappear as needed. This behavior is controlled by the scroll pane's scroll bar policy, Actually, it's two policies: each scroll bar has its own.

ScrollDemo doesn't explicitly set the scroll pane's scroll bar policies — it uses the default. You can set the policies when you create the scroll pane or change them dynamically.

Of the constructors provided by JScrollPane, these two let you set the scroll bar policies when you create the scroll pane:

JScrollPane(Component, int, int)
JScrollPane(int, int)
The first int specifies the policy for the vertical scroll bar; the second specifies the policy for the horizontal scroll bar. You can also set the policies dynamically with the setHorizontalScrollBarPolicy and setVerticalScrollBarPolicy methods. With both the constructors and the methods, use one of the following constants defined in the ScrollPaneConstants interface (which is implemented by JScrollPane):

Policy Description
VERTICAL_SCROLLBAR_AS_NEEDED
HORIZONTAL_SCROLLBAR_AS_NEEDED 		The default. The scroll bar appears when the viewport is smaller than the client and disappears when the viewport is larger than the client.
VERTICAL_SCROLLBAR_ALWAYS
HORIZONTAL_SCROLLBAR_ALWAYS 		Always display the scroll bar. The knob disappears if the viewport is large enough to show the whole client.
VERTICAL_SCROLLBAR_NEVER
HORIZONTAL_SCROLLBAR_NEVER 		Never display the scroll bar. Use this option if you don't want the user to directly control what part of the client is shown, or if you want them to use only non-scroll-bar techniques (such as dragging).

Providing Custom Decorations
The area drawn by a scroll pane consists of up to nine parts: the center, four sides, and four corners. The center is the only component that is always present in all scroll panes. Besides scroll bars, the sides can contain column and row headers. A corner component is visible only if both sides that intersect at that corner contain visible components.

Decorations on a scroll pane

As shown in the figure, the scroll pane in ScrollDemo has custom row and column headers. Additionally, because all four sides are populated, all four corners are present. The program customizes three of the corners — two just fill their area with the same color as the Rules, and the other contains a toggle button. The fourth corner, the lower right corner, is the default provided by the scroll pane. Notice that because the row and column headers are always present in this example, the toggle button is also always present.

If a corner contains a control that the user needs access to all the time, make sure the sides that intersect at the corner are always present. For example, if this application placed the toggle in the lower right corner where the scroll bars intersect, then the toggle would disappear if the user resized the window and even one of the scroll bars disappeared.

The scroll pane's row and column headers are provided by a custom JComponent subclass, Rule, that draws a ruler in centimeters or inches. Here's the code that creates and sets the scroll pane's row and column headers:

//Where the member variables are defined:
private Rule columnView;
private Rule rowView;
...
//Where the GUI is initialized:
ImageIcon david = createImageIcon("images/youngdad.jpeg");
...
//Create the row and column headers.
columnView = new Rule(Rule.HORIZONTAL, true);
rowView = new Rule(Rule.VERTICAL, true);

...
pictureScrollPane.setColumnHeaderView(columnView);
pictureScrollPane.setRowHeaderView(rowView);
You can use any component for a scroll pane's row and column headers. The scroll pane puts the row and column headers in JViewPorts of their own. Thus, when scrolling horizontally, the column header follows along, and when scrolling vertically, the row header follows along. Make sure the row and column have the same width and height as the view, because JScrollPane does not enforce these values to have the same size. If one differs from the other, you are likely to not get the desired behavior.

As a JComponent subclass, our custom Rule class puts its rendering code in its paintComponent method. The Rule rendering code takes care to draw only within the current clipping bounds, to ensure speedy scrolling. Your custom row and column headers should do the same.

You can also use any component for the corners of a scroll pane. ScrollDemo illustrates this by putting a toggle button in the upper left corner, and custom Corner objects in the upper right and lower left corners. Here's the code that creates the Corner objects and calls setCorner to place them:

//Create the corners.
JPanel buttonCorner = new JPanel(); //use FlowLayout
isMetric = new JToggleButton("cm", true);
isMetric.setFont(new Font("SansSerif", Font.PLAIN, 11));
isMetric.setMargin(new Insets(2,2,2,2));
isMetric.addItemListener(this);
buttonCorner.add(isMetric);
...
//Set the corners.
pictureScrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER,
                            buttonCorner);
pictureScrollPane.setCorner(JScrollPane.LOWER_LEFT_CORNER,
                            new Corner());
pictureScrollPane.setCorner(JScrollPane.UPPER_RIGHT_CORNER,
                            new Corner());

Remember that the size of each corner is determined by the size of the sides intersecting there. For some components you must take care that the specific instance of the component fits in its corner. For example, the program sets the font and margins on the toggle button so that it fits within the space established by the headers. It's not an issue with the Corner class because that class colors its entire bounds, whatever they happen to be, with a solid color.

As you can see from the code, constants indicate the corner positions. This figure shows the constant for each position:

The constants are defined in the ScrollPaneConstants interface, which JScrollPane implements.

Implementing a Scrolling-Savvy Client
To customize the way that a client component interacts with its scroll pane, you can make the component implement the Scrollable interface. By implementing Scrollable, a client can specify both the size of the viewport used to view it and the amount to scroll for clicks on the different controls on a scroll bar. You can also specify if the view should track the size of the viewport. This is typically used when the viewport is bigger than the view, but the view should fill the available space.
Note: If you can't or don't want to implement a scrollable client, you can specify the unit and block increments using the setUnitIncrement and setBlockIncrement methods of JScrollBar. For example, the following code sets the unit increment for vertical scrolling to 10 pixels:
scrollPane.getVerticalScrollBar().setUnitIncrement(10);

Here again are the three control areas of a scroll bar: the knob, the buttons, and the track.

The parts of a scroll bar

You might have noticed when manipulating the scroll bars in ScrollDemo that clicking the buttons scrolls the image to a tick boundary. You might also have noticed that clicking in the track scrolls the picture by a "screenful". More generally, the button scrolls the visible area by a unit increment and the track scrolls the visible area by a block increment. The behavior you see in the example is not the scroll pane's default behavior, but is specified by the client in its implementation of the Scrollable interface.

The client for the ScrollDemo program is ScrollablePicture. ScrollablePicture is a subclass of JLabel that provides implementations of all five Scrollable methods:

  • getScrollableBlockIncrement
  • getScrollableUnitIncrement
  • getPreferredScrollableViewportSize
  • getScrollableTracksViewportHeight
  • getScrollableTracksViewportWidth
ScrollablePicture implements the Scrollable interface primarily to affect the unit and block increments. However, it must provide implementations for all five methods. Thus, it provides reasonable defaults for the other three methods that you might want to copy for your scrolling-savvy classes.

The scroll pane calls the client's getScrollableUnitIncrement method whenever the user clicks one of the buttons on the scroll bar. This is true as long as the client implements Scrollable. This method returns the number of pixels to scroll. An obvious implementation of this method returns the number of pixels between tick marks on the header rulers. ScrollablePicture, however, does something different: It returns the value required to position the image on a tick mark boundary. Here's the implementation:

public int getScrollableUnitIncrement(Rectangle visibleRect,
                                      int orientation,
                                      int direction) {
    //Get the current position.
    int currentPosition = 0;
    if (orientation == SwingConstants.HORIZONTAL) {
        currentPosition = visibleRect.x;
    } else {
        currentPosition = visibleRect.y;
    }

    //Return the number of pixels between currentPosition
    //and the nearest tick mark in the indicated direction.
    if (direction < 0) {
        int newPosition = currentPosition -
                         (currentPosition / maxUnitIncrement)
                          * maxUnitIncrement;
        return (newPosition == 0) ? maxUnitIncrement : newPosition;
    } else {
        return ((currentPosition / maxUnitIncrement) + 1)
                 * maxUnitIncrement
                 - currentPosition;
    }
}
If the image is already on a tick mark boundary, this method returns the number of pixels between ticks. Otherwise, it returns the number of pixels from the current location to the nearest tick.

Likewise, the scroll pane calls the client's getScrollableBlockIncrement method each time the user clicks on the track, but only if the client implements Scrollable. Here's ScrollablePicture's implementation of this method:

public int getScrollableBlockIncrement(Rectangle visibleRect,
                                       int orientation,
                                       int direction) {
    if (orientation == SwingConstants.HORIZONTAL)
        return visibleRect.width - maxUnitIncrement;
    else
        return visibleRect.height - maxUnitIncrement;
}
This method returns the height of the visible rectangle minus a tick mark. This behavior is typical, but true if scrolling vertically, otherwise, it's the width.A block increment should be slightly smaller than the viewport to leave a little of the previous visible area for context. For example, a text area might leave one or two lines of text for context and a table might leave a row or column (depending on the scroll direction).

ScrollablePicture.java has one more bit of code that's not required by the Scrollable interface, but is common in scrollable components: a mouse motion listener that lets the user scroll the picture by dragging from it. The boldface code in the following snippet implements scrolling by dragging:

public class ScrollablePicture extends JLabel
                               implements Scrollable,
                                          MouseMotionListener {
    ...
    public ScrollablePicture(...) {
        ...
        setAutoscrolls(true); //enable synthetic drag events
        addMouseMotionListener(this); //handle mouse drags
    }
    ...
    public void mouseDragged(MouseEvent e) {
        //The user is dragging us, so scroll!
        Rectangle r = new Rectangle(e.getX(), e.getY(), 1, 1);
        scrollRectToVisible(r);
    }
...
}
This snippet scrolls the picture whenever the user drags from the picture to a location outside the picture and pauses. The setAutoscrolls method is defined by JComponent for the purpose of assisting — but not implementing — scrolling by dragging. Setting the autoscrolls property to true makes the component fire synthetic mouse-dragged events even when the mouse isn't moving (because it stopped, mid-drag, outside the component). It's up to the component's mouse motion listener to listen for these events and react accordingly.

Sizing a Scroll Pane
Unless you explicitly set a scroll pane's preferred size, the scroll pane computes it based on the preferred size of its nine components (the viewport, and, if present, the two scroll bars, the row and column headers, and the four corners). The largest factor, and the one most programmers care about, is the size of the viewport used to display the client.

If the client is not scrolling-savvy, then the scroll pane sizes itself so that the client displays at its preferred size. For typical unsavvy clients, this makes the scroll pane redundant. That is, the scroll pane has no scroll bars because the client's preferred size is big enough to display the entire client. In this case, if the client doesn't change size dynamically, you should probably limit the size of the scroll pane by setting its preferred size or the preferred size of its container.

If the client is scrolling-savvy, then the scroll pane uses the value returned by the client's getPreferredScrollableViewportSize method to compute the size of its viewport. Implementations of this method generally report a preferred size for scrolling that's smaller than the component's standard preferred size. For example, by default, the value returned by JList's implementation of getPreferredScrollableViewportSize is just big enough to display eight rows.

Scrolling-savvy classes, like lists, tables, text components, and trees, often provide one or more methods that let programmers affect the size returned from getPreferredScrollableViewportSize. For example, you can set the number of visible rows in a list or a tree by calling the setVisibleRowCount method. The list or tree takes care of figuring out the size needed to display that number of rows.

Refer to Methods in Other Classes Related to Scrolling for information about scrolling-related methods provided by classes other than JScrollPane. And remember — if you don't like the value that getPreferredScrollableViewportSize returns, you can always set the preferred size of the scroll pane or its container.

Dynamically Changing the Client's Size
Changing the size of a scroll pane's client is a two-step process. First, set the client's preferred size. Then, call revalidate on the client to let the scroll pane know that it should update itself and its scroll bars. Let's look at an example.

Here's a picture of an application that changes the client's size whenever the user places a circle whose bounds fall outside of the client's current bounds. The program also changes the client's size when the user clears the drawing area:

A snapshot of ScrollDemo2

You can find the full source code for this example in ScrollDemo2.java, which is based on an example provided by tutorial reader John Vella. You can run ScrollDemo2 ( download JDK 6).

Here's the code that changes the drawing area's size when necessary:

if (changed) {
    //Update client's preferred size because
    //the area taken up by the graphics has
    //gotten larger or smaller (if cleared).
    drawingArea.setPreferredSize(/* the new size */);

    //Let the scroll pane know to update itself
    //and its scroll bars.
    drawingArea.revalidate();
}
Note that when the client changes size, the scroll bars adjust. The scroll pane doesn't resize, nor does the viewport.

Refer to SplitPaneDemo for another example in which the client object changes size.

The Scroll Pane API

The following tables list the commonly used scroll-related constructors and methods. Other methods you are most likely to invoke on a JScrollPane object are those such as setPreferredSize that its superclasses provide. See The JComponent API for tables of commonly used inherited methods.

The API for using scroll panes falls into these categories:

  • Setting Up the Scroll Pane
  • Decorating the Scroll Pane
  • Implementing a Scrolling-Savvy Client
  • Methods in Other Classes Related to Scrolling

Setting Up the Scroll Pane
(JScrollPane constructors and methods)
Method or Constructor | Purpose
JScrollPane()
JScrollPane(Component)
JScrollPane(int, int)
JScrollPane(Component, int, int) 		Create a scroll pane. The Component parameter, when present, sets the scroll pane's client. The two int parameters, when present, set the vertical and horizontal scroll bar policies (respectively).
void setViewportView(Component) | Set the scroll pane's client.
void setVerticalScrollBarPolicy(int)
int getVerticalScrollBarPolicy() 		Set or get the vertical scroll policy. ScrollPaneConstants defines three values for specifying this policy: VERTICAL_SCROLLBAR_AS_NEEDED (the default), VERTICAL_SCROLLBAR_ALWAYS, and VERTICAL_SCROLLBAR_NEVER.
void setHorizontalScrollBarPolicy(int)
int getHorizontalScrollBarPolicy() 		Set or get the horizontal scroll policy. ScrollPaneConstants defines three values for specifying this policy: HORIZONTAL_SCROLLBAR_AS_NEEDED (the default), HORIZONTAL_SCROLLBAR_ALWAYS, and HORIZONTAL_SCROLLBAR_NEVER.
void setViewportBorder(Border)
Border getViewportBorder() 		Set or get the border around the viewport.This is preferred over setting the border on the component.
boolean isWheelScrollingEnabled() | Set or get whether scrolling occurs in response to the mouse wheel. Mouse-wheel scrolling is enabled by default.

Decorating the Scroll Pane
(JScrollPane methods)
Method Purpose
void setColumnHeaderView(Component)
void setRowHeaderView(Component) 		Set the column or row header for the scroll pane.
void setCorner(String, Component)
Component getCorner(String) 		Set or get the corner specified. The int parameter specifies which corner and must be one of the following constants defined in ScrollPaneConstants: UPPER_LEFT_CORNER, UPPER_RIGHT_CORNER, LOWER_LEFT_CORNER, LOWER_RIGHT_CORNER, LOWER_LEADING_CORNER, LOWER_TRAILING_CORNER, UPPER_LEADING_CORNER, and UPPER_TRAILING_CORNER.

Implementing a Scrolling-Savvy Client
Method Purpose
int getScrollableUnitIncrement(Rectangle, int, int)
int getScrollableBlockIncrement(Rectangle, int, int)
(required by the Scrollable interface) 		Get the unit or block increment in pixels. The Rectangle parameter is the bounds of the currently visible rectangle. The first int parameter is either SwingConstants.HORIZONTAL or SwingConstants.VERTICAL depending on what scroll bar the user clicked on. The second int parameter indicates which direction to scroll. A value less than 0 indicates up or left. A value greater than 0 indicates down or right.
Dimension getPreferredScrollableViewportSize()
(required by the Scrollable interface) 		Get the preferred size of the viewport. This allows the client to influence the size of the viewport in which it is displayed. If the viewport size is unimportant, implement this method to return getPreferredSize.
boolean getScrollableTracksViewportWidth()
boolean getScrollableTracksViewportHeight()
(required by the Scrollable interface) 		Get whether the scroll pane should force the client to be the same width or height as the viewport. A return value of true from either of these methods effectively disallows horizontal or vertical scrolling (respectively).
void setAutoscrolls(boolean)
(in JComponent) 		Set whether synthetic mouse dragged events should be generated when the user drags the mouse outside of the component and stops; these events are necessary for scrolling by dragging. By default, the value is false, but many scrollable components such as JTable and custom components set the value to true.

Methods in Other Classes Related to Scrolling
Method Purpose
void scrollRectToVisible(Rectangle)
(in JComponent) 		If the component is in a container that supports scrolling, such as a scroll pane, then calling this method scrolls the scroll pane such that the specified rectangle is visible.
void setVisibleRowCount(int)
int getVisibleRowCount()
(in JList) 		Set or get how many rows of the list are visible. The getPreferredScrollableViewportSize method uses the visible row count to compute its return value.
void ensureIndexIsVisible(int)
(in JList) 		Scroll so that the row at the specified index is visible. This method calls scrollRectToVisible and works only if the list is in a container, such as a scroll pane, that supports scrolling.
void setVisibleRowCount(int)
int getVisibleRowCount()
(in JTree) 		Set or get how many rows of the tree are visible. The getPreferredScrollableViewportSize method uses the visible row count to compute its return value.
void scrollPathToVisible(TreePath)
void scrollRowToVisible(int)
(in JTree) 		Scroll so that the specified tree path or row at the specified index is visible. These methods call scrollRectToVisible and work only if the tree is in a container, such as a scroll pane, that supports scrolling.
void setScrollsOnExpand(boolean)
boolean getScrollsOnExpand()
(in JTree) 		Set or get whether scrolling occurs automatically when the user expands a node. True by default. This feature works only when the tree is in a container, such as a scroll pane, that supports scrolling.
void setPreferredScrollableViewportSize(Dimension)
(in JTable) 		Set the value to be returned by getPreferredScrollableViewportSize.

Examples that Use Scroll Panes

This table shows the examples that use JScrollPane and where those examples are described.

Example | Where Described | Notes
ToolBarDemo This section,
How to Use Tool Bars 		Shows a simple, yet typical, use of a scroll pane.
ScrollDemo | This section | Uses many of scroll pane's bells and whistles.
ScrollDemo2 | This section | Shows how to change the client's size.
SplitPaneDemo How to Use Split Panes,
How to Use Lists 		Puts a list and a label in a scroll pane. Also, shows how to handle the case when a scroll pane's client changes size.
TableDemo | How to Use Tables | Puts a table in a scroll pane.
TextSamplerDemo | Using Text Components | Puts a text area, an editor pane, and a text pane each in a scroll pane.
TreeDemo | How to Use Trees | Puts a tree in a scroll pane.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Root Panes
Next page: How to Use Separators


How to Use Separators (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Separators
The JSeparator class provides a horizontal or vertical dividing line or empty space. It's most commonly used in menus and tool bars. In fact, you can use separators without even knowing that a JSeparator class exists, since menus and tool bars provide convenience methods that create and add separators customized for their containers. Separators are somewhat similar to borders, except that they are genuine components and, as such, are drawn inside a container, rather than around the edges of a particular component.

Here is a picture of a menu that has three separators, used to divide the menu into four groups of items:

A menu with 4 parts, as indicated by 3 separators

The code to add the menu items and separators to the menu is extremely simple, boiling down to something like this:

menu.add(menuItem1);
menu.add(menuItem2);
menu.add(menuItem3);
menu.addSeparator();
menu.add(rbMenuItem1);
menu.add(rbMenuItem2);
menu.addSeparator();
menu.add(cbMenuItem1);
menu.add(cbMenuItem2);
menu.addSeparator();
menu.add(submenu);

Adding separators to a tool bar is similar. You can find the full code explained in the how-to sections for menus and tool bars. If you want more control over separators in menus and tool bars, you can directly use the JSeparator subclasses that implement them: JPopupMenu.Separator and JToolBar.Separator. In particular, JToolBar.Separator has API for specifying the separator's size.

Using JSeparator

You can use the JSeparator class directly to provide a dividing line in any container. The following picture shows a GUI that has a separator to the right of the button labeled Fire.

A snapshot of ListDemo

Separators have almost no API and are extremely easy to use as long as you keep one thing in mind: In most implementations, a vertical separator has a preferred height of 0, and a horizontal separator has a preferred width of 0. This means a separator is not visible unless you either set its preferred size or put it in under the control of a layout manager such as BorderLayout or BoxLayout that stretches it to fill its available display area.

The vertical separator does have a bit of width (and the horizontal a bit of height), so you should see some space where the separator is. However, the actual dividing line isn't drawn unless the width and height are both non-zero.

The following code snippet shows how ListDemo puts together the panel that contains the vertical separator. You can find the full source code for ListDemo in ListDemo.java.

JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane,
                                   BoxLayout.LINE_AXIS));
buttonPane.add(fireButton);
buttonPane.add(Box.createHorizontalStrut(5));
buttonPane.add(new JSeparator(SwingConstants.VERTICAL));
buttonPane.add(Box.createHorizontalStrut(5));
buttonPane.add(employeeName);
buttonPane.add(hireButton);
buttonPane.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
As the code shows, the buttons, separator, and text field all share a single container — a JPanel instance that uses a left-to-right box layout. Thanks to the layout manager (and to the fact that separators have unlimited maximum sizes), the separator is automatically made as tall as its available display area.

In the preceding code, the horizontal struts are invisible components used to provide space around the separator. A 5-pixel empty border provides a cushion around the panel, and also serves to prevent the separator from extending all the way to the component above it and the window's edge below it.

Here's a picture of another GUI that uses a separator, this time to put a dividing line between a group of controls and a display area.

A snapshot of TextInputDemo

You can find the code in the example index. Here is the code that sets up the separator's container:

JPanel panel = new JPanel(new BorderLayout());
...
panel.setBorder(BorderFactory.createEmptyBorder(
                        GAP/2, //top
                        0,     //left
                        GAP/2, //bottom
                        0));   //right
panel.add(new JSeparator(JSeparator.VERTICAL),
          BorderLayout.LINE_START);
panel.add(addressDisplay,
          BorderLayout.CENTER);
As in the last example, the panel uses an empty border so that the separator doesn't extend all the way to the edges of its container. Placing the separator in the leftmost area of the BorderLayout-controlled container makes the separator as tall as the address-display component that's in the center of the container. See How to Use BorderLayout for details on how border layouts work.

The Separator API

The API for using separators is minimal, since they have no contents and don't respond to user input.

Creating and Initializing Separators
Constructor or Method | Purpose
void addSeparator()
void addSeparator(Dimension)
(in JToolBar) 		Append a tool bar separator (which is invisible in most, if not all, look and feels) to the current end of the tool bar. The optional argument specifies the size of the separator. The no-argument version of this method uses a separator with a default size, as determined by the current look and feel.
void addSeparator()
void insertSeparator(int)
(in JMenu) 		Put a separator in the menu. The addSeparator method puts the separator at the current end of the menu. The insertSeparator method inserts the separator into the menu at the specified position.
void addSeparator()
(in JPopupMenu) 		Put a separator at the current end of the popup menu.
JSeparator()
JSeparator(int) 		Create a separator. If you don't specify an argument, the separator is horizontal. The argument can be either SwingConstants.HORIZONTAL or SwingConstants.VERTICAL.
void setOrientation(int)
int getOrientation()
(in JSeparator) 		Get or set the separator's orientation, which can be either SwingConstants.HORIZONTAL or SwingConstants.VERTICAL.
JToolBar.Separator()
JToolBar.Separator(Dimension) 		Create a separator for use in a tool bar. The optional argument specifies the separator's size.
setSeparatorSize(Dimension)
(in JToolBar.Separator) 		Specify the separator's size. More specifically, the specified Dimension is used as the separator's minimum, preferred, and maximum sizes.
JPopupMenu.Separator() | Create a separator for use in a menu.

Examples that Use Separators

Several of this lesson's examples use separators, usually in menus. Here is a list of some of the more interesting examples.

Example | Where Described | Notes
ListDemo | This section and How to Use Lists | Uses a vertical separator in a panel controlled by a horizontal box layout.
TextInputDemo | This section and How to Use Formatted Text Fields | Uses a vertical separator at the left of a panel controlled by a border layout.
MenuDemo | This section and How to Use Menus | Uses the JMenu method addSeparator to put separators in a menu.
ToolBarDemo2 | How to Use Tool Bars | Uses the JToolBar method addSeparator to put space between two kinds of buttons.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Scroll Panes
Next page: How to Use Sliders


How to Use Sliders (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Sliders
A JSlider component is intended to let the user easily enter a numeric value bounded by a minimum and maximum value. If space is limited, a spinner is a possible alternative to a slider.

The following picture shows an application that uses a slider to control animation speed:

A snapshot of SliderDemo, which uses a slider

Try this:
  1. Click the Launch button to run SliderDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the SliderDemo application

  2. Use the slider to adjust the animation speed.
  3. Push the slider to 0 to stop the animation.
Below is the code from the SliderDemo.java file that creates the slider in the previous example.
static final int FPS_MIN = 0;
static final int FPS_MAX = 30;
static final int FPS_INIT = 15;    //initial frames per second
. . .
JSlider framesPerSecond = new JSlider(JSlider.HORIZONTAL,
                                      FPS_MIN, FPS_MAX, FPS_INIT);
framesPerSecond.addChangeListener(this);

//Turn on labels at major tick marks.
framesPerSecond.setMajorTickSpacing(10);
framesPerSecond.setMinorTickSpacing(1);
framesPerSecond.setPaintTicks(true);
framesPerSecond.setPaintLabels(true);
By default, spacing for major and minor tick marks is zero. To see tick marks, you must explicitly set the spacing for either major or minor tick marks (or both) to a non-zero value and call the setPaintTicks(true) method. However, you also need labels for your tick marks. To display standard, numeric labels at major tick mark locations, set the major tick spacing, then call the setPaintLabels(true) method. The example program provides labels for its slider in this way. But you are not constrained to using only these labels. Customizing Labels on a Slider shows you how to customize slider labels. In addition, a new slider feature available in JDK 6 allows you to set a font for the JSlider component.
Font font = new Font("Serif", Font.ITALIC, 15);
framesPerSecond.setFont(font);

When you move the slider's knob, the stateChanged method of the slider's ChangeListener is called. For information about change listeners, refer to How to Write a Change Listener. Here is the change listener code that reacts to slider value changes:

public void stateChanged(ChangeEvent e) {
    JSlider source = (JSlider)e.getSource();
    if (!source.getValueIsAdjusting()) {
        int fps = (int)source.getValue();
        if (fps == 0) {
            if (!frozen) stopAnimation();
        } else {
            delay = 1000 / fps;
            timer.setDelay(delay);
            timer.setInitialDelay(delay * 10);
            if (frozen) startAnimation();
        }
    }
}
Notice that the stateChanged method changes the animation speed only if the getValueIsAdjusting method returns false. Many change events are fired as the user moves the slider knob. This program is interested only in the final result of the user's action.

Customizing Labels on a Slider

The demo below is a modified version of the SliderDemo that uses a slider with custom labels:

A snapshot of SliderDemo2, which uses a slider with custom labels

The source for this program can be found in SliderDemo2.java. Click the Launch button to run SliderDemo2 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SliderDemo2 application

The following code creates the slider and customizes its labels:

//Create the slider
JSlider framesPerSecond = new JSlider(JSlider.VERTICAL,
                                      FPS_MIN, FPS_MAX, FPS_INIT);
framesPerSecond.addChangeListener(this);
framesPerSecond.setMajorTickSpacing(10);
framesPerSecond.setPaintTicks(true);

//Create the label table
Hashtable labelTable = new Hashtable();
labelTable.put( new Integer( 0 ), new JLabel("Stop") );
labelTable.put( new Integer( FPS_MAX/10 ), new JLabel("Slow") );
labelTable.put( new Integer( FPS_MAX ), new JLabel("Fast") );
framesPerSecond.setLabelTable( labelTable );

framesPerSecond.setPaintLabels(true);
Each key-value pair in the hashtable specified with the setLabelTable method gives the position and the value of one label. The hashtable key must be of an Integer type and must have a value within the slider's range at which to place the label. The hashtable value associated with each key must be a Component object. This demo uses JLabel instances with text only. An interesting modification would be to use JLabel instances with icons or buttons that move the knob to the label's position.

Use the createStandardLabels method of the JSlider class to create a set of numeric labels positioned at a specific interval. You can also modify the table returned by the createStandardLabels method in order to customize it.

The Slider API

The following tables list the commonly used JSlider constructors and methods. See The JComponent Class for tables of commonly used inherited methods.

The API for using sliders is divided into these categories:

  • Creating the Slider
  • Fine Tuning the Slider's Appearance
  • Watching the Slider Operate
  • Working Directly with the Data Model

Creating the Slider
Constructor | Purpose
JSlider() | Creates a horizontal slider with the range 0 to 100 and an initial value of 50.
JSlider(int min, int max)
JSlider(int min, int max, int value) 		Creates a horizontal slider with the specified minimum and maximum values. The third int argument, when present, specifies the slider's initial value.
JSlider(int orientation)
JSlider(int orientation, int min, int max, int value) 		Creates a slider with the specified orientation, which must be either JSlider.HORIZONTAL or JSlider.VERTICAL. The last three int arguments, when present, specify the slider's minimum, maximum, and initial values, respectively.
JSlider(BoundedRangeModel) | Creates a horizontal slider with the specified model, which manages the slider's minimum, maximum, and current values and their relationships.

Fine Tuning the Slider's Appearance
Method | Purpose
void setValue(int)
int getValue() 		Sets or gets the slider's current value. The set method also positions the slider's knob.
void setOrientation(int)
int getOrientation() 		Sets or gets the orientation of the slider. Possible values are JSlider.HORIZONTAL or JSlider.VERTICAL.
void setInverted(boolean)
boolean getInverted() 		Sets or gets whether the maximum is shown at the left of a horizontal slider or at the bottom of a vertical one, thereby inverting the slider's range.
void setMinimum(int)
int getMinimum()
void setMaximum(int)
int getMaximum() 		Sets or gets the minimum or maximum values of the slider. Together, these methods set or get the slider's range.
void setMajorTickSpacing(int)
int getMajorTickSpacing()
void setMinorTickSpacing(int)
int getMinorTickSpacing() 		Sets or gets the range between major and minor ticks. You must call setPaintTicks(true) for the tick marks to appear.
void setPaintTicks(boolean)
boolean getPaintTicks() 		Sets or gets whether tick marks are painted on the slider.
void setPaintLabels(boolean)
boolean getPaintLabels() 		Sets or gets whether labels are painted on the slider. You can provide custom labels with setLabelTable or get automatic labels by setting the major tick spacing to a non-zero value.
void setLabelTable(Dictionary)
Dictionary getLabelTable() 		Sets or gets the labels for the slider. You must call setPaintLabels(true) for the labels to appear.
Hashtable createStandardLabels(int)
Hashtable createStandardLabels(int, int) 		Creates a standard set of numeric labels. The first int argument specifies the increment, the second int argument specifies the starting point. When left unspecified, the starting point is set to the slider's minimum number.
setFont(java.awt.Font) | Sets the font for slider labels .

Watching the Slider Operate
Method | Purpose
void addChangeListener(ChangeListener) | Registers a change listener with the slider.
boolean getValueIsAdjusting() | Determines whether the user gesture to move the slider's knob is complete.

Working Directly with the Data Model
Class, Interface, or Method | Purpose
BoundedRangeModel | The interface required for the slider's data model.
DefaultBoundedRangeModel | An implementation of the BoundedRangeModel interface.
void setModel()
getModel()
(in JSlider) 		Sets or gets the data model used by the slider. You can also set the model by using the constructor that takes a single argument of type BoundedRangeModel.

Examples that Use Sliders

This table shows the examples that use JSlider and where those examples are described.

Example | Where Described | Notes
SliderDemo | This section | Shows a slider with labels at major tick marks.
SliderDemo2 | This section | Shows a vertical slider with custom labels.
Converter | Using Models, How to Use Panels | A measurement conversion application featuring two sliders that share data and have custom BoundedRangeModels.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Separators
Next page: How to Use Spinners


How to Use Spinners (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Spinners
Spinners are similar to combo boxes and lists in that they let the user choose from a range of values. Like editable combo boxes, spinners allow the user to type in a value. Unlike combo boxes, spinners do not have a drop-down list that can cover up other components. Because spinners do not display possible values — only the current value is visible — they are often used instead of combo boxes or lists when the set of possible values is extremely large. However, spinners should only be used when the possible values and their sequence are obvious.

A spinner is a compound component with three subcomponents: two small buttons and an editor. The editor can be any JComponent, but by default it is implemented as a panel that contains a formatted text field. The spinner's possible and current values are managed by its model.

Here is a picture of an application named SpinnerDemo that has three spinners used to specify dates:

SpinnerDemo shows 3 kinds of spinners

The code for the main class can be found in SpinnerDemo.java. The Month spinner displays the name of the first month in the user's locale. The possible values for this spinner are specified using an array of strings. The Year spinner displays one value of a range of integers, initialized to the current year. The Another Date spinner displays one value in a range of Date objects (initially the current date) in a custom format that shows just a month and year.
Try this:
  1. Click the Launch button to run SpinnerDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    2. Launches the SpinnerDemo Application

  2. With the Month spinner, use the arrow buttons or keys to cycle forward and backward through the possible values.
    Note that the lowest value is the first month of the year (for example, January) and the highest is the last (for example, December). The exact values depend on your locale. Also note that the values do not cycle — you cannot use the up arrow button or key to go from December directly to January — because the standard spinner models do not support cycling.
  3. Type in a valid month name for your locale — for example, July.
    Note that the spinner automatically completes the month name.
  4. Moving on to the Year spinner, try typing a year over 100 years ago — for example, 1800 — and then click on another spinner or press the Tab key to move the focus out of the spinner.
    Because this program restricts the spinner's model to numbers within 100 years of the current year, 1800 is invalid. When the focus moves out of the spinner, the displayed text changes back to the last valid value.
  5. Moving to the Another Date spinner, use the arrow buttons or keys to change the date.
    Note that by default the first part of the date — in this case, the month number — changes. You can change which part of the date changes either by clicking the mouse or using the arrow keys to move to another part of the date.

To create a spinner, first create its model and then pass the model into the JSpinner constructor. For example:

String[] monthStrings = getMonthStrings(); //get month names
SpinnerListModel monthModel = new SpinnerListModel(monthStrings);
JSpinner spinner = new JSpinner(monthModel);
The rest of this section covers the following topics:
  • Using Standard Spinner Models and Editors
  • Specifying Spinner Formatting
  • Creating Custom Spinner Models and Editors
  • Detecting Spinner Value Changes
  • The Spinner API
  • Examples That Use Spinners

Using Standard Spinner Models and Editors

The Swing API provides three spinner models:
SpinnerListModel
The SpinnerListModel is a model whose values are defined by an array of objects or a List object. The Month spinner in the SpinnerDemo example uses this model, initialized with an array derived from the value returned by the getMonths method of the java.text.DateFormatSymbols class. See SpinnerDemo.java for details.
SpinnerNumberModel
The SpinnerNumberModel supports sequences of numbers which can be expressed as double objects, int objects, or Number objects. You can specify the minimum and maximum allowable values, as well as the step size — the amount of each increment or decrement. The Year spinner uses this model, created with the following code:
SpinnerModel model =
        new SpinnerNumberModel(currentYear, //initial value
                               currentYear - 100, //min
                               currentYear + 100, //max
                               1);                //step
SpinnerDateModel
The SpinnerDateModel supports sequences of Date objects. You can specify the minimum and maximum dates, as well as the field (such as Calendar.YEAR) to increment or decrement. Note, however, that some types of look and feel ignore the specified field, and instead change the field that appears selected. The Another Date spinner uses this model, created with the following code:
Date initDate = calendar.getTime();
calendar.add(Calendar.YEAR, -100);
Date earliestDate = calendar.getTime();
calendar.add(Calendar.YEAR, 200);
Date latestDate = calendar.getTime();
model = new SpinnerDateModel(initDate,
                             earliestDate,
                             latestDate,
                             Calendar.YEAR);

When you set the spinner's model, the spinner's editor is automatically set. The Swing API provides an editor class corresponding to each of the three model classes listed above. These classes — JSpinner.ListEditor, JSpinner.NumberEditor, and JSpinner.DateEditor — are all subclasses of the JSpinner.DefaultEditor class that feature editable formatted text fields. If you use a model that does not have an editor associated with it, the editor is by default a JSpinner.DefaultEditor instance with a non-editable formatted text field.

Specifying Spinner Formatting

To change the formatting used in a standard spinner editor, you can create and set the editor yourself.

The JSpinner.NumberEditor and JSpinner.DateEditor classes have constructors that allow you to create an editor that formats its data in a particular way. For example, the following code sets up the Another Date spinner so that instead of using the default date format, which is long and includes the time, it shows just a month and year in a compact way.

spinner.setEditor(new JSpinner.DateEditor(spinner, "MM/yyyy"));
Note: You can play with date formats by running ComboBoxDemo2 example. Click the Launch button to run ComboBoxDemo2 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the ComboBoxDemo2 Application

For information about format strings, see the Formatting lesson of the Internationalization trail. For tables of number format characters, see the Getting Started section.

To change the formatting when using a default editor, you can obtain the editor's formatted text field and invoke methods on it. You can call those methods using the getTextField method defined in the JSpinner.DefaultEditor class. Note that the Swing-provided editors are not formatted text fields. Instead, they are the JPanel instances that contain a formatted text field. Here is an example of getting and invoking methods on the editor's formatted text field:

//Tweak the spinner's formatted text field.
ftf = getTextField(spinner);
if (ftf != null ) {
    ftf.setColumns(8); //specify more width than we need
    ftf.setHorizontalAlignment(JTextField.RIGHT);
}
...

public JFormattedTextField getTextField(JSpinner spinner) {
    JComponent editor = spinner.getEditor();
    if (editor instanceof JSpinner.DefaultEditor) {
        return ((JSpinner.DefaultEditor)editor).getTextField();
    } else {
        System.err.println("Unexpected editor type: "
                           + spinner.getEditor().getClass()
                           + " isn't a descendant of DefaultEditor");
        return null;
    }
}

Creating Custom Spinner Models and Editors

If the existing spinner models or editors do not meet your needs, you can create your own.

The easiest route to creating a custom spinner model is to create a subclass of an existing AbstractSpinnerModel subclass that already does most of what you need. An alternative is to implement your own class by extending AbstractSpinnerModel class, which implements the event notifications required for all spinner models.

The following subclass of SpinnerListModel implements a spinner model that cycles through an array of objects. It also lets you specify a second spinner model that will be updated whenever the cycle begins again. For example, if the array of objects is a list of months, the linked model could be for a spinner that displays the year. When the month flips over from December to January the year is incremented. Similarly, when the month flips back from January to December the year is decremented.

public class CyclingSpinnerListModel extends SpinnerListModel {
    Object firstValue, lastValue;
    SpinnerModel linkedModel = null;

    public CyclingSpinnerListModel(Object[] values) {
        super(values);
        firstValue = values[0];
        lastValue = values[values.length - 1];
    }

    public void setLinkedModel(SpinnerModel linkedModel) {
        this.linkedModel = linkedModel;
    }

    public Object getNextValue() {
        Object value = super.getNextValue();
        if (value == null) {
            value = firstValue;
            if (linkedModel != null) {
                linkedModel.setValue(linkedModel.getNextValue());
            }
        }
        return value;
    }

    public Object getPreviousValue() {
        Object value = super.getPreviousValue();
        if (value == null) {
            value = lastValue;
            if (linkedModel != null) {
                linkedModel.setValue(linkedModel.getPreviousValue());
            }
        }
        return value;
    }
}

The CyclingSpinnerListModel model is used for the Month spinner in the SpinnerDemo2 example, an example that is almost identical to the SpinnerDemo. Click the Launch button to run SpinnerDemo2 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SpinnerDemo2 Application

As we mentioned before, if you implement a spinner model that does not descend from SpinnerListModel, SpinnerNumberModel, or SpinnerDateModel, then the spinner's default editor is a non-editable instance of JSpinner.DefaultEditor. As you have already seen, you can set a spinner's editor by invoking the setEditor method on the spinner after the spinner's model property has been set. An alternative to using setEditor is to create a subclass of the JSpinner class and override its createEditor method so that it returns a particular kind of editor whenever the spinner model is of a certain type.

In theory at least, you can use any JComponent instance as an editor. Possibilities include using a subclass of a standard component such as JLabel, or a component you have implemented from scratch, or a subclass of JSpinner.DefaultEditor. The only requirements are that the editor must be updated to reflect changes in the spinner's value, and it must have a reasonable preferred size. The editor should generally also set its tool tip text to whatever tool tip text has been specified for the spinner. An example of implementing an editor is provided in the next section.

Detecting Spinner Value Changes

You can detect that a spinner's value has changed by registering a change listener on either the spinner or its model. Here is an example of implementing such a change listener. This example is from SpinnerDemo3, which is based on SpinnerDemo and uses a change listener to change the color of some text to match the value of the Another Date spinner. Click the Launch button to run SpinnerDemo3 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SpinnerDemo3 Application

public class SpinnerDemo3 extends JPanel
                          implements ChangeListener {
    protected Calendar calendar;
    protected JSpinner dateSpinner;
    ...
    public SpinnerDemo3() {
        ...
        SpinnerDateModel dateModel = ...;
        ...
        setSeasonalColor(dateModel.getDate()); //initialize color

        //Listen for changes on the date spinner.
        dateSpinner.addChangeListener(this);
        ...
    }

    public void stateChanged(ChangeEvent e) {
        SpinnerModel dateModel = dateSpinner.getModel();
        if (dateModel instanceof SpinnerDateModel) {
            setSeasonalColor(((SpinnerDateModel)dateModel).getDate());
        }
    }

    protected void setSeasonalColor(Date date) {
        calendar.setTime(date);
        int month = calendar.get(Calendar.MONTH);
        JFormattedTextField ftf = getTextField(dateSpinner);
        if (ftf == null) return;

        //Set the color to match northern hemisphere seasonal conventions.
        switch (month) {
            case 2:  //March
            case 3:  //April
            case 4:  //May
                     ftf.setForeground(SPRING_COLOR);
                     break;
            ...
            default: //December, January, February
                     ftf.setForeground(WINTER_COLOR);
        }
    }
    ...
}
The following example implements an editor which has a change listener so that it can reflect the spinner's current value. This particular editor displays a solid color of gray, ranging anywhere from white to black. Click the Launch button to run SpinnerDemo4 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SpinnerDemo4 Application

...//Where the components are created:
JSpinner spinner = new JSpinner(new GrayModel(170));
spinner.setEditor(new GrayEditor(spinner));

class GrayModel extends SpinnerNumberModel {
    ...
}

class GrayEditor extends JLabel
                 implements ChangeListener {
    public GrayEditor(JSpinner spinner) {
        setOpaque(true);
        ...
        //Get info from the model.
        GrayModel myModel = (GrayModel)(spinner.getModel());
        setBackground(myModel.getColor());
        spinner.addChangeListener(this);
        ...
        updateToolTipText(spinner);
    }

    protected void updateToolTipText(JSpinner spinner) {
        String toolTipText = spinner.getToolTipText();
        if (toolTipText != null) {
            //JSpinner has tool tip text.  Use it.
            if (!toolTipText.equals(getToolTipText())) {
                setToolTipText(toolTipText);
            }
        } else {
            //Define our own tool tip text.
            GrayModel myModel = (GrayModel)(spinner.getModel());
            int rgb = myModel.getIntValue();
            setToolTipText("(" + rgb + "," + rgb + "," + rgb + ")");
        }
    }

    public void stateChanged(ChangeEvent e) {
            JSpinner mySpinner = (JSpinner)(e.getSource());
            GrayModel myModel = (GrayModel)(mySpinner.getModel());
            setBackground(myModel.getColor());
            updateToolTipText(mySpinner);
    }
}

The Spinner API

The following tables list some of the commonly used API for using spinners. If you need to deal directly with the editor's formatted text field, you should also see The FormattedTextField API. Other methods you might use are listed in the API tables in The JComponent Class.

  • Classes Related to Spinners
  • Useful JSpinner Constructors and Methods
  • Useful Editor Constructors and Methods
  • SpinnerListModel Methods
  • SpinnerDateModel Methods
  • SpinnerNumberModel Methods

Classes Related to Spinners
Class or Interface | Purpose
JSpinner | A single-line input field that allows the user to select a number or object value from an ordered sequence.
SpinnerModel | The interface implemented by all spinner models.
AbstractSpinnerModel | The usual superclass for spinner model implementations.
SpinnerListModel | A subclass of AbstractSpinnerModel whose values are defined by an array or a List.
SpinnerDateModel | A subclass of AbstractSpinnerModel that supports sequences of Date instances.
SpinnerNumberModel | A subclass of AbstractSpinnerModel that supports sequences of numbers.
JSpinner.DefaultEditor | Implements an uneditable component that displays the spinner's value. Subclasses of this class are generally more specialized (and editable).
JSpinner.ListEditor | A subclass of JSpinner.DefaultEditor whose values are defined by an array or a List.
JSpinner.DateEditor | A subclass of JSpinner.DefaultEditor that supports sequences of Date instances.
JSpinner.NumberEditor | A subclass of JSpinner.DefaultEditor that supports sequences of numbers.

Useful JSpinner Constructors and Methods
Constructor or Method | Purpose
JSpinner()
JSpinner(SpinnerModel) 		Creates a new JSpinner. The no-argument constructor creates a spinner with an integer SpinnerNumberModel with an initial value of 0 and no minimum or maximum limits. The optional parameter on the second constructor allows you to specify your own SpinnerModel.
void setValue(java.lang.Object)
Object getValue() 		Sets or gets the currently displayed element of the sequence.
Object getNextValue()
Object getPreviousValue() 		Gets the object in the sequence that comes before or after the object returned by the getValue method.
SpinnerModel getModel()
void setModel(SpinnerModel) 		Gets or sets the spinner's model.
JComponent getEditor()
void setEditor(JComponent) 		Gets or sets the spinner's editor, which is often an object of type JSpinner.DefaultEditor.
protected JComponent createEditor(SpinnerModel) | Called by the JSpinner constructors to create the spinner's editor. Override this method to associate an editor with a particular type of model.

Useful Editor Constructors and Methods
Constructor or Method | Purpose
JSpinner.NumberEditor(JSpinner, String) | Creates a JSpinner.NumberEditor instance that displays and allows editing of the number value of the specified spinner. The string argument specifies the format to use to display the number. See the API documentation for DecimalFormat for information about decimal format strings.
JSpinner.DateEditor(JSpinner, String) | Creates a JSpinner.DateEditor instance that displays and allows editing of the Date value of the specified spinner. The string argument specifies the format to use to display the date. See the API documentation for SimpleDateFormat for information about date format strings.
JFormattedTextField getTextField()
(defined in JSpinner.DefaultEditor) 		Gets the formatted text field that provides the main GUI for this editor.

SpinnerListModel Methods
Method Purpose
void setList(List)
List getList() 		Sets or gets the List that defines the sequence for this model.

SpinnerDateModel Methods
Method Purpose
void setValue(Object)
Date getDate()
Object getValue() 		Sets or gets the current Date for this sequence.
void setStart(Comparable)
Comparable getStart() 		Sets or gets the first Date in this sequence. Use null to specify that the spinner has no lower limit.
void setEnd(Comparable)
Comparable getEnd() 		Sets or gets the last Date in this sequence. Use null to specify that the spinner has no upper limit.
void setCalendarField(int)
int getCalendarField() 		Sets or gets the size of the date value increment used by the getNextValue and getPreviousValue methods. This property is not used when the user explicitly increases or decreases the value; instead, the selected part of the formatted text field is incremented or decremented. The specified parameter must be one of the following constants, defined in Calendar: ERA, YEAR, MONTH, WEEK_OF_YEAR, WEEK_OF_MONTH, DAY_OF_MONTH, DAY_OF_YEAR, DAY_OF_WEEK, DAY_OF_WEEK_IN_MONTH, AM_PM, HOUR_OF_DAY, MINUTE, SECOND, MILLISECOND.

SpinnerNumberModel Methods
Method Purpose
void setValue(Object)
Number getNumber() 		Sets or gets the current value for this sequence.
void setMaximum(Comparable)
Comparable getMaximum() 		Sets or gets the upper bound for numbers in this sequence. If the maximum is null, there is no upper bound.
void setMinimum(Comparable)
Comparable getMinimum() 		Sets or gets the lower bound for numbers in this sequence. If the minimum is null, there is no lower bound.
void setStepSize(Number)
Number getStepSize() 		Sets or gets the increment used by getNextValue and getPreviousValue methods.

Examples That Use Spinners

This table lists examples that use spinners and points to where those examples are described.

Example | Where Described | Notes
SpinnerDemo | This section | Uses all three standard spinner model classes. Contains the code to use a custom spinner model, but the code is turned off by default.
SpinnerDemo2 | This section | A SpinnerDemo subclass that uses the custom spinner model for its Months spinner.
SpinnerDemo3 | This section | Based on SpinnerDemo, this application shows how to listen for changes in a spinner's value.
SpinnerDemo4 | This section | Implements a custom model and a custom editor for a spinner that displays shades of gray.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Sliders
Next page: How to Use Split Panes


How to Use Split Panes (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Split Panes
A JSplitPane displays two components, either side by side or one on top of the other. By dragging the divider that appears between the components, the user can specify how much of the split pane's total area goes to each component. You can divide screen space among three or more components by putting split panes inside of split panes, as described in Nesting Split Panes.

If you want to create a split pane with an arbitrary number of components, you should check out Hans Muller's article, MultiSplitPane: Splitting Without Nesting.

Instead of adding the components of interest directly to a split pane, you often put each component into a scroll pane. You then put the scroll panes into the split pane. This allows the user to view any part of a component of interest, without requiring the component to take up a lot of screen space or adapt to displaying itself in varying amounts of screen space.

Here's a picture of an application that uses a split pane to display a list and an image side by side:

A snapshot of SplitPaneDemo

Try this:
  1. Click the Launch button to run the SplitPaneDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the SplitPaneDemo example

  2. Drag the dimpled line that divides the list and the image to the left or right. Try to drag the divider all the way to the window's edge.
  3. Click the tiny arrows on the divider to hide/expand the left or right component.
Below is the code from SplitPaneDemo that creates and sets up the split pane.
//Create a split pane with the two scroll panes in it.
splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                           listScrollPane, pictureScrollPane);
splitPane.setOneTouchExpandable(true);
splitPane.setDividerLocation(150);

//Provide minimum sizes for the two components in the split pane
Dimension minimumSize = new Dimension(100, 50);
listScrollPane.setMinimumSize(minimumSize);
pictureScrollPane.setMinimumSize(minimumSize);
The constructor used by this example takes three arguments. The first indicates the split direction. The other arguments are the two components to put in the split pane. Refer to Setting the Components in a Split Pane for information about JSplitPane methods that set the components dynamically.

The split pane in this example is split horizontally — the two components appear side by side — as specified by the JSplitPane.HORIZONTAL_SPLIT argument to the constructor. Split pane provides one other option, specified with JSplitPane.VERTICAL_SPLIT, that places one component above the other. You can change the split direction after the split pane has been created with the setOrientation method.

Two small arrows appear at the top of the divider in the example's split pane. These arrows let the user collapse (and then expand) either of the components with a single click. The current look and feel determines whether these controls appear by default. In the Java look and feel, they are turned off by default. (Note that not all look and feels support this.) The example turned them on using the setOneTouchExpandable method.

The range of a split pane's divider is determined in part by the minimum sizes of the components within the split pane. See Positioning the Divider and Restricting its Range for details.

The rest of this section covers these topics:

  • Setting the Components in a Split Pane
  • Positioning the Divider and Restricting its Range
  • Nesting Split Panes
  • The Split Pane API
  • Examples that Use Split Panes

Setting the Components in a Split Pane
A program can set a split pane's two components dynamically with these four methods:
  • setLeftComponent
  • setRightComponent
  • setTopComponent
  • setBottomComponent
You can use any of these methods at any time regardless of the split pane's current split direction. Calls to setLeftComponent and setTopComponent are equivalent and set the specified component in the top or left position, depending on the split pane's current split orientation. Similarly, calls to setRightComponent and setBottomComponent are equivalent. These methods replace whatever component is already in that position with the new one.

Like other containers, JSplitPane supports the add method. Split pane puts the first component added in the left or top position. The danger of using add is that you can inadvertantly call it too many times, in which case the split pane's layout manager will throw a rather esoteric-looking exception. If you are using the add method and a split pane is already populated, you first need to remove the existing components with remove.

If you put only one component in a split pane, then the divider will be stuck at the right side or the bottom of the split pane, depending on its split direction.

Positioning the Divider and Restricting Its Range
To make your split pane work well, you often need to set the minimum sizes of components in the split pane, as well as the preferred size of either the split pane or its contained components. Choosing which sizes you should set is an art that requires understanding how a split pane's preferred size and divider location are determined. Before we get into details, let's take another look at SplitPaneDemo. Or, if you're in a hurry, you can skip to the list of rules.
Try this:
  1. Click the Launch button to run the SplitPaneDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the SplitPaneDemo example

    Because the size of the demo's frame is set using the pack method, the split pane is at its preferred size, which SplitPaneDemo happens to set explicitly. The divider is automatically placed so that the left component is at its preferred width and all remaining space goes to the right component.
  2. Make the window wider.
    The divider stays where it is, and the extra space goes to the component at the right.
  3. Make the window noticeably narrower than when it first came up — perhaps twice as wide as the left component.
    Again, the left component's size and the divider position stay the same. Only the size of the right component changes.
  4. Make the window as narrow as possible.
    Assuming the window uses the Java look and feel-provided decorations, you cannot size the window smaller than the split pane's minimum size, which is determined by the minimum size of the components contained by the split pane. SplitPaneDemo sets the minimum size of these contained components explicitly.
  5. Make the window wider, and then drag the divider as far as it will go to the right.
    The divider goes only as far as the right component's minimum size allows. If you drag the divider to the left, you'll see that it also respects the left component's minimum size.

Now that you've seen the default behavior of split panes, we can tell you what's happening behind the scenes and how you can affect it. In this discussion, when we refer to a component's preferred or minimum size, we often mean the preferred or minimum width of the component if the split pane is horizontal, or its preferred or minimum height if the split pane is vertical.

By default, a split pane's preferred size and divider location are initialized so that the two components in the split pane are at their preferred sizes. If the split pane isn't displayed at this preferred size and the program hasn't set the divider's location explicitly, then the initial position of the divider (and thus the sizes of the two components) depends on a split pane property called the resize weight. If the split pane is initially at its preferred size or bigger, then the contained components start out at their preferred sizes, before adjusting for the resize weight. If the split pane is initially too small to display both components at their preferred sizes, then they start out at their minimum sizes, before adjusting for the resize weight.

A split pane's resize weight has a value between 0.0 and 1.0 and determines how space is distributed between the two contained components when the split pane's size is set — whether programmatically or by the user resizing the split pane (enlarging its containing window, for example). The resize weight of a split pane is 0.0 by default, indicating that the left or top component's size is fixed, and the right or bottom component adjusts its size to fit the remaining space. Setting the resize weight to 0.5 splits any extra or missing space evenly between the two components. Setting the resize weight to 1.0 makes the right or bottom component's size remain fixed. The resize weight has no effect, however, when the user drags the divider.

The user can drag the divider to any position as long as neither contained component goes below its minimum size. If the divider has one-touch buttons, the user can use them to make the divider move completely to one side or the other — no matter what the minimum sizes of the components are.

Now that you know the factors that affect a split pane's size and divider location, here are some rules for making them work well:

  • To ensure that the divider can be dragged when the split pane is at its preferred size, make sure the minimum size of one or both contained components is smaller than the contained component's preferred size. You can set the minimum size of a component either by invoking setMinimumSize on it or by overriding its getMinimumSize method. For example, if you want the user to be able to drag the divider all the way to both sides:
    Dimension minimumSize = new Dimension(0, 0);
leftComponent.setMinimumSize(minimumSize);
rightComponent.setMinimumSize(minimumSize);
  • To guarantee that both contained components appear, make sure that either the split pane is initially at or above its preferred size, or the minimum sizes of the contained components are greater than zero.

    This should usually happen if the splitpane is given its preferred size, which depends upon the layout manager containing the split pane. Another option is to explicitly set a preferred size on the split pane that is larger than the size of the contained components.

  • If you want the bottom or right component to stay the same size and the top or left component to be flexible when the split pane gets bigger, set the resize weight to 1.0. You can do this by invoking setResizeWeight:
    splitPane.setResizeWeight(1.0);

  • If you want both halves of the split pane to share in the split pane's extra or removed space, set the resize weight to 0.5:
    splitPane.setResizeWeight(0.5);

  • Make sure each component contained by a split pane has a reasonable preferred size. If the component is a panel that uses a layout manager, you can generally just use the value it returns. If the component is a scroll pane, you have a few choices. You can invoke the setPreferredSize method on the scroll pane, invoke the appropriate method on the component in the scroll pane (such as the setVisibleRowCount method for JList or JTree).

  • Make sure each component contained by a split pane can display itself reasonably in varying amounts of space. For example, panels that contain multiple components should use layout managers that use extra space in a reasonable way.

  • If you want to set the size of contained components to something other than their preferred sizes, use the setDividerLocation method. For example, to make the left component 150 pixels wide:
    splitPane.setDividerLocation(150 + splitPane.getInsets().left);
    Although the split pane does its best to honor the initial divider location (150 in this case), once the user drags the divider it may no longer be possible to drag to the programmatically specified size.

    To make the right component 150 pixels wide:

    splitPane.setDividerLocation(splitPane.getSize().width
                             - splitPane.getInsets().right
                             - splitPane.getDividerSize()
                             - 150);
    If the split pane is already visible, you can set the divider location as a percentage of the split pane. For example, to make 25% of the space go to left/top:
    splitPane.setDividerLocation(0.25);

    Note that this is implemented in terms of the current size and is therefore really ony useful if the split pane is visible.

  • To lay out the split pane as if it just came up, likely repositioning the divider in the process, invoke resetToPreferredSizes() on the split pane.

    Note: Just changing the contained components' preferred sizes — even if you invoke revalidate afterwards — is not enough to cause the split pane to lay itself out again. You must invoke resetToPreferredSizes as well.
The following snapshot shows an example named SplitPaneDividerDemo that demonstrates split pane component sizes and divider placement.

A snapshot of SplitPaneDividerDemo

Like SplitPaneDemo, SplitPaneDividerDemo features a horizontal split pane with one-touch buttons. SplitPaneDividerDemo has the following additional features:

  • The split pane's resize weight is explicitly set (to 0.5).
  • The split pane is displayed at its default preferred size.
  • A Reset button at the bottom of the window invokes resetToPreferredSizes on the split pane.
  • The components in the split pane are instances of a custom JComponent subclass called SizeDisplayer. A SizeDisplayer displays optional text against the background of a faded (and also optional) image. More importantly, it has rectangles that show its preferred and minimum sizes.
  • SplitPaneDividerDemo sets up its SizeDisplayers to have equal preferred sizes (due to the equally large images they show) but unequal minimum sizes.
Try this:
  1. Click the Launch button to run the SplitPaneDividerDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the SplitPaneDividerDemo example

    Because the size of the demo's frame is set using the pack method, the split pane is at its preferred size, which by default is just big enough for the SizeDisplayers to be at their preferred sizes. The preferred size of each SizeDisplayer is indicated by a red rectangle. The divider is automatically placed so that both components are at their preferred widths.

  2. Make the window wider.
    Because the split pane's resize weight is 0.5, the extra space is divided evenly between the left and right components. The divider moves accordingly.
  3. Make the window as narrow as possible.
    Assuming the window uses the Java look and feel-provided decorations, it will not let you size the window smaller than the split pane's minimum size, which is determined by the minimum size of the SizeDisplayers it contains. The minimum size of each SizeDisplayer is indicated by a bright blue rectangle.
  4. Make the window a bit wider, and then drag the divider as far as it will go to the right.
    The divider goes only as far as the right component's minimum size allows.
  5. After making sure the split pane is smaller than its preferred size, click the Reset button.
    Note that the two SizeDisplayers are displayed at the different sizes, even though when the application came up they had equal sizes. The reason is that although their preferred sizes are equal, their minimum sizes are not. Because the split pane cannot display them at their preferred sizes or larger, it lays them out using their minimum sizes. The leftover space is divided equally between the components, since the split pane's resize weight is 0.5.
  6. Widen the split pane so that it is large enough for both SizeDisplayers to be shown at their preferred sizes, and then click the Reset button.
    The divider is placed in the middle again, so that both components are the same size.
Here is the code that creates the GUI for SplitPaneDividerDemo:
public class SplitPaneDividerDemo extends JPanel ... {

    private JSplitPane splitPane;

    public SplitPaneDividerDemo() {
        super(new BorderLayout());

        Font font = new Font("Serif", Font.ITALIC, 24);

        ImageIcon icon = createImageIcon("images/Cat.gif");
        SizeDisplayer sd1 = new SizeDisplayer("left", icon);
        sd1.setMinimumSize(new Dimension(30,30));
        sd1.setFont(font);

        icon = createImageIcon("images/Dog.gif");
        SizeDisplayer sd2 = new SizeDisplayer("right", icon);
        sd2.setMinimumSize(new Dimension(60,60));
        sd2.setFont(font);

        splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT,
                                   sd1, sd2);
        splitPane.setResizeWeight(0.5);
        splitPane.setOneTouchExpandable(true);
        splitPane.setContinuousLayout(true);

        add(splitPane, BorderLayout.CENTER);
        add(createControlPanel(), BorderLayout.PAGE_END);
    }
    ...
}
The code is fairly self explanatory, except perhaps for the call to setContinuousLayout. Setting the continuousLayout property to true makes the split pane's contents be painted continuously while the user is moving the divider. Continuous layout is not on, by default, because it can have a negative performance impact. However, it makes sense to use it in this demo, when having the split pane's components as up-to-date as possible can improve the user experience.

Nesting Split Panes
Here's a picture of a program that achieves a three-way split by nesting one split pane inside of another:

A snapshot of SplitPaneDemo2

If the top portion of the split pane looks familiar to you, it is because the program puts the split pane created by SplitPaneDemo inside a second split pane. A simple JLabel is the other component in the second split pane. This is not the most practical use of a nested split pane, but it gets the point across.

  • Click the Launch button to run the SplitPaneDemo2 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the SplitPaneDemo2 example

    Here's the interesting part of the code, which you can find in SplitPaneDemo2.java:

    //Create an instance of SplitPaneDemo
SplitPaneDemo splitPaneDemo = new SplitPaneDemo();
JSplitPane top = splitPaneDemo.getSplitPane();

...
//Create a regular old label
label = new JLabel("Click on an image name in the list.",
           JLabel.CENTER);

//Create a split pane and put "top" (a split pane)
//and JLabel instance in it.
JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,
                      top, label);
    Refer to Solving Common Component Problems for information about fixing a border problem that can appear when nesting split panes.

    • The Split Pane API

    The following tables list the commonly used JSplitPane constructors and methods. Other methods you are most likely to invoke on a JSplitPane object are those such as setPreferredSize that its superclasses provide. See The JComponent API for tables of commonly used inherited methods.

    The API for using lists falls into these categories:

    • Setting up the Split Pane
    • Managing the Split Pane's Contents
    • Positioning the Divider

    Setting Up the Split Pane
    Method or Constructor Purpose
    JSplitPane()
    JSplitPane(int)
    JSplitPane(int, boolean)
    JSplitPane(int, Component, Component)
    JSplitPane(int, boolean, Component, Component)     		Create a split pane. When present, the int parameter indicates the split pane's orientation, either HORIZONTAL_SPLIT (the default) or VERTICAL_SPLIT. The boolean parameter, when present, sets whether the components continually repaint as the user drags the split pane. If left unspecified, this option (called continuous layout) is turned off. The Component parameters set the initial left and right, or top and bottom components, respectively.
    void setOrientation(int)
    int getOrientation()     		Set or get the split pane's orientation. Use either HORIZONTAL_SPLIT or VERTICAL_SPLIT defined in JSplitPane. If left unspecified, the split pane will be horizontally split.
    void setDividerSize(int)
    int getDividerSize()     		Set or get the size of the divider in pixels.
    void setContinuousLayout(boolean)
    boolean isContinuousLayout()     		Set or get whether the split pane's components are continually layed out and painted while the user is dragging the divider. By default, continuous layout is turned off.
    void setOneTouchExpandable(boolean)
    boolean isOneTouchExpandable()     		Set or get whether the split pane displays a control on the divider to expand/collapse the divider. The default depends on the look and feel. In the Java look and feel, it is off by default.

    Managing the Split Pane's Contents
    Method | Purpose
    void setTopComponent(Component)
    void setBottomComponent(Component)
    void setLeftComponent(Component)
    void setRightComponent(Component)
    Component getTopComponent()
    Component getBottomComponent()
    Component getLeftComponent()
    Component getRightComponent()     		Set or get the indicated component. Each method works regardless of the split pane's orientation. Top and left are equivalent, and bottom and right are equivalent.
    void remove(Component)
    void removeAll()     		Remove the indicated component(s) from the split pane.
    void add(Component) | Add the component to the split pane. You can add only two components to a split pane. The first component added is the top/left component. The second component added is the bottom/right component. Any attempt to add more components results in an exception.

    Positioning the Divider
    Method | Purpose
    void setDividerLocation(double)
    void setDividerLocation(int)
    int getDividerLocation()     		Set or get the current divider location. When setting the divider location, you can specify the new location as a percentage (double) or a pixel location (int).
    void resetToPreferredSizes() | Move the divider such that both components are at their preferred sizes. This is how a split pane divides itself at startup, unless specified otherwise.
    void setLastDividerLocation(int)
    int getLastDividerLocation()     		Set or get the previous position of the divider.
    int getMaximumDividerLocation()
    int getMinimumDividerLocation()     		Get the minimum and maximum locations for the divider. These are set implicitly by setting the minimum sizes of the split pane's two components.
    void setResizeWeight(float)
    float getResizeWeight()     		Set or get the resize weight for the split pane, a value between 0.0 (the default) and 1.0. See Positioning the Divider and Restricting Its Range for an explanation of and examples of using the resize weight.

    Examples that Use Split Panes

    This table shows some examples that use JSplitPane and where those examples are described.

    Example | Where Described | Notes
    SplitPaneDemo | This page and How to Use Lists | Shows a split pane with a horizontal split.
    SplitPaneDividerDemo | This page | Demonstrates how component size information and resize weight are used to position the divider.
    SplitPaneDemo2 | This page | Puts a split pane within a split pane to create a three-way split.
    TreeDemo | How to Use Trees | Uses a split pane with a vertical split to separate a tree (in a scroll pane) from an editor pane (in a scroll pane). Does not use the one-touch expandable feature.
    TextComponentDemo | Text Component Features | Uses a split pane with a vertical split to separate a text pane and a text area, both in scroll panes.
    TextSamplerDemo | Text Component Features | Uses a split pane with a vertical split and resize weight of 0.5 to separate a text pane and an editor pane, both in scroll panes. The split pane is in the right half of a container that has a fairly complicated layout. Layout managers such as GridLayout and BorderLayout are used, along with the split pane's resize weight, to ensure that the components in scroll panes share all extra space.
    ListSelectionDemo | How to Write a List Selection Listener | Uses a split pane with a vertical split to separate an upper pane, containing a list and a table (both in scroll panes), from a lower pane that contains a combo box above a scroll pane. The lower pane uses a border layout to keep the combo box small and the scroll pane greedy for space.

    « Previous • Trail • Next »
    Problems with the examples? Try Compiling and Running the Examples: FAQs.
    Complaints? Compliments? Suggestions? Give us your feedback.

    Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

             About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
    Copyright 1995-2008 Sun Microsystems, Inc.
    Previous page: How to Use Spinners
    Next page: How to Use Tabbed Panes


How to Use Tabbed Panes (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Tabbed Panes
With the JTabbedPane class, you can have several components, such as panels, share the same space. The user chooses which component to view by selecting the tab corresponding to the desired component. If you want similar functionality without the tab interface, you can use a card layout instead of a tabbed pane.

To Create Tabbed Panes

To create a tabbed pane, instantiate JTabbedPane, create the components you wish it to display, and then add the components to the tabbed pane using the addTab method.

The following picture introduces an application called TabbedPaneDemo that has a tabbed pane with four tabs.

A screenshot of TabbedPaneDemo

Try this:
  1. Click the Launch button to run TabbedPaneDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TabbedPaneDemo Application

  2. Put the cursor over a tab.
    The tool tip associated with the tab appears. As a convenience, you can specify tool tip text when you add a component to the tabbed pane.
  3. Select a tab by clicking it.
    The tabbed pane displays the component corresponding to the tab.
  4. Select a tab by entering its mnemonic.
    For example, in the Java look and feel you can select the tab labeled "Tab 3" by typing Alt-3.
  5. Navigate between scrollable tabs.
    This example provides scrollable tabs. Resize the dialog box by moving its left or right boundary so that tabs do not fit within the dialog. Scroll arrows appear next to the tabs.
    Click the arrow to view one of the hidden tabs.
    Note that clicking the arrow only reveals hidden tabs. It does not select a new tab.

As the TabbedPaneDemo example shows, a tab can have a tool tip and a mnemonic, and it can display both text and an image.

Tab Placement

The default tab placement is set to the TOP location, as shown above. You can change the tab placement to LEFT, RIGHT, TOP or BOTTOM by using the setTabPlacement method.

Code for Tabbed Panes

The following code from TabbedPaneDemo.java creates the tabbed pane in the previous example. Note that no event-handling code is necessary. The JTabbedPane object takes care of mouse and keyboard events for you.
JTabbedPane tabbedPane = new JTabbedPane();
ImageIcon icon = createImageIcon("images/middle.gif");

JComponent panel1 = makeTextPanel("Panel #1");
tabbedPane.addTab("Tab 1", icon, panel1,
                  "Does nothing");
tabbedPane.setMnemonicAt(0, KeyEvent.VK_1);

JComponent panel2 = makeTextPanel("Panel #2");
tabbedPane.addTab("Tab 2", icon, panel2,
                  "Does twice as much nothing");
tabbedPane.setMnemonicAt(1, KeyEvent.VK_2);

JComponent panel3 = makeTextPanel("Panel #3");
tabbedPane.addTab("Tab 3", icon, panel3,
                  "Still does nothing");
tabbedPane.setMnemonicAt(2, KeyEvent.VK_3);

JComponent panel4 = makeTextPanel(
        "Panel #4 (has a preferred size of 410 x 50).");
panel4.setPreferredSize(new Dimension(410, 50));
tabbedPane.addTab("Tab 4", icon, panel4,
                      "Does nothing at all");
tabbedPane.setMnemonicAt(3, KeyEvent.VK_4);
As the previous code shows, the addTab method handles the bulk of the work in setting up a tab in a tabbed pane. The addTab method has several forms, but they all use both a string title and the component to be displayed by the tab. Optionally, you can specify an icon and tool tip string. The text or icon (or both) can be null. Another way to create a tab is to use the insertTab method, which lets you specify the index of the tab you're adding. Note that the addTab method does not allow index specification in this step.

To Switch to Specific Tabs

There are three ways to switch to specific tabs using GUI.
  1. Using a mouse. To switch to a specific tab, the user clicks it with the mouse.
  2. Using keyboard arrows. When the JTabbedPane object has the focus, the keyboard arrows can be used to switch from tab to tab.
  3. Using key mnemonics. The setMnemonicAt method allows the user to switch to a specific tab using the keyboard. For example, setMnemonicAt(3, KeyEvent.VK_4) makes '4' the mnemonic for the fourth tab (which is at index 3, since the indices start with 0); pressing Alt-4 makes the fourth tab's component appear. Often, a mnemonic uses a character in the tab's title that is then automatically underlined.
To switch to a specific tab programmatically, use the setSelectedIndex or the setSelectedComponent methods.

Preferred Size in Tabs

When building components to add to a tabbed pane, keep in mind that no matter which child of a tabbed pane is visible, each child gets the same amount of space in which to display itself. The preferred size of the tabbed pane is just big enough to display its tallest child at its preferred height, and its widest child at its preferred width. Similarly, the minimum size of the tabbed pane depends on the biggest minimum width and height of all its children.

In the TabbedPaneDemo example, the fourth panel has a preferred width and height that are larger than those of the other panels. Thus, the preferred size of the tabbed pane is just big enough to display the fourth panel at its preferred size. Every panel gets exactly the same amount of space — 410 pixels wide and 50 high, assuming the tabbed pane is at its preferred size. If you do not understand how preferred size is used, please refer to How Layout Management Works.

Tabs With Custom Components

The TabComponentsDemo example introduces a tabbed pane whose tabs contain real components. The use of custom components brings new features such as buttons, combo boxes, labels and other components to tabs, and allows more complex user interaction.

Here is a tabbed pane with close buttons on its tabs.

A screenshot of TabComponentsDemo

Try this:
  1. Click the Launch button to run TabComponentsDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TabComponentsDemo Application

  2. Put the cursor over a tab.
  3. Select a tab by clicking it (make sure not to hit the little cross).
  4. Put the cursor over one of the widgets with a little cross.
    The cross turns magenta and gets enclosed in a square. A tool tip associated with the close button appears.
    Click the cross with the left mouse button to close the tab.
  5. Restore the tabs that have been removed by choosing the Reset JTabbedPane item from the Options menu.
  6. Note that tabs with custom components are displayed on top of original tabbed pane tabs.
    To view the tabs underneath, open the Options menu and clear the Use TabComponents checkbox.
  7. Display the tabs with components by selecting the Use TabComponents checkbox again.
  8. Close all tabs. Now the tabbed pane is empty.

To Remove Tabs

The following code from ButtonTabComponent.java removes a tab from the tabbed pane. Note that event-handling code is necessary. Since each tab contains a real JButton object, you must attach an ActionListener to the close button. As the user clicks the button, the actionPerformed method determines the index of the tab it belongs to and removes the corresponding tab.
public void actionPerformed(ActionEvent e) {
    int i = pane.indexOfTabComponent(ButtonTabComponent.this);
    if (i != -1) {
    pane.remove(i);
    }
}

To Give Titles to Customized Tabs

The code below, taken from ButtonTabComponent.java, shows how a customized tab component gets a title from an original tabbed pane tab.
JLabel label = new JLabel(title) {
    public String getText() {
        int i = pane.indexOfTabComponent(ButtonTabComponent.this);
    if (i != -1) {
        return pane.getTitleAt(i);
    }
    return null;
    }
};

The Tabbed Pane API

The following tables list the commonly used JTabbedPane constructors and methods. The API for using tabbed panes falls into the following categories:
  • Creating and Setting Up a Tabbed Pane
  • Inserting, Removing, Finding, and Selecting Tabs
  • Changing Tab Appearance
  • Setting Up Custom Components on Tabs

Creating and Setting Up a Tabbed Pane
Method or Constructor Purpose
JTabbedPane()
JTabbedPane(int)
JTabbedPane(int, int) 		Creates a tabbed pane. The first optional argument specifies where the tabs should appear. By default, the tabs appear at the top of the tabbed pane. You can specify these positions (defined in the SwingConstants interface, which JTabbedPane implements): TOP, BOTTOM, LEFT, RIGHT. The second optional argument specifies the tab layout policy. You can specify one of these policies (defined in JTabbedPane): WRAP_TAB_LAYOUT or SCROLL_TAB_LAYOUT.
addTab(String, Icon, Component, String)
addTab(String, Icon, Component)
addTab(String, Component) 		Adds a new tab to the tabbed pane. The first argument specifies the text on the tab. The optional icon argument specifies the tab's icon. The component argument specifies the component that the tabbed pane should show when the tab is selected. The fourth argument, if present, specifies the tool tip text for the tab.
void setTabLayoutPolicy(int)
int getTabLayoutPolicy() 		Sets or gets the policy that the tabbed pane uses in laying out tabs when all tabs do not fit within a single run. Possible values are WRAP_TAB_LAYOUT and SCROLL_TAB_LAYOUT. The default policy is WRAP_TAB_LAYOUT.
void setTabPlacement(int)
int getTabPlacement() 		Sets or gets the location where the tabs appear relative to the content. Possible values (defined in SwingConstants, which is implemented by JTabbedPane) are TOP, BOTTOM, LEFT, and RIGHT.

Inserting, Removing, Finding, and Selecting Tabs
Method | Purpose
insertTab(String, Icon, Component, String, int) | Inserts a tab at the specified index, where the first tab is at index 0. The arguments are the same as for addTab.
remove(Component)
removeTabAt(int) 		Removes the tab corresponding to the specified component or index.
removeAll() | Removes all tabs.
int indexOfComponent(Component)
int indexOfTab(String)
int indexOfTab(Icon) 		Returns the index of the tab that has the specified component, title, or icon.
void setSelectedIndex(int)
void setSelectedComponent(Component) 		Selects the tab that has the specified component or index. Selecting a tab has the effect of displaying its associated component.
int getSelectedIndex()
Component getSelectedComponent() 		Returns the index or component for the selected tab.

Changing Tab Appearance
Method Purpose
void setComponentAt(int, Component)
Component getComponentAt(int) 		Sets or gets which component is associated with the tab at the specified index. The first tab is at index 0.
void setTitleAt(int, String)
String getTitleAt(int) 		Sets or gets the title of the tab at the specified index.
void setIconAt(int, Icon)
Icon getIconAt(int)
void setDisabledIconAt(int, Icon)
Icon getDisabledIconAt(int) 		Sets or gets the icon displayed by the tab at the specified index.
void setBackgroundAt(int, Color)
Color getBackgroundAt(int)
void setForegroundAt(int, Color)
Color getForegroundAt(int) 		Sets or gets the background or foreground color used by the tab at the specified index. By default, a tab uses the tabbed pane's background and foreground colors. For example, if the tabbed pane's foreground is black, then each tab's title is black except for any tabs for which you specify another color using setForegroundAt.
void setEnabledAt(int, boolean)
boolean isEnabledAt(int) 		Sets or gets the enabled state of the tab at the specified index.
void setMnemonicAt(int, int)
int getMnemonicAt(int) 		Sets or gets the keyboard mnemonic for accessing the specified tab.
void setDisplayedMnemonicIndexAt(int, int)
int getDisplayedMnemonicIndexAt(int) 		Sets or gets which character should be decorated to represent the mnemonic. This is useful when the mnemonic character appears multiple times in the tab's title and you don't want the first occurrence underlined.
void setToolTipTextAt(int, String)
String getToolTipTextAt(int) 		Sets or gets the text displayed on tool tips for the specified tab.

Setting Up Custom Components on Tabs
Method | Purpose
void setTabComponentAt(int, Component) | Sets the component that is responsible for rendering the title or icon (or both) for the tab specified by the first argument. When a null value is specified, JTabbedPane renders the title or icon. The same component cannot be used for several tabs.
Component getTabComponentAt(int) | Gets the tab component for the tab at the index specified by the argument. If there is no tab component for the specified tab, a null value is returned.
int indexOfTabComponent(Component) | Checks if the specified component belongs to one of the tabs. Return the index of the corresponding tab or -1 if there is no such a tab.

Examples That Use Tabbed Panes

This table lists examples that use JTabbedPane and points to where those examples are described.

Example | Where Described | Notes
TabbedPaneDemo | This page | Demonstrates a few tabbed pane features, such as tool tips, icons, scrollable layout, and mnemonics.
TabComponentsDemo | This page | Demonstrates custom components on tabs. Uses a tabbed pane with close buttons.
BoxAlignmentDemo | How to Use BoxLayout | Uses a JTabbedPane as the only child of a frame's content pane.
BorderDemo | How to Use Borders | Uses its tabbed pane in a manner similar to BoxAlignmentDemo.
DialogDemo | How to Use Dialogs | Has a tabbed pane in the center of a frame's content pane, with a label below it.
DragFileDemo | Introduction to DnD | Uses a tabbed pane at the bottom of the window to display the contents of one or more files. The tabbed pane isn't used until the user selects a file. The tabbed pane's state is controlled by an object of the custom type TabbedPaneController.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Split Panes
Next page: How to Use Tables


How to Use Tables (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Tables
This section has been updated to reflect features and conventions of the latest release, JDK 6.0, but it is not yet final. We've published this preliminary version so you can get the most current information now, and so you can tell us (please!) about errors, omissions, or improvements we can make to this tutorial.

With the JTable class you can display tables of data, optionally allowing the user to edit the data. JTable does not contain or cache data; it is simply a view of your data. Here is a picture of a typical table displayed within a scroll pane:

A snapshot of TableDemo, which displays a typical table.

The rest of this section shows you how to accomplish some common table-related tasks. Here are the topics this section covers:

  • Creating a Simple Table
  • Adding a Table to a Container
  • Setting and Changing Column Widths
  • User Selections
  • Creating a Table Model
  • Listening for Data Changes
  • Firing Data Change Events
  • Concepts: Editors and Renderers
  • Using Custom Renderers
  • Specifying Tool Tips for Cells
  • Specifying Tool Tips for Column Headers
  • Sorting and Filtering
  • Using a Combo Box as an Editor
  • Using Other Editors
  • Using an Editor to Validate User-Entered Text
  • Printing
  • Examples that Use Tables

Creating a Simple Table

Try this:

  1. Click the Launch button to run SimpleTableDemo using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

    Launches the SimpleTableDemo example

  2. Click the cell that contains "Snowboarding".
    The entire first row is selected, indicating that you have selected Mary Campione's data. A special highlight indicates that the "Snowboarding" cell is editable. Generally, you begin editing a text cell by double-clicking it.

  3. Position the cursor over "First Name". Now press the mouse button and drag to the right.
    As you can see, users can rearrange columns in tables.

  4. Position the cursor just to the right of a column header. Now press the mouse button and drag to the right or left.
    The column changes size, and the other columns adjust to fill the remaining space.

  5. Resize the window containing the table so that it's bigger than necessary to display the whole table.
    All the table cells become wider, expanding to fill the extra horizontal space.

The table in SimpleTableDemo.java declares the column names in a String array:

String[] columnNames = {"First Name",
                        "Last Name",
                        "Sport",
                        "# of Years",
                        "Vegetarian"};

Its data is initialized and stored in a two-dimensional Object array:

Object[][] data = {
    {"Mary", "Campione",
     "Snowboarding", new Integer(5), new Boolean(false)},
    {"Alison", "Huml",
     "Rowing", new Integer(3), new Boolean(true)},
    {"Kathy", "Walrath",
     "Knitting", new Integer(2), new Boolean(false)},
    {"Sharon", "Zakhour",
     "Speed reading", new Integer(20), new Boolean(true)},
    {"Philip", "Milne",
     "Pool", new Integer(10), new Boolean(false)}
};

Then the Table is constructed using these data and columnNames:

JTable table = new JTable(data, columnNames);

There are two JTable constructors that directly accept data (SimpleTableDemo uses the first):

  • JTable(Object[][] rowData, Object[] columnNames)
  • JTable(Vector rowData, Vector columnNames)

The advantage of these constructors is that they are easy to use. However, these constructors also have disadvantages:

  • They automatically make every cell editable.
  • They treat all data types the same (as strings). For example, if a table column has Boolean data, the table can display the data in a check box. However, if you use one of the two JTable constructors listed previously, your Boolean data will be displayed as a string. You can see this difference in the last column of the two previous pictures of tables.
  • They require that you put all of the table's data in an array or vector, which may not be appropriate for some data. For example, if you are instantiating a set of objects from a database, you might want to query the objects directly for their values, rather than copying all their values into an array or vector.

If you want to get around these restrictions, you need to implement your own table model, as described in Creating a Table Model.

Adding a Table to a Container

Here is typical code for creating a scroll pane that serves as a container for a table:

JScrollPane scrollPane = new JScrollPane(table);
table.setFillsViewportHeight(true);

The two lines in this snippet do the following:

  • The JScrollPane constructor is invoked with an argument that refers to the table object. This creates a scroll pane as a container for the table; the table is automatically added to the container.
  • JTable.setFillsViewportHeight is invoked to set the fillsViewportHeight property. When this property is true the table uses the entire height of the container, even if the table doesn't have enough rows to use the whole vertical space. This makes it easier to use the table as a drag-and-drop target.

The scroll pane automatically places the table header at the top of the viewport. The column names remain visible at the top of the viewing area when the table data is scrolled.

If you are using a table without a scroll pane, then you must get the table header component and place it yourself. For example:

container.setLayout(new BorderLayout());
container.add(table.getTableHeader(), BorderLayout.PAGE_START);
container.add(table, BorderLayout.CENTER);

Setting and Changing Column Widths

By default, all columns in a table start out with equal width, and the columns automatically fill the entire width of the table. When the table becomes wider or narrower (which might happen when the user resizes the window containing the table), all the column widths change appropriately.

When the user resizes a column by dragging its right border, then either other columns must change size, or the table's size must change. By default, the table's size remains the same, and all columns to the right of the drag point resize to accommodate space added to or removed from the column to the left of the drag point.

To customize initial column widths, you can invoke setPreferredWidth on each of your table's columns. This sets both the preferred widths of the columns and their approximate relative widths. For example, adding the following code to SimpleTableDemo makes its third column bigger than the other columns:

TableColumn column = null;
for (int i = 0; i < 5; i++) {
    column = table.getColumnModel().getColumn(i);
    if (i == 2) {
        column.setPreferredWidth(100); //third column is bigger
    } else {
        column.setPreferredWidth(50);
    }
}

As the preceding code shows, each column in a table is represented by a TableColumn object. TableColumn supplies getter and setter methods for the minimum, preferred, and maximum widths of a column, as well as a method for getting the current width. For an example of setting cell widths based on an approximation of the space needed to draw the cells' contents, see the initColumnSizes method in TableRenderDemo.java.

When the user explicitly resizes columns, the columns' preferred widths are set such that the user-specified sizes become the columns' new current widths. However, when table itself is resized — typically because the window has resized —; the columns' preferred widths do not change. Instead, the existing preferred widths are used to calculate new column widths to fill the available space.

You can change a table's resize behavior by invoking setAutoResizeMode.

User Selections

In its default configuration, a table supports a selection that consists of one or more rows. The user can select a contiguous range of rows or an arbitrary set of rows. The last cell that the user indicated gets a special indication; in the Metal look and feel, the cell is outlined. This cell is known as the lead selection; it is sometimes called "the cell with the focus" or "the current cell".

The user uses the mouse and/or keyboard to make selections, as described in the following table:

Operation | Mouse Action | Keyboard Action
Select single row. | Click. | Up Arrow or Down Arrow.
Extend contiguous selection. | Shift-Click or Drag over rows. | Shift-Up Arrow or Shift-Down Arrow.
Add row to selection/toggle row selection. | Control-Click | Move lead selection with Control-Up Arrow or Control-Down Arrow, then use Space Bar to add to selection or Control-Space Bar to toggle row selection.

To see how selections work, click the Launch button to run TableSelectionDemo using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

Launches the TableSelectionDemo example

This example program presents the familiar table, and allows the user to manipulate certain JTable options. There is also a text pane that logs selection events.

In the screenshot below, a user has run the program, clicked in the first row, then control-clicked in the third row. Notice the outline around the last cell clicked; this is how the Metal look and feel highlights the lead selection.

TableSelectionDemo with a non-contiguous row selection.

Under "Selection Mode" there are a set of radio buttons. Click the one labelled "Single Selection". Now you can only select one row at a time. If you click on the "Single Interval Selection" radio button, you can select a set of rows that must be contiguous.

All of the radio buttons under "Selection Mode" invoke JTable.setSelectionMode. This method takes a single argument, which must be one of the following constants defined in javax.swing.ListSelectionModel: MULTIPLE_INTERVAL_SELECTION, SINGLE_INTERVAL_SELECTION, and SINGLE_SELECTION.

Returning to TableSelectionDemo, notice the three option checkboxes under "Selection Options." Each of checkbox controls the state of a boolean bound variable defined by JTable:

  • "Row Selection" controls rowSelectionAllowed which has setter method setRowSelectionAllowed and getter method getRowSelectionAllowed. When this bound property is true (and the columnSelectionAllowed property is false), the user can select by row.
  • "Column Selection" controls columnSelectionAllowed which has setter method setColumnSelectionAllowed and getter method getColumnSelectionAllowed. When this bound property is true (and the rowSelectionAllowed bound property is false), the user can select by column.
  • "Cell Selection" controls cellSelectionEnabled, which has setter method setCellSelectionEnabled and getter method getCellSelectionEnabled. When this bound property is true, the user can select a single cell or rectangular block of cells.
NOTE: JTable uses a very simple concept of selection, managed as an intersection of rows and columns. It was not designed to handle fully independent cell selections.

If you clear all three check boxes (setting all three bound properties to false), there is no selection; only the lead selection is shown.

You may notice that the "Cell Selection" checkbox is disabled in multiple interval selection mode. This is because cell selection is not supported in this mode in the demo. You can specify selection by cell in multiple interval selection mode, but the result is a table that does not produce useful selections.

You may also notice that changing any of the three selection options can affect the others. This is because allowing both row selection and column selection is exactly the same as enabling cell selection. JTable automatically updates the three bound variables as necessary to keep them consistent.

NOTE: Setting cellSelectionEnabled to a value has the side effect of also setting both rowSelectionEnabled and columnSelectionEnabled to that value. Setting both rowSelectionEnabled and columnSelectionEnabled to a value has the side effect of also setting cellSelectionEnabled to that value. Setting rowSelectionEnabled and columnSelectionEnabled to different values has the side effect of also setting cellSelectionEnabled to false.

To retrieve the current selection, use JTable.getSelectedRows which returns an array of row indexes, and JTable.getSelectedColumns which returns an array of column indexes. To retrieve the coordinates of the lead selection, refer to the selection models for the table itself and for the table's column model. The following code formats a string containing the row and column of the lead selection:

String.format("Lead Selection: %d, %d. ",
    table.getSelectionModel().getLeadSelectionIndex(),
    table.getColumnModel().getSelectionModel().getLeadSelectionIndex());

User selections generate a number of events. For information on these, refer to How to Write a List Selection Listener in the Writing Event Listeners lesson.

NOTE: Selection data actually describes selected cells in the "view" (table data as it appears after any sorting or filtering) rather than in the table model. This distinction does not matter unless your viewed data has been rearranged by sorting, filtering, or user manipulation of columns. In that case, you must convert selection coordinates using the conversion methods described in Sorting and Filtering.

Creating a Table Model

Every table object uses a table model object to manage the actual table data. A table model object must implement the TableModel interface. If the programmer does not provide a table model object, JTable automatically creates an instance of DefaultTableModel. This relationship is illustrated below.

Relation between table, table object, model object

The JTable constructor used by SimpleTableDemo creates its table model with code like this:

new AbstractTableModel() {
    public String getColumnName(int col) {
        return columnNames[col].toString();
    }
    public int getRowCount() { return rowData.length; }
    public int getColumnCount() { return columnNames.length; }
    public Object getValueAt(int row, int col) {
        return rowData[row][col];
    }
    public boolean isCellEditable(int row, int col)
        { return true; }
    public void setValueAt(Object value, int row, int col) {
        rowData[row][col] = value;
        fireTableCellUpdated(row, col);
    }
}

As the preceding code shows, implementing a table model can be simple. Generally, you implement your table model in a subclass of the AbstractTableModel class.

Your model might hold its data in an array, vector, or hash map, or it might get the data from an outside source such as a database. It might even generate the data at execution time.

This table is different from the SimpleTableDemo table in the following ways:

  • TableDemo's custom table model, even though it is simple, can easily determine the data's type, helping the JTable display the data in the best format. SimpleTableDemo's automatically created table model, on the other hand, does not know that the # of Years column contains numbers (which should generally be right aligned and have a particular format). It also does not know that the Vegetarian column contains boolean values, which can be represented by check boxes.
  • The custom table model implemented in TableDemo does not let you edit the name columns; it does, however, let you edit the other columns. In SimpleTableDemo, all cells are editable.

See below the code taken from TableDemo.java that is different from the SimpleTableDemo.java. Bold font indicates the code that makes this table's model different from the table model defined automatically for SimpleTableDemo.

public TableDemo() {
    ...
    JTable table = new JTable(new MyTableModel());
    ...
}

class MyTableModel extends AbstractTableModel {
    private String[] columnNames = ...//same as before...
    private Object[][] data = ...//same as before...

    public int getColumnCount() {
        return columnNames.length;
    }

    public int getRowCount() {
        return data.length;
    }

    public String getColumnName(int col) {
        return columnNames[col];
    }

    public Object getValueAt(int row, int col) {
        return data[row][col];
    }

    public Class getColumnClass(int c) {
        return getValueAt(0, c).getClass();
    }

    /*
     * Don't need to implement this method unless your table's
     * editable.
     */
    public boolean isCellEditable(int row, int col) {
        //Note that the data/cell address is constant,
        //no matter where the cell appears onscreen.
        if (col < 2) {
            return false;
        } else {
            return true;
        }
    }

    /*
     * Don't need to implement this method unless your table's
     * data can change.
     */
    public void setValueAt(Object value, int row, int col) {
        data[row][col] = value;
        fireTableCellUpdated(row, col);
    }
    ...
}

Listening for Data Changes

A table model can have a set of listeners that are notified whenever the table data changes. Listeners are instances of TableModelListener. In the following example code, SimpleTableDemo is extended include such a listener. New code is in bold.

import javax.swing.event.*;
import javax.swing.table.TableModel;

public class SimpleTableDemo ... implements TableModelListener {
    ...
    public SimpleTableDemo() {
        ...
        table.getModel().addTableModelListener(this);
        ...
    }

    public void tableChanged(TableModelEvent e) {
        int row = e.getFirstRow();
        int column = e.getColumn();
        TableModel model = (TableModel)e.getSource();
        String columnName = model.getColumnName(column);
        Object data = model.getValueAt(row, column);

        ...// Do something with the data...
    }
    ...
}

Firing Data Change Events

In order to fire data change events the table model must know how to construct a TableModelEvent object. This can be a complex procedure, but is already implemented in DefaultTableModel. You can either allow JTable to use its default instance of DefaultTableModel, or create your own custom subclass of DefaultTableModel.

If DefaultTableModel is not a suitable base class for your custom table model class, consider subclassing AbstractTableModel. This class implements a simple framework for constructing TableModelEvent objects. Your custom class simply needs to invoke one the following AbstractTableModel methods each time table data is changed by an external source.

Method | Change
fireTableCellUpdated | Update of specified cell.
fireTableRowsUpdated | Update of specified rows
fireTableDataChanged | Update of entire table (data only).
fireTableRowsInserted | New rows inserted.
fireTableRowsDeleted | Existing rows Deleted
fireTableStructureChanged | Invalidate entire table, both data and structure.

Concepts: Editors and Renderers

Before you go on to the next few tasks, you need to understand how tables draw their cells. You might expect each cell in a table to be a component. However, for performance reasons, Swing tables are implemented differently.

Instead, a single cell renderer is generally used to draw all of the cells that contain the same type of data. You can think of the renderer as a configurable ink stamp that the table uses to stamp appropriately formatted data onto each cell. When the user starts to edit a cell's data, a cell editor takes over the cell, controlling the cell's editing behavior.

For example, each cell in the # of Years column in TableDemo contains Number data — specifically, an Integer object. By default, the cell renderer for a Number-containing column uses a single JLabel instance to draw the appropriate numbers, right-aligned, on the column's cells. If the user begins editing one of the cells, the default cell editor uses a right-aligned JTextField to control the cell editing.

To choose the renderer that displays the cells in a column, a table first determines whether you specified a renderer for that particular column. If you did not, then the table invokes the table model's getColumnClass method, which gets the data type of the column's cells. Next, the table compares the column's data type with a list of data types for which cell renderers are registered. This list is initialized by the table, but you can add to it or change it. Currently, tables put the following types of data in the list:

  • Boolean — rendered with a check box.
  • Number — rendered by a right-aligned label.
  • Double, Float — same as Number, but the object-to-text translation is performed by a NumberFormat instance (using the default number format for the current locale).
  • Date — rendered by a label, with the object-to-text translation performed by a DateFormat instance (using a short style for the date and time).
  • ImageIcon, Icon — rendered by a centered label.
  • Object — rendered by a label that displays the object's string value.

Cell editors are chosen using a similar algorithm.

Remember that if you let a table create its own model, it uses Object as the type of every column. To specify more precise column types, the table model must define the getColumnClass method appropriately, as demonstrated by TableDemo.java.

Keep in mind that although renderers determine how each cell or column header looks and can specify its tool tip text, a renderer does not handle events. If you need to pick up the events that take place inside a table, the technique you use varies by the sort of event you are interested in:

Situation | How to Get Events
To detect events from a cell that is being edited... | Use the cell editor (or register a listener on the cell editor).
To detect row/column/cell selections and deselections... | Use a selection listener as described in Detecting User Selections.
To detect mouse events on a column header... | Register the appropriate type of mouse listener on the table's JTableHeader object. (See TableSorter.java for an example.)
To detect other events... | Register the appropriate listener on the JTable object.

The next few sections tell you how to customize display and editing by specifying renderers and editors. You can specify cell renderers and editors either by column or by data type.

Using Custom Renderers

This section tells you how to create and specify a cell renderer. You can set a type-specific cell renderer using the JTable method setDefaultRenderer. To specify that cells in a particular column should use a renderer, you use the TableColumn method setCellRenderer. You can even specify a cell-specific renderer by creating a JTable subclass.

It is easy to customize the text or image rendered by the default renderer, DefaultTableCellRenderer. You just create a subclass and implement the setValue method so that it invokes setText or setIcon with the appropriate string or image. For example, here is how the default date renderer is implemented:

static class DateRenderer extends DefaultTableCellRenderer {
    DateFormat formatter;
    public DateRenderer() { super(); }

    public void setValue(Object value) {
        if (formatter==null) {
            formatter = DateFormat.getDateInstance();
        }
        setText((value == null) ? "" : formatter.format(value));
    }
}

If extending DefaultTableCellRenderer is insufficient, you can build a renderer using another superclass. The easiest way is to create a subclass of an existing component, making your subclass implement the TableCellRenderer interface. TableCellRenderer requires just one method: getTableCellRendererComponent. Your implementation of this method should set up the rendering component to reflect the passed-in state, and then return the component.

In the snapshot of TableDialogEditDemo, the renderer used for Favorite Color cells is a subclass of JLabel called ColorRenderer. Here are excerpts from ColorRenderer.java that show how it is implemented.

public class ColorRenderer extends JLabel
                           implements TableCellRenderer {
    ...
    public ColorRenderer(boolean isBordered) {
        this.isBordered = isBordered;
        setOpaque(true); //MUST do this for background to show up.
    }

    public Component getTableCellRendererComponent(
                            JTable table, Object color,
                            boolean isSelected, boolean hasFocus,
                            int row, int column) {
        Color newColor = (Color)color;
        setBackground(newColor);
        if (isBordered) {
            if (isSelected) {
                ...
                //selectedBorder is a solid border in the color
                //table.getSelectionBackground().
                setBorder(selectedBorder);
            } else {
                ...
                //unselectedBorder is a solid border in the color
                //table.getBackground().
                setBorder(unselectedBorder);
            }
        }

        setToolTipText(...); //Discussed in the following section
        return this;
    }
}

Here is the code from TableDialogEditDemo.java that registers a ColorRenderer instance as the default renderer for all Color data:

table.setDefaultRenderer(Color.class, new ColorRenderer(true));

To specify a cell-specific renderer, you need to define a JTable subclass that overrides the getCellRenderer method. For example, the following code makes the first cell in the first column of the table use a custom renderer:

TableCellRenderer weirdRenderer = new WeirdRenderer();
table = new JTable(...) {
    public TableCellRenderer getCellRenderer(int row, int column) {
        if ((row == 0) && (column == 0)) {
            return weirdRenderer;
        }
        // else...
        return super.getCellRenderer(row, column);
    }
};

Specifying Tool Tips for Cells

By default, the tool tip text displayed for a table cell is determined by the cell's renderer. However, sometimes it can be simpler to specify tool tip text by overriding JTable's implementation of the getToolTipText(MouseEvent) method. This section shows you how to use both techniques.

To add a tool tip to a cell using its renderer, you first need to get or create the cell renderer. Then, after making sure the rendering component is a JComponent, invoke the setToolTipText method on it.

An example of setting tool tips for cells is in TableRenderDemo. Click the Launch button to run it using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

Launches the TableRenderDemo example

The source code is in TableRenderDemo.java. It adds tool tips to the cells of the Sport column with the following code:

//Set up tool tips for the sport cells.
DefaultTableCellRenderer renderer =
        new DefaultTableCellRenderer();
renderer.setToolTipText("Click for combo box");
sportColumn.setCellRenderer(renderer);

Although the tool tip text in the previous example is static, you can also implement tool tips whose text changes depending on the state of the cell or program. Here are a couple ways to do so:

  • Add a bit of code to the renderer's implementation of the getTableCellRendererComponent method.
  • Override the JTable method getToolTipText(MouseEvent).

An example of adding code to a cell renderer is in TableDialogEditDemo. Click the Launch button to run it using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

Launches the TableDialogEditDemo example

TableDialogEditDemo uses a renderer for colors, implemented in ColorRenderer.java, that sets the tool tip text using the boldface code in the following snippet:

public class ColorRenderer extends JLabel
                           implements TableCellRenderer {
    ...
    public Component getTableCellRendererComponent(
                            JTable table, Object color,
                            boolean isSelected, boolean hasFocus,
                            int row, int column) {
        Color newColor = (Color)color;
        ...
        setToolTipText("RGB value: " + newColor.getRed() + ", "
                                     + newColor.getGreen() + ", "
                                     + newColor.getBlue());
        return this;
    }
}

Here is an example of what the tool tip looks like:

TableDialogEditDemo with a tool tip describing the moused-over cell's RGB value

You can specify tool tip text by overriding JTable's getToolTipText(MouseEvent) method. The program TableToolTipsDemo shows how. Click the Launch button to run it using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

Launches the TableToolTipsDemo example

The cells with tool tips are in the Sport and Vegetarian columns. Here is a picture of its tool tip:

TableToolTipsDemo with a tool tip for a cell in the Sport column

Here is the code from TableToolTipsDemo.java that implements tool tips for cells in the Sport and Vegetarian columns:

JTable table = new JTable(new MyTableModel()) {
    //Implement table cell tool tips.
    public String getToolTipText(MouseEvent e) {
        String tip = null;
        java.awt.Point p = e.getPoint();
        int rowIndex = rowAtPoint(p);
        int colIndex = columnAtPoint(p);
        int realColumnIndex = convertColumnIndexToModel(colIndex);

        if (realColumnIndex == 2) { //Sport column
            tip = "This person's favorite sport to "
                   + "participate in is: "
                   + getValueAt(rowIndex, colIndex);

        } else if (realColumnIndex == 4) { //Veggie column
            TableModel model = getModel();
            String firstName = (String)model.getValueAt(rowIndex,0);
            String lastName = (String)model.getValueAt(rowIndex,1);
            Boolean veggie = (Boolean)model.getValueAt(rowIndex,4);
            if (Boolean.TRUE.equals(veggie)) {
                tip = firstName + " " + lastName
                      + " is a vegetarian";
            } else {
                tip = firstName + " " + lastName
                      + " is not a vegetarian";
            }

        } else { //another column
            //You can omit this part if you know you don't
            //have any renderers that supply their own tool
            //tips.
            tip = super.getToolTipText(e);
        }
        return tip;
    }
    ...
}

The code is fairly straightforward, except perhaps for the call to convertColumnIndexToModel. That call is necessary because if the user moves the columns around, the view's index for the column will not match the model's index for the column. For example, the user might drag the Vegetarian column (which the model considers to be at index 4) so it is displayed as the first column — at view index 0. Since prepareRenderer provides the view index, you need to translate the view index to a model index so you can be sure the intended column has been selected.

Specifying Tool Tips for Column Headers

You can add a tool tip to a column header by setting the tool tip text for the table's JTableHeader. Often, different column headers require different tool tip text. You can change the text by overriding the table header's getToolTipText method. Alternately, you can invoke TableColumn.setHeaderRenderer to provide a custom renderer for the header.

An example of using the same tool tip text for all column headers is in TableToolTipsDemo.java has an example of implementing column header tool tips that vary by column. If you run TableToolTipsDemo (click the Launch button) using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

Launches the TableToolTipsDemo example

You will see the tool tips when you mouse over any column header except for the first two. No tool tips were suppled for the name columns since they seemed self-explanatory. Here is a picture of one of the column header tool tips:

TableToolTipsDemo with a tool tip for a column header

The following code implements the tool tips. Basically, it creates a subclass of JTableHeader that overrides the getToolTipText(MouseEvent) method so that it returns the text for the current column. To associate the revised table header with the table, the JTable method createDefaultTableHeader is overridden so that it returns an instance of the JTableHeader subclass.

protected String[] columnToolTips = {
    null, // "First Name" assumed obvious
    null, // "Last Name" assumed obvious
    "The person's favorite sport to participate in",
    "The number of years the person has played the sport",
    "If checked, the person eats no meat"};
...

JTable table = new JTable(new MyTableModel()) {
    ...

    //Implement table header tool tips.
    protected JTableHeader createDefaultTableHeader() {
        return new JTableHeader(columnModel) {
            public String getToolTipText(MouseEvent e) {
                String tip = null;
                java.awt.Point p = e.getPoint();
                int index = columnModel.getColumnIndexAtX(p.x);
                int realIndex =
                        columnModel.getColumn(index).getModelIndex();
                return columnToolTips[realIndex];
            }
        };
    }
};

Sorting and Filtering

Table sorting and filtering is managed by a sorter object. The easiest way to provide a sorter object is to set autoCreateRowSorter bound property to true:

JTable table = new JTable();
table.setAutoCreateRowSorter(true);

This action defines a row sorter that is an instance of javax.swing.table.TableRowSorter. This provides a table that does a simple locale-specific sort when the user clicks on a column header. This is demonstrated in TableSortDemo.java, as seen in this screen shot:

TableSortDemo after clicking Last Name

To have more control over sorting, you can construct an instance of TableRowSorter and specify that it is the sorter object for your table.

TableRowSorter<TableModel> sorter
    = new TableRowSorter<TableModel>(table.getModel());
table.setRowSorter(sorter);

TableRowSorter uses java.util.Comparator objects to sort its rows. A class that implements this interface must provide a class called compare that defines how any two objects are compared for the purpose of sorting. For example, the following code creates a Comparator that sorts a set of strings by the last word in each string:

Comparator<String> comparator = new Comparator<String>() {
    public int compare(String s1, String s2) {
        String[] strings1 = s1.split("\\s");
        String[] strings2 = s2.split("\\s");
        return strings1[strings1.length - 1]
            .compareTo(strings2[strings2.length - 1]);
    }
};

This example is fairly simplistic; more typically, a Comparator implementation is a subclass of java.text.Collator. You can define your own subclass, use the factory methods in Collator to obtain a Comparator for a specific locale, or use java.text.RuleBasedCollator.

To determine which Comparator to use for a column, TableRowSorter attempts to apply each of the following rules in turn. Rules are followed in the order listed below; the first rule that provides the sorter with a Comparator is used, and the remainining rules ignored.

  1. If a comparator has been specified by invoking setComparator, use that comparator.
  2. If the table model reports that the column data consists of strings (TableModel.getColumnClass returns String.class for that column), use a comparator that sorts the strings based on the current locale.
  3. If the column class returned by TableModel.getColumnClass implements Comparable, use a comparator that sorts the strings based on the values returned by Comparable.compareTo.
  4. If a string convertor has been specified for the table by invoking setStringConverter, use a comparator that sorts the resulting string representations based on the current locale.
  5. If none of the previous rules apply, use a comparator that invokes toString on the column data and sorts the resulting strings based on the current locale.

For more sophisticated kinds of sorting, subclass TableRowSorter or its parent class javax.swing.DefaultRowSorter.

To specify the sort order and sort precedence for columns, invoke setSortKeys. Here is an example that sorts the table used in the examples by the first two columns. The precedence of the columns in the sort is indicated by the order of the sort keys in the sort key list. In this case, the second column has the first sort key, so they rows are sorted by first name, then last name.

List <RowSorter.SortKey> sortKeys
    = new ArrayList<RowSorter.SortKey>();
sortKeys.add(new RowSorter.SortKey(1, SortOrder.ASCENDING));
sortKeys.add(new RowSorter.SortKey(0, SortOrder.ASCENDING));
sorter.setSortKeys(sortKeys);

In addition to reordering the results, a table sorter can also specify which rows will be displayed. This is known as filtering. TableRowSorter implements filtering using javax.swing.RowFilter objects. RowFilter implements several factory methods that create common kinds of filters. For example, regexFilter returns a RowFilter that filters based on a regular expression.

In the following example code, you explicitly create a sorter object so you can later use it to specify a filter:

MyTableModel model = new MyTableModel();
sorter = new TableRowSorter<MyTableModel>(model);
table = new JTable(model);
table.setRowSorter(sorter);

Then you filter based on the current value of a text field:

private void newFilter() {
    RowFilter<MyTableModel, Object> rf = null;
    //If current expression doesn't parse, don't update.
    try {
        rf = RowFilter.regexFilter(filterText.getText(), 0);
    } catch (java.util.regex.PatternSyntaxException e) {
        return;
    }
    sorter.setRowFilter(rf);
}

In a subsequent example, newFilter() is invoked every time the text field changes. When the user enters complicated regular expressions, the try...catch prevents the syntax exception from interfering with input.

When a table uses a sorter, the data the users sees may be in a different order than that specified by the data model, and may not include all rows specified by the data model. The data the user actually sees is known as the view, and has its own set of coordinates. JTable provides methods that convert from model coordinates to view coordinates — convertColumnIndexToView and convertRowIndexToView — and that convert from view coordinates to model coordinates — convertColumnIndexToModel and convertRowIndexToModel.

NOTE: When using a sorter, always remember to translate cell coordinates.

The following example brings together the ideas discussed in this section. TableFilterDemo.java adds a small number of changes to TableDemo. These include the code snippets earlier in this section, which provide a sorter for the main table, and use a text field to supply the filtering regular expression. The following screen shot shows TableFilterDemo before any sorting or filtering has been done. Notice that row 3 in the model is still the same as row 3 in the view:

TableFilterDemo without sorting

If the user clicks twice on the second column, the fourth row becomes the first row — but only in the view:

TableFilterDemo with reverse sorting in second column

As previously noted, the text the user enters in the "Filter Text" text field defines a filter that determines which rows are shown. As with sorting, filtering can cause view coordinates to diverge from model coordinates:

TableFilterDemo with filtering

Here is the code that updates the status field to reflect the current selection:

table.getSelectionModel().addListSelectionListener(
        new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent event) {
                int viewRow = table.getSelectedRow();
                if (viewRow < 0) {
                    //Selection got filtered away.
                    statusText.setText("");
                } else {
                    int modelRow =
                        table.convertRowIndexToModel(viewRow);
                    statusText.setText(
                        String.format("Selected Row in view: %d. " +
                            "Selected Row in model: %d.",
                            viewRow, modelRow));
                }
            }
        }
);

Using a Combo Box as an Editor

Setting up a combo box as an editor is simple, as the following example shows. The bold line of code sets up the combo box as the editor for a specific column.

TableColumn sportColumn = table.getColumnModel().getColumn(2);
...
JComboBox comboBox = new JComboBox();
comboBox.addItem("Snowboarding");
comboBox.addItem("Rowing");
comboBox.addItem("Chasing toddlers");
comboBox.addItem("Speed reading");
comboBox.addItem("Teaching high school");
comboBox.addItem("None");
sportColumn.setCellEditor(new DefaultCellEditor(comboBox));

Here is a picture of the combo box editor in use:

A combo box cell editor in use

The preceding code is from TableRenderDemo.java. You can run TableRenderDemo (click the Launch button) using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

Launches the TableRenderDemo example

Using Other Editors

Whether you are setting the editor for a single column of cells (using the TableColumn setCellEditor method) or for a specific type of data (using the JTable setDefaultEditor method), you specify the editor using an argument that adheres to the TableCellEditor interface. Fortunately, the DefaultCellEditor class implements this interface and provides constructors to let you specify an editing component that is a JTextField, JCheckBox, or JComboBox. Usually you do not have to explicitly specify a check box as an editor, since columns with Boolean data automatically use a check box renderer and editor.

What if you want to specify an editor other than a text field, check box, or combo box? As DefaultCellEditor does not support other types of components, you must do a little more work. You need to create a class that implements the TableCellEditor interface. The AbstractCellEditor class is a good superclass to use. It implements TableCellEditor's superinterface, CellEditor, saving you the trouble of implementing the event firing code necessary for cell editors.

Your cell editor class needs to define at least two methods — getCellEditorValue and getTableCellEditorComponent. The getCellEditorValue method, required by CellEditor, returns the cell's current value. The getTableCellEditorComponent method, required by TableCellEditor, should configure and return the component that you want to use as the editor.

Here is a picture of a table with a dialog that serves, indirectly, as a cell editor. When the user begins editing a cell in the Favorite Color column, a button (the true cell editor) appears and brings up the dialog, with which the user can choose a different color.

The cell editor brings up a dialog

You can run TableDialogEditDemo (click the Launch button) using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

Launches the TableDialogEditDemo example

Here is the code, taken from ColorEditor.java, that implements the cell editor.

public class ColorEditor extends AbstractCellEditor
                         implements TableCellEditor,
                                    ActionListener {
    Color currentColor;
    JButton button;
    JColorChooser colorChooser;
    JDialog dialog;
    protected static final String EDIT = "edit";

    public ColorEditor() {
        button = new JButton();
        button.setActionCommand(EDIT);
        button.addActionListener(this);
        button.setBorderPainted(false);

        //Set up the dialog that the button brings up.
        colorChooser = new JColorChooser();
        dialog = JColorChooser.createDialog(button,
                                        "Pick a Color",
                                        true,  //modal
                                        colorChooser,
                                        this,  //OK button handler
                                        null); //no CANCEL button handler
    }

    public void actionPerformed(ActionEvent e) {
        if (EDIT.equals(e.getActionCommand())) {
            //The user has clicked the cell, so
            //bring up the dialog.
            button.setBackground(currentColor);
            colorChooser.setColor(currentColor);
            dialog.setVisible(true);

            fireEditingStopped(); //Make the renderer reappear.

        } else { //User pressed dialog's "OK" button.
            currentColor = colorChooser.getColor();
        }
    }

    //Implement the one CellEditor method that AbstractCellEditor doesn't.
    public Object getCellEditorValue() {
        return currentColor;
    }

    //Implement the one method defined by TableCellEditor.
    public Component getTableCellEditorComponent(JTable table,
                                                 Object value,
                                                 boolean isSelected,
                                                 int row,
                                                 int column) {
        currentColor = (Color)value;
        return button;
    }
}

As you can see, the code is pretty simple. The only part that is a bit tricky is the call to fireEditingStopped at the end of the editor button's action handler. Without this call, the editor would remain active, even though the modal dialog is no longer visible. The call to fireEditingStopped lets the table know that it can deactivate the editor, letting the cell be handled by the renderer again.

Using an Editor to Validate User-Entered Text

If a cell's default editor allows text entry, you get some error checking for free if the cell's type is specified as something other than String or Object. The error checking is a side effect of converting the entered text into an object of the proper type.

The automatic checking of user-entered strings occurs when the default editor attempts to create a new instance of the class associated with the cell's column. The default editor creates this instance using a constructor that takes a String as an argument. For example, in a column whose cells have type Integer, when the user types in "123" the default editor creates the corresponding Integer using code equivalent to new Integer("123"). If the constructor throws an exception, the cell's outline turns red and refuses to let focus move out of the cell. If you implement a class used as a column data type, you can use the default editor if your class supplies a constructor that takes a single argument of type String.

If you like having a text field as the editor for a cell, but want to customize it — perhaps to check user-entered text more strictly or to react differently when the text is invalid — you can change the cell editor to use a formatted text field. The formatted text field can check the value either continuously while the user is typing or after the user has indicated the end of typing (such as by pressing Enter).

The following code, taken from a demo named TableFTFEditDemo.java, sets up a formatted text field as an editor that limits all integer values to be between 0 and 100. You can run TableFTFEditDemo (click the Launch button) using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

Launches the TableFTFEditDemo example

The following code makes the formatted text field the editor for all columns that contain data of type Integer.

table.setDefaultEditor(Integer.class,
                       new IntegerEditor(0, 100));

The IntegerEditor class is implemented as a subclass of DefaultCellEditor that uses a JFormattedTextField instead of the JTextField that DefaultCellEditor supports. It accomplishes this by first setting up a formatted text field to use an integer format and have the specified minimum and maximum values, using the API described in How to Use Formatted Text Fields. It then overrides the DefaultCellEditor implementation of the getTableCellEditorComponent, getCellEditorValue, and stopCellEditing methods, adding the operations that are necessary for formatted text fields.

The override of getTableCellEditorComponent sets the formatted text field's value property (and not just the text property it inherits from JTextField) before the editor is shown. The override of getCellEditorValue keeps the cell value as an Integer, rather than, say, the Long value that the formatted text field's parser tends to return. Finally, overriding stopCellEditing lets you check whether the text is valid, possibly stopping the editor from being dismissed. If the text isn't valid, your implementation of stopCellEditing puts up a dialog that gives the user the option of continuing to edit or reverting to the last good value. The source code is a bit too long to include here, but you can find it in IntegerEditor.java.

Printing

JTable provides a simple API for printing tables. The easiest way to print out a table is to invoke JTable.print with no arguments:

try {
    if (! table.print()) {
        System.err.println("User cancelled printing");
    }
} catch (java.awt.print.PrinterException e) {
    System.err.format("Cannot print %s%n", e.getMessage());
}

Invoking print on a normal Swing application brings up a standard printing dialog box. (On a headless application, the table is simply printed.) The return value indicates whether the user went ahead with the print job or cancelled it. JTable.print can throw java.awt.print.PrinterException, which is a checked exception; that's why the above example uses a try ... catch.

JTable provides several overloads of print with various options. The following code from TablePrintDemo.java shows how to define a page header:

MessageFormat header = new MessageFormat("Page {0,number,integer}");
try {
    table.print(JTable.PrintMode.FIT_WIDTH, header, null);
} catch (java.awt.print.PrinterException e) {
    System.err.format("Cannot print %s%n", e.getMessage());
}

For more sophisticated printing applications, use JTable.getPrintable to obtain a Printable object for the table. For more on Printable, refer to the Printing lesson in the 2D Graphics trail.

Examples that Use Tables

This table lists examples that use JTable and where those examples are described.

Example | Where Described | Notes
SimpleTableDemo | Creating a Simple Table | A basic table with no custom model. Does not include code to specify column widths or detect user editing.
SimpleTable-
SelectionDemo 		Detecting User Selections Adds single selection and selection detection to SimpleTableDemo. By modifying the program's ALLOW_COLUMN_SELECTION and ALLOW_ROW_SELECTION constants, you can experiment with alternatives to the table default of allowing only rows to be selected.
TableDemo | Creating a Table Model | A basic table with a custom model.
TableFTFEditDemo | Using an Editor to Validate User-Entered Text | Modifies TableDemo to use a custom editor (a formatted text field variant) for all Integer data.
TableRenderDemo | Using a Combo Box as an Editor | Modifies TableDemo to use a custom editor (a combo box) for all data in the Sport column. Also intelligently picks column sizes. Uses renderers to display tool tips for the sport cells.
TableDialogEditDemo | Using Other Editors | Modifies TableDemo to have a cell renderer and editor that display a color and let you choose a new one, using a color chooser dialog.
TableToolTipsDemo | Specifying Tool Tips for Cells, Specifying Tool Tips for Column Headers, | Demonstrates how to use several techniques to set tool tip text for cells and column headers.
TableSortDemo | Sorting and Filtering | Demonstrates the default sorter, which allows the user to sort columns by clicking on their headers.
TableFilterDemo | Sorting and Filtering | Demonstrates sorting and filtering, and how this can cause the view coordinates to diverge from the model coordinates.
TablePrintDemo | Printing | Demonstrates table printing.
ListSelectionDemo | How to Write a List Selection Listener | Shows how to use all list selection modes, using a list selection listener that's shared between a table and list.
SharedModelDemo | Nowhere | Builds on ListSelectionDemo making the data model be shared between the table and list. If you edit an item in the first column of the table, the new value is reflected in the list.
TreeTable, TreeTable II | Creating TreeTables in Swing, Creating TreeTables: Part 2 | Examples that combine a tree and table to show detailed information about a hierarchy such as a file system. The tree is a renderer for the table.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Tabbed Panes
Next page: How to Use Text Areas


How to Use Text Areas (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Text Areas
The JTextArea class provides a component that displays multiple lines of text and optionally allows the user to edit the text. If you need to obtain only one line of input from the user, you should use a text field. If you want the text area to display its text using multiple fonts or other styles, you should use an editor pane or text pane. If the displayed text has a limited length and is never edited by the user, use a label.

Many of the Tutorial's examples use uneditable text areas to display program output. Here is a picture of an example called TextDemo that enables you to type text using a text field (at the top) and then appends the typed text to a text area (underneath).

A snapshot of TextDemo

Click the Launch button to run TextDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the TextDemo application

You can find the entire code for this program in TextDemo.java. The following code creates and initializes the text area:
textArea = new JTextArea(5, 20);
jscrollPane scrollPane = new JScrollPane(textArea);
textArea.setEditable(false);
The two arguments to the JTextArea constructor are hints as to the number of rows and columns, respectively, that the text area should display. The scroll pane that contains the text area pays attention to these hints when determining how big the scroll pane should be.

Without the creation of the scroll pane, the text area would not automatically scroll. The JScrollPane constructor shown in the preceding snippet sets up the text area for viewing in a scroll pane, and specifies that the scroll pane's scroll bars should be visible when needed. See How to Use Scroll Panes if you want further information.

Text areas are editable by default. The code setEditable(false) makes the text area uneditable. It is still selectable and the user can copy data from it, but the user cannot change the text area's contents directly.

The following code adds text to the text area. Note that the text system uses the '\n' character internally to represent newlines; for details, see the API documentation for DefaultEditorKit.

private final static String newline = "\n";
...
textArea.append(text + newline);

Unless the user has moved the caret (insertion point) by clicking or dragging in the text area, the text area automatically scrolls so that the appended text is visible. You can force the text area to scroll to the bottom by moving the caret to the end of the text area after the call to append:

textArea.setCaretPosition(textArea.getDocument().getLength());

Customizing Text Areas

You can customize text areas in several ways. For example, although a given text area can display text in only one font and color, you can set which font and color it uses. This customization option can be performed on any component. You can also determine how the text area wraps lines and the number of characters per tab. Finally, you can use the methods that the JTextArea class inherits from the JTextComponent class to set properties such as the caret, support for dragging, or color selection.

The following code taken from TextSamplerDemo.java demonstrates initializing an editable text area. The text area uses the specified italic font, and wraps lines between words.

JTextArea textArea = new JTextArea(
    "This is an editable JTextArea. " +
    "A text area is a \"plain\" text component, " +
    "which means that although it can display text " +
    "in any font, all of the text is in the same font."
);
textArea.setFont(new Font("Serif", Font.ITALIC, 16));
textArea.setLineWrap(true);
textArea.setWrapStyleWord(true);

By default, a text area does not wrap lines that are too long for the display area. Instead, it uses one line for all the text between newline characters and — if the text area is within a scroll pane — allows itself to be scrolled horizontally. This example turns line wrapping on with a call to the setLineWrap method and then calls the setWrapStyleWord method to indicate that the text area should wrap lines at word boundaries rather than at character boundaries.

To provide scrolling capability, the example puts the text area in a scroll pane.

JScrollPane areaScrollPane = new JScrollPane(textArea);
areaScrollPane.setVerticalScrollBarPolicy(
        JScrollPane.VERTICAL_SCROLLBAR_ALWAYS);
areaScrollPane.setPreferredSize(new Dimension(250, 250));
You might have noticed that the JTextArea constructor used in this example does not specify the number of rows or columns. Instead, the code limits the size of the text area by setting the scroll pane's preferred size.

Another Example: TextAreaDemo

The TextAreaDemo example introduces an editable text area with a special feature — a word completion function. As the user types in words, the program suggests hints to complete the word whenever the program's vocabulary contains a word that starts with what has been typed. Here is a picture of the TextAreaDemo application.

A snapshot of TextAreaDemo

Click the Launch button to run TextAreaDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the TextAreaDemo Application

You can find the entire code for this program in TextAreaDemo.java.

This example provides a scrolling capacity for the text area with the default scroll bar policy. By default, the vertical scroll bar only appears when the display area is entirely filled with text and there is no room to append new words. You can provide a scroll pane of this type with the following code:

  textArea.setWrapStyleWord(true);
  jScrollPane1 = new JScrollPane(textArea);
As mentioned above, the text area is editable. You can play with the text area by typing and pasting text, or by deleting some parts of text or the entire content. Also try using standard key bindings for editing text within the text area.

Now explore how the word completion function is implemented. Type in a word like "Swing" or "special". As soon as you have typed "sw" the program shows a possible completion "ing" highlighted in light-blue. Press Enter to accept the completion or continue typing.

The following code adds a document listener to the text area's document:

  textArea.getDocument().addDocumentListener(this);
When you started typing a word, the insertUpdate method checks whether the program's vocabulary contains the typed prefix. Once a completion for the prefix is found, a call to the invokeLater method submits a task for changing the document later. It is important to remember that you cannot modify the document from within the document event notification, otherwise you will get an exception. Examine the following code below.
  String prefix = content.substring(w + 1).toLowerCase();
  int n = Collections.binarySearch(words, prefix);
  if (n < 0 && -n <= words.size())="words.size())" {="{" String="String" match="words.get(-n" -="-" 1);="1);" if="if" (match.startsWith(prefix))="(match.startsWith(prefix))" {="{" //="//" A="A" completion="completion" is="is" found="found" String="String" completion="match.substring(pos" -="-" w);="w);" //="//" We="We" cannot="cannot" modify="modify" Document="Document" from="from" within="within" notification,="notification," //="//" so="so" we="we" submit="submit" a="a" task="task" that="that" does="does" the="the" change="change" later="later" SwingUtilities.invokeLater(="SwingUtilities.invokeLater(" new="new" CompletionTask(completion,="CompletionTask(completion," pos="pos" +="+" 1));="1));" }="}" }="}" else="else" {="{" //="//" Nothing="Nothing" found="found" mode="Mode.INSERT;" }="}"
The code shown in bold illustrates how the selection is created. The caret is first set to the end of the complete word, then moved back to a position after the last character typed. The moveCaretPosition method not only moves the caret to a new position but also selects the text between the two positions. The completion task is implemented with the following code:
  private class CompletionTask implements Runnable {
        String completion;
        int position;

        CompletionTask(String completion, int position) {
            this.completion = completion;
            this.position = position;
        }

        public void run() {
            textArea.insert(completion, position);
            textArea.setCaretPosition(position + completion.length());
            textArea.moveCaretPosition(position);
            mode = Mode.COMPLETION;
        }
    }

The Text Area API

The following tables list the commonly used JTextArea constructors and methods. Other methods you are likely to call are defined in JTextComponent, and listed in The Text Component API.

You might also invoke methods on a text area that it inherits from its other ancestors, such as setPreferredSize, setForeground, setBackground, setFont, and so on. See The JComponent Class for tables of commonly used inherited methods.

The API for using text areas includes the following categories:

  • Setting or Obtaining Contents
  • Fine Tuning Appearance
  • Implementing Functionality

Setting or Obtaining Contents
Method or Constructor Purpose
JTextArea()
JTextArea(String)
JTextArea(String, int, int)
JTextArea(int, int) 		Creates a text area. When present, the String argument contains the initial text. The int arguments specify the desired width in columns and height in rows, respectively.
void setText(String)
String getText()
(defined in JTextComponent) 		Sets or obtains the text displayed by the text area.

Fine Tuning the Text Area's Appearance
Method | Purpose
void setEditable(boolean)
boolean isEditable()
(defined in JTextComponent) 		Sets or indicates whether the user can edit the text in the text area.
void setColumns(int);
int getColumns() 		Sets or obtains the number of columns displayed by the text area. This is really just a hint for computing the area's preferred width.
void setRows(int);
int getRows() 		Sets or obtains the number of rows displayed by the text area. This is a hint for computing the area's preferred height.
int setTabSize(int) | Sets the number of characters a tab is equivalent to.
int setLineWrap(boolean) | Sets whether lines are wrapped if they are too long to fit within the allocated width. By default this property is false and lines are not wrapped.
int setWrapStyleWord(boolean) | Sets whether lines can be wrapped at white space (word boundaries) or at any character. By default this property is false, and lines can be wrapped (if line wrapping is turned on) at any character.

Implementing the Text Area's Functionality
Method | Purpose
void selectAll()
(defined in JTextComponent) 		Selects all characters in the text area.
void append(String) | Adds the specified text to the end of the text area.
void insert(String, int) | Inserts the specified text at the specified position.
void replaceRange(String, int, int) | Replaces the text between the indicated positions with the specified string.
int getLineCount()
int getLineOfOffset(int)
int getLineStartOffset(int)
int getLineEndOffset(int) 		Utilities for finding a line number or the position of the beginning or end of the specified line.

Examples That Use Text Areas

This table lists examples that use text areas and points to where those examples are described.

Example | Where Described | Notes
TextDemo | This section | An application that appends user-entered text to a text area.
TextAreaDemo | This section | An application that has a text area with a word completion function.
TextSamplerDemo | Using Text Components | Uses one of each Swing text components.
HtmlDemo | How to Use HTML in Swing Components | A text area that enables the user to type HTML code to be displayed in a label.
BasicDnD | Introduction to DnD | Demonstrates built-in drag-and-drop functionality of several Swing components, including text areas.
ExtendedDnDDemo | Introduction to DnD | Demonstrates dragging and dropping text between a text area, a list, and a table.
DragFileDemo | Introduction to DnD | Demonstrates dragging file contents from a file chooser into a text area. A tabbed pane lets you easily switch between files.
FocusConceptsDemo | How to Use the Focus Subsystem | Demonstrates how focus works using a few components that include a text area.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Tables
Next page: How to Use Text Fields


How to Use Text Fields (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Text Fields
A text field is a basic text control that enables the user to type a small amount of text. When the user indicates that text entry is complete (usually by pressing Enter), the text field fires an action event. If you need to obtain more than one line of input from the user, use a text area.

The Swing API provides several classes for components that are either varieties of text fields or that include text fields.

JTextField | What this section covers: basic text fields.
JFormattedTextField | A JTextField subclass that allows you to specify the legal set of characters that the user can enter. See How to Use Formatted Text Fields.
JPasswordField | A JTextField subclass that does not show the characters that the user types. See How to Use Password Fields.
JComboBox | Can be edited, and provides a menu of strings to choose from. See How to Use Combo Boxes.
JSpinner | Combines a formatted text field with a couple of small buttons that enables the user to choose the previous or next available value. See How to Use Spinners.

The following example displays a basic text field and a text area. The text field is editable. The text area is not editable. When the user presses Enter in the text field, the program copies the text field's contents to the text area, and then selects all the text in the text field.

A snapshot of TextDemo

Click the Launch button to run TextDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the TextDemo application

You can find the entire code for this program in TextDemo.java. The following code creates and sets up the text field:
textField = new JTextField(20);
The integer argument passed to the JTextField constructor, 20 in the example, indicates the number of columns in the field. This number is used along with metrics provided by the field's current font to calculate the field's preferred width. It does not limit the number of characters the user can enter. To do that, you can either use a formatted text field or a document listener, as described in Text Component Features.
Note: We encourage you to specify the number of columns for each text field. If you do not specify the number of columns or a preferred size, then the field's preferred size changes whenever the text changes, which can result in unwanted layout updates.

The next line of code registers a TextDemo object as an action listener for the text field.

textField.addActionListener(this);
The actionPerformed method handles action events from the text field:
private final static String newline = "\n";
...
public void actionPerformed(ActionEvent evt) {
    String text = textField.getText();
    textArea.append(text + newline);
    textField.selectAll();
}
Notice the use of JTextField's getText method to retrieve the text currently contained by the text field. The text returned by this method does not include a newline character for the Enter key that fired the action event.

You have seen how a basic text field can be used. Because the JTextField class inherits from the JTextComponent class, text fields are very flexible and can be customized almost any way you like. For example, you can add a document listener or a document filter to be notified when the text changes, and in the filter case you can modify the text field accordingly. Information on text components can be found in Text Component Features. Before customizing a JTextField, however, make sure that one of the other components based on text fields will not do the job for you.

Often text fields are paired with labels that describe the text fields. See Examples That Use Text Fields for pointers on creating these pairs.

Another Example: TextFieldDemo

The TextFieldDemo example introduces a text field and a text area. You can find the entire code for this program in TextFieldDemo.java.

As you type characters in the text field the program searches for the typed text in the text area. If the entry is found it gets highlighted. If the program fails to find the entry then the text field's background becomes pink. A status bar below the text area displays a message whether text is found or not. The Escape key is used to start a new search or to finish the current one. Here is a picture of the TextFieldDemo application.

A snapshot of TextFieldDemo

Click the Launch button ro run TextFieldDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the TextFieldDemo Application

To highlight text, this example uses a highlighter and a painter. The code below creates and sets up the highlighter and the painter for the text area.
final Highlighter hilit;
final Highlighter.HighlightPainter painter;
...
hilit = new DefaultHighlighter();
painter = new DefaultHighlighter.DefaultHighlightPainter(HILIT_COLOR);
textArea.setHighlighter(hilit);
This code adds a document listener to the text field's document.
entry.getDocument().addDocumentListener(this);
Document listener's insertUpdate and removeUpdate methods call the search method, which not only performs a search in the text area but also handles highlighting. The following code highlights the found text, sets the caret to the end of the found match, sets the default background for the text field, and displays a message in the status bar.
hilit.addHighlight(index, end, painter);
textArea.setCaretPosition(end);
entry.setBackground(entryBg);
message("'" + s + "' found. Press ESC to end search");
The status bar is a JLabel object. The code below shows how the message method is implemented.
private JLabel status;
...
void message(String msg) {
    status.setText(msg);
}
If there is no match in the text area, the following code changes the text field's background to pink and displays a proper information message.
entry.setBackground(ERROR_COLOR);
message("'" + s + "' not found. Press ESC to start a new search");
The CancelAction class is responsible for handling the Escape key as follows.
   class CancelAction extends AbstractAction {
       public void actionPerformed(ActionEvent ev) {
               hilit.removeAllHighlights();
               entry.setText("");
               entry.setBackground(entryBg);
           }
   }

The Text Field API

The following tables list the commonly used JTextField constructors and methods. Other methods you are likely to call are defined in the JTextComponent class. Refer to The Text Component API.

You might also invoke methods on a text field inherited from the text field's other ancestors, such as setPreferredSize, setForeground, setBackground, setFont, and so on. See The JComponent Class for tables of commonly used inherited methods.

The API for using text fields falls into these categories:

  • Setting or Obtaining the Field's Contents
  • Fine Tuning the Field's Appearance
  • Implementing the Field's Functionality

Setting or Obtaining the Field's Contents
Method or Constructor Purpose
JTextField()
JTextField(String)
JTextField(String, int)
JTextField(int) 		Creates a text field. When present, the int argument specifies the desired width in columns. The String argument contains the field's initial text.
void setText(String)
String getText()
(defined in JTextComponent) 		Sets or obtains the text displayed by the text field.

Fine Tuning the Field's Appearance
Method Purpose
void setEditable(boolean)
boolean isEditable()
(defined in JTextComponent) 		Sets or indicates whether the user can edit the text in the text field.
void setColumns(int);
int getColumns() 		Sets or obtains the number of columns displayed by the text field. This is really just a hint for computing the field's preferred width.
void setHorizontalAlignment(int);
int getHorizontalAlignment() 		Sets or obtains how the text is aligned horizontally within its area. You can use JTextField.LEADING, JTextField.CENTER, and JTextField.TRAILING for arguments.

Implementing the Field's Functionality
Method Purpose
void addActionListener(ActionListener)
void removeActionListener(ActionListener) 		Adds or removes an action listener.
void selectAll()
(defined in JTextComponent) 		Selects all characters in the text field.

Examples That Use Text Fields

This table shows a few of the examples that use text fields and points to where those examples are described. For examples of code that are similar among all varieties of text fields such as dealing with layout, look at the example lists for related components such as formatted text fields and spinners.

Example | Where Described | Notes
TextDemo | This section | An application that uses a basic text field with an action listener.
TextFieldDemo | This section | An application that uses a text field and a text area. A search is made in the text area to find an entry from the text field.
DialogDemo | How to Make Dialogs | CustomDialog.java includes a text field whose value is checked. You can bring up the dialog by clicking the More Dialogs tab, selecting the Input-validating dialog option, and then clicking the Show it! button.
TextSamplerDemo Using Text Components Lays out label-text field pairs using a GridBagLayout and a convenience method:
addLabelTextRows(JLabel[] labels,
         JTextField[] textFields,
         GridBagLayout gridbag,
         Container container)
TextInputDemo How to Use Formatted Text Fields Lays out label-text field pairs using a SpringLayout and a SpringUtilities convenience method:
makeCompactGrid(Container parent,
                int rows, int cols,
                int initialX, int initialY,
                int xPad, int yPad)

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Text Areas
Next page: How to Use Tool Bars


How to Use Tool Bars (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Tool Bars
A JToolBar is a container that groups several components — usually buttons with icons — into a row or column. Often, tool bars provide easy access to functionality that is also in menus. How to Use Actions describes how to provide the same functionality in menu items and tool bar buttons.

The following images show an application named ToolBarDemo that contains a tool bar above a text area. Click the Launch button to run ToolBarDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run it yourself, consult the example index.

Launches the ToolBarDemo Application

ToolBarDemo, with the tool bar in an initial north position

By default, the user can drag the tool bar to another edge of its container or out into a window of its own. The next figure shows how the application looks after the user has dragged the tool bar to the right edge of its container.

ToolBarDemo, after the tool bar is dragged to the east

For the drag behavior to work correctly, the tool bar must be in a container that uses the BorderLayout layout manager. The component that the tool bar affects is generally in the center of the container. The tool bar must be the only other component in the container, and it must not be in the center.

The next figure shows how the application looks after the user has dragged the tool bar outside its window.

ToolBarDemo, after the tool bar is dragged out into its own window

The following code creates the tool bar and adds it to a container. You can find the entire program in ToolBarDemo.java.

public class ToolBarDemo extends JPanel
                         implements ActionListener {
    ...
    public ToolBarDemo() {
        super(new BorderLayout());
        ...
        JToolBar toolBar = new JToolBar("Still draggable");
        addButtons(toolBar);
        ...
        setPreferredSize(new Dimension(450, 130));
        add(toolBar, BorderLayout.PAGE_START);
        add(scrollPane, BorderLayout.CENTER);
    }
    ...
}
This code positions the tool bar above the scroll pane by placing both components in a panel controlled by a border layout, with the tool bar in the PAGE_START position and the scroll pane in the CENTER position. Because the scroll pane is in the center and no other components except the tool bar are in the container, by default the tool bar can be dragged to other edges of the container. The tool bar can also be dragged out into its own window, in which case the window has the title "Still draggable", as specified by the JToolBar constructor.

Creating Tool Bar Buttons

The buttons in the tool bar are ordinary JButton instances that use images from the Java Look and Feel Graphics Repository. Use images from the Java Look and Feel Graphics Repository if your tool bar has the Java look and feel.

Here is the code that creates the buttons and adds them to the tool bar.

protected void addButtons(JToolBar toolBar) {
    JButton button = null;

    //first button
    button = makeNavigationButton("Back24", PREVIOUS,
                                  "Back to previous something-or-other",
                                  "Previous");
    toolBar.add(button);

    //second button
    button = makeNavigationButton("Up24", UP,
                                  "Up to something-or-other",
                                  "Up");
    toolBar.add(button);

    ...//similar code for creating and adding the third button...
}

protected JButton makeNavigationButton(String imageName,
                                       String actionCommand,
                                       String toolTipText,
                                       String altText) {
    //Look for the image.
    String imgLocation = "images/"
                         + imageName
                         + ".gif";
    URL imageURL = ToolBarDemo.class.getResource(imgLocation);

    //Create and initialize the button.
    JButton button = new JButton();
    button.setActionCommand(actionCommand);
    button.setToolTipText(toolTipText);
    button.addActionListener(this);

    if (imageURL != null) {                      //image found
        button.setIcon(new ImageIcon(imageURL, altText));
    } else {                                     //no image found
        button.setText(altText);
        System.err.println("Resource not found: " + imgLocation);
    }

    return button;
}
The first call to makeNavigationButton creates the image for the first button, using the 24x24 "Back" navigation image in the graphics repository.

Besides finding the image for the button, the makeNavigationButton method also creates the button, sets the strings for its action command and tool tip text, and adds the action listener for the button. If the image is missing, the method prints an error message and adds text to the button, so that the button is still usable.

Note: If any buttons in your tool bar duplicate the functionality of other components, such as menu items, you should probably create and add the tool bar buttons as described in How to Use Actions.

Customizing Tool Bars

By adding a few lines of code to the preceding example, we can demonstrate some more tool bar features:

  • Using setFloatable(false) to make a tool bar immovable.
  • Using setRollover(true) to visually indicate tool bar buttons when the user passes over them with the cursor.
  • Adding a separator to a tool bar.
  • Adding a non-button component to a tool bar.
You can see these features by running ToolBarDemo2. Click the Launch button to run ToolBarDemo2 using Java™ Web Start (download JDK 6). Alternatively, to compile and run it yourself, consult the example index.

Launches the ToolBarDemo2 Application

You can find the entire code for this program in ToolBarDemo2.java. Below you can see a picture of a new UI using these customized features.

ToolBarDemo2 shows a tool bar with a variety of components

Because the tool bar can no longer be dragged, it no longer has bumps at its left edge. Here is the code that turns off dragging:

toolBar.setFloatable(false);

The tool bar is in rollover mode, so the button under the cursor has a visual indicator. The kind of visual indicator depends on the look and feel. For example, the Metal look and feel uses a gradient effect to indicate the button under the cursor while other types of look and feel use borders for this purpose. Here is the code that sets rollover mode:

toolBar.setRollover(true);

Another visible difference in the example above is that the tool bar contains two new components, which are preceded by a blank space called a separator. Here is the code that adds the separator:

toolBar.addSeparator();
Here is the code that adds the new components:
//fourth button
button = new JButton("Another button");
...
toolBar.add(button);

//fifth component is NOT a button!
JTextField textField = new JTextField("A text field");
...
toolBar.add(textField);
You can easily make the tool bar components either top-aligned or bottom-aligned instead of centered by invoking the setAlignmentY method. For example, to align the tops of all the components in a tool bar, invoke setAlignmentY(TOP_ALIGNMENT) on each component. Similarly, you can use the setAlignmentX method to specify the alignment of components when the tool bar is vertical. This layout flexibility is possible because tool bars use BoxLayout to position their components. For more information, see How to Use BoxLayout.

The Tool Bar API

The following table lists the commonly used JToolBar constructors and methods. Other methods you might call are listed in the API tables in The JComponent Class.

Method or Constructor | Purpose
JToolBar()
JToolBar(int)
JToolBar(String)
JToolBar(String, int) 		Creates a tool bar. The optional int parameter lets you specify the orientation; the default is HORIZONTAL. The optional String parameter allows you to specify the title of the tool bar's window if it is dragged outside of its container.
Component add(Component) Adds a component to the tool bar.

You can associate a button with an Action using the setAction(Action) method defined by the AbstractButton.

void addSeparator() | Adds a separator to the end of the tool bar.
void setFloatable(boolean)
boolean isFloatable() 		The floatable property is true by default, and indicates that the user can drag the tool bar out into a separate window. To turn off tool bar dragging, use toolBar.setFloatable(false). Some types of look and feel might ignore this property.
void setRollover(boolean)
boolean isRollover() 		The rollover property is false by default. To make tool bar buttons be indicated visually when the user passes over them with the cursor, set this property to true. Some types of look and feel might ignore this property.

Examples That Use Tool Bars

This table lists examples that use JToolBar and points to where those examples are described.

Example | Where Described | Notes
ToolBarDemo | This page | A basic tool bar with icon-only buttons.
ToolBarDemo2 | This page | Demonstrates a non-floatable tool bar in rollover mode that contains a separator and a non-button component.
ActionDemo | How to Use Actions | Implements a tool bar using Action objects.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Text Fields
Next page: How to Use Tool Tips


How to Use Tool Tips (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Tool Tips
Creating a tool tip for any JComponent object is easy. Use the setToolTipText method to set up a tool tip for the component. For example, to add tool tips to three buttons, you add only three lines of code:
b1.setToolTipText("Click this button to disable the middle button.");
b2.setToolTipText("This middle button does not react when you click it.");
b3.setToolTipText("Click this button to enable the middle button.");
When the user of the program pauses with the cursor over any of the program's buttons, the tool tip for the button comes up. You can see this by running the ButtonDemo example, which is explained in How to Use Buttons, Check Boxes, and Radio Buttons. Here is a picture of the tool tip that appears when the cursor pauses over the left button in the ButtonDemo example.

ButtonDemo showing a tool tip.

For components such as tabbed panes that have multiple parts, it often makes sense to vary the tool tip text to reflect the part of the component under the cursor. For example, a tabbed pane might use this feature to explain what will happen when you click the tab under the cursor. When you implement a tabbed pane, you can specify the tab-specific tool tip text in an argument passed to the addTab or setToolTipTextAt method.

Even in components that have no API for setting part-specific tool tip text, you can generally do the job yourself. If the component supports renderers, then you can set the tool tip text on a custom renderer. The table and tree sections provide examples of tool tip text determined by a custom renderer. An alternative that works for all JComponents is creating a subclass of the component and overriding its getToolTipText(MouseEvent) method.

The Tool Tip API

Most of the API you need in order to set up tool tips belongs to the JComponent class, and thus is inherited by most Swing components. More tool tip API can be found in individual classes such as JTabbedPane. In general, those APIs are sufficient for specifying and displaying tool tips; you usually do not need to deal directly with the implementing classes JToolTip and ToolTipManager.

The following table lists the tool tip API in the JComponent class. For information on individual components' support for tool tips, see the how-to section for the component in question.

Tool Tip API in the JComponent class
Method | Purpose
setToolTipText(String) | If the specified string is not null, then this method registers the component as having a tool tip and, when displayed, gives the tool tip the specified text. If the argument is null, then this method turns off the tool tip for this component.
String getToolTipText() | Returns the string that was previously specified with setToolTipText.
String getToolTipText(MouseEvent) | By default, returns the same value returned by getToolTipText(). Multi-part components such as JTabbedPane, JTable, and JTree override this method to return a string associated with the mouse event location. For example, each tab in a tabbed pane can have different tool tip text.
Point getToolTipLocation(MouseEvent) | Returns the location (in the receiving component's coordinate system) where the upper left corner of the component's tool tip appears. The argument is the event that caused the tool tip to be shown. The default return value is null, which tells the Swing system to choose a location.

Examples That Use Tool Tips

This table lists some examples that use tool tips and points to where those examples are described.

Example | Where Described | Notes
ButtonDemo | This section and How to Use Buttons, Check Boxes, and Radio Buttons | Uses a tool tip to provide instructions for a button.
IconDemo | How to Use Icons | Uses a tool tip in a label to provide name and size information for an image.
TabbedPaneDemo | How to Use Tabbed Panes | Uses tab-specific tool tip text specified in an argument to the addTab method.
TableRenderDemo | Specifying Tool Tips for Cells | Adds tool tips to a table using a renderer.
TableToolTipsDemo | Specifying Tool Tips for Cells, Specifying Tool Tips for Column Headers | Adds tool tips to a table using various techniques.
TreeIconDemo2 | Customizing a Tree's Display | Adds tool tips to a tree using a custom renderer.
ActionDemo | How to Use Actions | Adds tool tips to buttons that have been created using Actions.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Tool Bars
Next page: How to Use Trees


How to Use Trees (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Section: How to Use Various Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Trees
With the JTree class, you can display hierarchical data. A JTree object does not actually contain your data; it simply provides a view of the data. Like any non-trivial Swing component, the tree gets data by querying its data model. Here is a picture of a tree:

As the preceding figure shows, JTree displays its data vertically. Each row displayed by the tree contains exactly one item of data, which is called a node. Every tree has a root node from which all nodes descend. By default, the tree displays the root node, but you can decree otherwise. A node can either have children or not. We refer to nodes that can have children — whether or not they currently have children — as branch nodes. Nodes that can not have children are leaf nodes.

Branch nodes can have any number of children. Typically, the user can expand and collapse branch nodes — making their children visible or invisible — by clicking them. By default, all branch nodes except the root node start out collapsed. A program can detect changes in branch nodes' expansion state by listening for tree expansion or tree-will-expand events, as described in How to Write a Tree Expansion Listener and How to Write a Tree-Will-Expand Listener.

A specific node in a tree can be identified either by a TreePath, an object that encapsulates a node and all of its ancestors, or by its display row, where each row in the display area displays one node.

  • An expanded node is a non-leaf node that will display its children when all its ancestors are expanded.
  • A collapsed node is one which hides them.
  • A hidden node is one which is under a collapsed ancestor.

The rest of this section discusses the following topics:

  • Creating a Tree
  • Responding to Node Selection
  • Customizing a Tree's Display
  • Dynamically Changing a Tree
  • Creating a Data Model
  • The Tree API
  • Examples that Use Trees

Creating a Tree

Here is a picture of an application, the top half of which displays a tree in a scroll pane.

Try this::
  1. Click the Launch button to run the Tree Demo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TreeDemo example

  2. Expand one or more nodes.
    You can do this by clicking the circle to the left of the item.
  3. Collapse a node.
    You do this by clicking the circle to the left of an expanded node.

The following code, taken from TreeDemo.java, creates the JTree object and puts it in a scroll pane:

//Where instance variables are declared:
private JTree tree;
...
public TreeDemo() {
    ...
    DefaultMutableTreeNode top =
        new DefaultMutableTreeNode("The Java Series");
    createNodes(top);
    tree = new JTree(top);
    ...
    JScrollPane treeView = new JScrollPane(tree);
    ...
}
The code creates an instance of DefaultMutableTreeNode to serve as the root node for the tree. It then creates the rest of the nodes in the tree. After that, it creates the tree, specifying the root node as an argument to the JTree constructor. Finally, it puts the tree in a scroll pane, a common tactic because showing the full, expanded tree would otherwise require too much space.

Here is the code that creates the nodes under the root node:

private void createNodes(DefaultMutableTreeNode top) {
    DefaultMutableTreeNode category = null;
    DefaultMutableTreeNode book = null;

    category = new DefaultMutableTreeNode("Books for Java Programmers");
    top.add(category);

    //original Tutorial
    book = new DefaultMutableTreeNode(new BookInfo
        ("The Java Tutorial: A Short Course on the Basics",
        "tutorial.html"));
    category.add(book);

    //Tutorial Continued
    book = new DefaultMutableTreeNode(new BookInfo
        ("The Java Tutorial Continued: The Rest of the JDK",
        "tutorialcont.html"));
    category.add(book);

    //JFC Swing Tutorial
    book = new DefaultMutableTreeNode(new BookInfo
        ("The JFC Swing Tutorial: A Guide to Constructing GUIs",
        "swingtutorial.html"));
    category.add(book);

    //...add more books for programmers...

    category = new DefaultMutableTreeNode("Books for Java Implementers");
    top.add(category);

    //VM
    book = new DefaultMutableTreeNode(new BookInfo
        ("The Java Virtual Machine Specification",
         "vm.html"));
    category.add(book);

    //Language Spec
    book = new DefaultMutableTreeNode(new BookInfo
        ("The Java Language Specification",
         "jls.html"));
    category.add(book);
}

The argument to the DefaultMutableTreeNode constructor is the user object which is an object that contains or points to the data associated with the tree node. The user object can be a string, or it can be a custom object. If you implement a custom object, you should implement its toString method so that it returns the string to be displayed for that node. JTree, by default, renders each node using the value returned from toString, so it is important that toString returns something meaningful. Sometimes, it is not feasible to override toString; in such a scenario you can override the convertValueToText of JTree to map the object from the model into a string that gets displayed.

For example, the BookInfo class used in the previous code snippet is a custom class that holds two pieces of data: the name of a book, and the URL for an HTML file describing the book. The toString method is implemented to return the book name. Thus, each node associated with a BookInfo object displays a book name.

Note: You can specify text formatting in a tree node by putting HTML tags in the string for the node. See Using HTML in Swing Components for details.

To summarize, you can create a tree by invoking the JTree constructor, specifying the class that implements TreeNode as an argument. You should probably put the tree inside a scroll pane, so that the tree would not take up too much space. You do not have to do anything to make the tree nodes expand and collapse in response to user clicks. However, you do have to add some code to make the tree respond when the user selects a node — by clicking the node, for example.

Responding to Node Selection

Responding to tree node selections is simple. You implement a tree selection listener and register it on the tree. The following code shows the selection-related code from the TreeDemo program:
//Where the tree is initialized:
    tree.getSelectionModel().setSelectionMode
            (TreeSelectionModel.SINGLE_TREE_SELECTION);

    //Listen for when the selection changes.
    tree.addTreeSelectionListener(this);
...
public void valueChanged(TreeSelectionEvent e) {
//Returns the last path element of the selection.
//This method is useful only when the selection model allows a single selection.
    DefaultMutableTreeNode node = (DefaultMutableTreeNode)
                       tree.getLastSelectedPathComponent();

    if (node == null)
    //Nothing is selected.
    return;

    Object nodeInfo = node.getUserObject();
    if (node.isLeaf()) {
        BookInfo book = (BookInfo)nodeInfo;
        displayURL(book.bookURL);
    } else {
        displayURL(helpURL);
    }
}
The preceding code performs these tasks:
  • Gets the default TreeSelectionModel for the tree, and then sets it up so that at most one tree node at a time can be selected.
  • Registers an event handler on the tree. The event handler is an object that implements the TreeSelectionListener interface.
  • In the event handler, determines which node is selected by invoking the tree's getLastSelectedPathComponent method.
  • Uses the getUserObject method to get the data associated with the node.
For more details about handling tree selection events, see How to Write a Tree Selection Listener.

Customizing a Tree's Display

Here is a picture of some tree nodes, as drawn by the Java, Windows, and Mac OS look and feel implementations.

TreeDemo with angled lines | A tree in the Windows look and feel | A tree in the MacOS look and feel
Java look and feel | Windows look and feel | Mac OS look and feel

As the preceding figures show, a tree conventionally displays an icon and some text for each node. You can customize these, as we will show shortly.

A tree typically also performs some look-and-feel-specific painting to indicate relationships between nodes. You can customize this painting in a limited way. First, you can use tree.setRootVisible(true) to show the root node or tree.setRootVisible(false) to hide it. Second, you can use tree.setShowsRootHandles(true) to request that a tree's top-level nodes — the root node (if it is visible) or its children (if not) — have handles that let them be expanded or collapsed.

If you are using the Java look and feel, you can customize whether lines are drawn to show relationships between tree nodes. By default, the Java look and feel draws angled lines between nodes. By setting the JTree.lineStyle client property of a tree, you can specify a different convention. For example, to request that the Java look and feel use only horizontal lines to group nodes, use the following code:

tree.putClientProperty("JTree.lineStyle", "Horizontal");

To specify that the Java look and feel should draw no lines, use this code:

tree.putClientProperty("JTree.lineStyle", "None");
The following snapshots show the results of setting the JTree.lineStyle property, when using the Java look and feel.

TreeDemo with angled lines

TreeDemo with horizontal lines

TreeDemo with no lines

"Angled" (default) "Horizontal" "None"

No matter what the look and feel, the default icon displayed by a node is determined by whether the node is a leaf and, if not, whether it is expanded. For example, in the Windows and Motif look and feel implementations, the default icon for each leaf node is a dot; in the Java look and feel, the default leaf icon is a paper-like symbol. In all the look-and-feel implementations we have shown, branch nodes are marked with folder-like symbols. Some look and feels might have different icons for expanded branches versus collapsed branches.

You can easily change the default icon used for leaf, expanded branch, or collapsed branch nodes. To do so, you first create an instance of DefaultTreeCellRenderer. You could always create your own TreeCellRenderer implementation from scratch, reusing whatever components you like. Next, specify the icons to use by invoking one or more of the following methods on the renderer: setLeafIcon (for leaf nodes), setOpenIcon (for expanded branch nodes), setClosedIcon (for collapsed branch nodes). If you want the tree to display no icon for a type of node, then specify null for the icon. Once you have set up the icons, use the tree's setCellRenderer method to specify that the DefaultTreeCellRenderer paint its nodes. Here is an example, taken from TreeIconDemo.java:

ImageIcon leafIcon = createImageIcon("images/middle.gif");
if (leafIcon != null) {
    DefaultTreeCellRenderer renderer =
    new DefaultTreeCellRenderer();
    renderer.setLeafIcon(leafIcon);
    tree.setCellRenderer(renderer);
}
Here is the screenshot of TreeIconDemo:

Try this::
  1. Click the Launch button to run the TreeIconDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TreeIconDemo example

If you want finer control over the node icons or you want to provide tool tips, you can do so by creating a subclass of DefaultTreeCellRenderer and overriding the getTreeCellRendererComponent method. Because DefaultTreeCellRenderer is a subclass of JLabel, you can use any JLabel method — such as setIcon — to customize the DefaultTreeCellRenderer.

The following code, from TreeIconDemo2.java, creates a cell renderer that varies the leaf icon depending on whether the word "Tutorial" is in the node's text data. The renderer also specifies tool-tip text, as the bold lines show.

Try this::
  1. Click the Launch button to run the TreeIconDemo2 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TreeDemo example

//...where the tree is initialized:
    //Enable tool tips.
    ToolTipManager.sharedInstance().registerComponent(tree);

    ImageIcon tutorialIcon = createImageIcon("images/middle.gif");
    if (tutorialIcon != null) {
        tree.setCellRenderer(new MyRenderer(tutorialIcon));
    }
...
class MyRenderer extends DefaultTreeCellRenderer {
    Icon tutorialIcon;

    public MyRenderer(Icon icon) {
        tutorialIcon = icon;
    }

    public Component getTreeCellRendererComponent(
                        JTree tree,
                        Object value,
                        boolean sel,
                        boolean expanded,
                        boolean leaf,
                        int row,
                        boolean hasFocus) {

        super.getTreeCellRendererComponent(
                        tree, value, sel,
                        expanded, leaf, row,
                        hasFocus);
        if (leaf && isTutorialBook(value)) {
            setIcon(tutorialIcon);
            setToolTipText("This book is in the Tutorial series.");
        } else {
            setToolTipText(null); //no tool tip
        }

        return this;
    }

    protected boolean isTutorialBook(Object value) {
        DefaultMutableTreeNode node =
                (DefaultMutableTreeNode)value;
        BookInfo nodeInfo =
                (BookInfo)(node.getUserObject());
        String title = nodeInfo.bookName;
        if (title.indexOf("Tutorial") >= 0) {
            return true;
        }

        return false;
    }
}
Here is the result:

You might be wondering how a cell renderer works. When a tree paints each node, neither the JTree nor its look-and-feel-specific implementation actually contains the code that paints the node. Instead, the tree uses the cell renderer's painting code to paint the node. For example, to paint a leaf node that has the string "The Java Programming Language", the tree asks its cell renderer to return a component that can paint a leaf node with that string. If the cell renderer is a DefaultTreeCellRenderer, then it returns a label that paints the default leaf icon followed by the string.

A cell renderer only paints; it cannot handle events. If you want to add event handling to a tree, you need to register your handler on either the tree or, if the handling occurs only when a node is selected, the tree's cell editor. For information about cell editors, see Concepts: Editors and Renderers. That section discusses table cell editors and renderers, which are similar to tree cell editors and renderers.

Dynamically Changing a Tree

The following figure shows an application called DynamicTreeDemo that lets you add nodes to and remove nodes from a visible tree. You can also edit the text in each node.

The application is based on an example provided by tutorial reader Richard Stanford.

Try this::
  1. Click the Launch button to run the DynamicTreeDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TreeDemo example

Here is the code that initializes the tree:
rootNode = new DefaultMutableTreeNode("Root Node");
treeModel = new DefaultTreeModel(rootNode);
treeModel.addTreeModelListener(new MyTreeModelListener());

tree = new JTree(treeModel);
tree.setEditable(true);
tree.getSelectionModel().setSelectionMode
        (TreeSelectionModel.SINGLE_TREE_SELECTION);
tree.setShowsRootHandles(true);
By explicitly creating the tree's model, the code guarantees that the tree's model is an instance of DefaultTreeModel. That way, we know all the methods that the tree model supports. For example, we know that we can invoke the model's insertNodeInto method, even though that method is not required by the TreeModel interface.

To make the text in the tree's nodes editable, we invoke setEditable(true) on the tree. When the user has finished editing a node, the model generates a tree model event that tells any listeners — including the JTree — that tree nodes have changed. Note that although DefaultMutableTreeNode has methods for changing a node's content, changes should go through the DefaultTreeModel cover methods. Otherwise, the tree model events would not be generated, and listeners such as the tree would not know about the updates.

To be notified of node changes, we can implement a TreeModelListener. Here is an example of a tree model listener that detects when the user has typed in a new name for a tree node:

class MyTreeModelListener implements TreeModelListener {
    public void treeNodesChanged(TreeModelEvent e) {
        DefaultMutableTreeNode node;
        node = (DefaultMutableTreeNode)
                 (e.getTreePath().getLastPathComponent());

        /*
         * If the event lists children, then the changed
         * node is the child of the node we have already
         * gotten.  Otherwise, the changed node and the
         * specified node are the same.
         */
        try {
            int index = e.getChildIndices()[0];
            node = (DefaultMutableTreeNode)
                   (node.getChildAt(index));
        } catch (NullPointerException exc) {}

        System.out.println("The user has finished editing the node.");
        System.out.println("New value: " + node.getUserObject());
    }
    public void treeNodesInserted(TreeModelEvent e) {
    }
    public void treeNodesRemoved(TreeModelEvent e) {
    }
    public void treeStructureChanged(TreeModelEvent e) {
    }
}

Here is the code that the Add button's event handler uses to add a new node to the tree:

treePanel.addObject("New Node " + newNodeSuffix++);
...
public DefaultMutableTreeNode addObject(Object child) {
    DefaultMutableTreeNode parentNode = null;
    TreePath parentPath = tree.getSelectionPath();

    if (parentPath == null) {
        //There is no selection. Default to the root node.
        parentNode = rootNode;
    } else {
        parentNode = (DefaultMutableTreeNode)
                     (parentPath.getLastPathComponent());
    }

    return addObject(parentNode, child, true);
}
...
public DefaultMutableTreeNode addObject(DefaultMutableTreeNode parent,
                                        Object child,
                                        boolean shouldBeVisible) {
    DefaultMutableTreeNode childNode =
            new DefaultMutableTreeNode(child);
    ...
    treeModel.insertNodeInto(childNode, parent,
                             parent.getChildCount());

    //Make sure the user can see the lovely new node.
    if (shouldBeVisible) {
        tree.scrollPathToVisible(new TreePath(childNode.getPath()));
    }
    return childNode;
}
The code creates a node, inserts it into the tree model, and then, if appropriate, requests that the nodes above it be expanded and the tree scrolled so that the new node is visible. To insert the node into the model, the code uses the insertNodeInto method provided by the DefaultTreeModel class.

Creating a Data Model

If DefaultTreeModel does not suit your needs, then you will need to write a custom data model. Your data model must implement the TreeModel interface. TreeModel specifies methods for getting a particular node of the tree, getting the number of children of a particular node, determining whether a node is a leaf, notifying the model of a change in the tree, and adding and removing tree model listeners.

Interestingly, the TreeModel interface accepts any kind of object as a tree node. It does not require that nodes be represented by DefaultMutableTreeNode objects, or even that nodes implement the TreeNode interface. Thus, if the TreeNode interface is not suitable for your tree model, feel free to devise your own representation for tree nodes. For example, if you have a pre-existing hierarchical data structure, you do not need to duplicate it or force it into the TreeNode mold. You just need to implement your tree model so that it uses the information in the existing data structure.

The following figure shows an application called GenealogyExample that displays the descendants or ancestors of a particular person. (Thanks to tutorial reader Olivier Berlanger for providing this example.)

Try this::
  1. Click the Launch button to run the Genealogy Example using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TreeDemo example

You can find the custom tree model implementation in GenealogyModel.java. Because the model is implemented as an Object subclass instead of, say, a subclass of DefaultTreeModel, it must implement the TreeModel interface directly. This requires implementing methods for getting information about nodes, such as which is the root and what are the children of a particular node. In the case of GenealogyModel, each node is represented by an object of type Person, a custom class that does not implement TreeNode.

A tree model must also implement methods for adding and removing tree model listeners, and must fire TreeModelEvents to those listeners when the tree's structure or data changes. For example, when the user instructs GenealogyExample to switch from showing ancestors to showing descendants, the tree model makes the change and then fires an event to inform its listeners (such as the tree component).

How to Load Children Lazily

Lazy loading is a characteristic of an application when the actual loading and instantiation of a class is delayed until the point just before the instance is actually used.

Do we gain anything by loading them lazily? Yes, this would definitely add to the performance of an application. By lazily loading, you can dedicate the memory resources to load and instantiate an object only when it is actually used. You can also speed up the initial loading time of an application.

One of the ways you can lazily load children of a Tree is by utilizing the TreeWillExpandListener interface. For example, you can declare and load root, grandparent and parent of a Tree along with the application as shown in the following code:

Let us declare the root, grandparent and parent as shown below:

class DemoArea extends JScrollPane
                   implements TreeWillExpandListener {
    .......
    .......

    private TreeNode createNodes() {
            DefaultMutableTreeNode root;
            DefaultMutableTreeNode grandparent;
            DefaultMutableTreeNode parent;

            root = new DefaultMutableTreeNode("San Francisco");

            grandparent = new DefaultMutableTreeNode("Potrero Hill");
            root.add(grandparent);

            parent = new DefaultMutableTreeNode("Restaurants");
            grandparent.add(parent);

            dummyParent = parent;
        return root;
        }
You can load above declared nodes to the tree as shown in the following code:
        TreeNode rootNode = createNodes();
            tree = new JTree(rootNode);
            tree.addTreeExpansionListener(this);
            tree.addTreeWillExpandListener(this);
        .......
        .......
            setViewportView(tree);

Now, you can load children lazily to the application whenever the parent node Restaurants is visible in the application. To do this, let us declare two children in a separate method and call that method as shown in the following code:

private void LoadLazyChildren(){
        DefaultMutableTreeNode child;
            child = new DefaultMutableTreeNode("Thai Barbeque");
            dummyParent.add(child);
            child = new DefaultMutableTreeNode("Goat Hill Pizza");
        dummyParent.add(child);
        textArea.append(" Thai Barbeque and Goat Hill Pizza are loaded lazily");
    }

    .......
    .......

public void treeWillExpand(TreeExpansionEvent e)
                    throws ExpandVetoException {
            saySomething("You are about to expand node ", e);
            int n = JOptionPane.showOptionDialog(
                this, willExpandText, willExpandTitle,
                JOptionPane.YES_NO_OPTION,
                JOptionPane.QUESTION_MESSAGE,
                null,
                willExpandOptions,
                willExpandOptions[1]);

    LoadLazyChildren();
    }

See How to Write a Tree-Will-Expand Listener for a description of Tree-Will-Expand listeners.

The Tree API

The tree API is quite extensive. The following tables list just a bit of the API, concentrating on the following categories:
  • Tree-Related Classes and Interfaces
  • Creating and Setting Up a Tree
  • Implementing Selection
  • Showing and Hiding Nodes

For more information about the tree API, see the API documentation for JTree and for the various classes and interfaces in the tree package. Also refer to The JComponent Class for information on the API JTree inherits from its superclass.

Tree-Related Classes and Interfaces
Class or Interface | Purpose
JTree | The component that presents the tree to the user.
TreePath | Represents a path to a node.
TreeNode
MutableTreeNode
DefaultMutableTreeNode 		The interfaces that the default tree model expects its tree nodes to implement, and the implementation used by the default tree model.
TreeModel
DefaultTreeModel 		Respectively, the interface that a tree model must implement and the usual implementation used.
TreeCellRenderer
DefaultTreeCellRenderer 		Respectively, the interface that a tree cell renderer must implement and the usual implementation used.
TreeCellEditor
DefaultTreeCellEditor 		Respectively, the interface that a tree cell editor must implement and the usual implementation used.
TreeSelectionModel
DefaultTreeSelectionModel 		Respectively, the interface that the tree's selection model must implement and the usual implementation used.
TreeSelectionListener
TreeSelectionEvent 		The interface and event type used for detecting tree selection changes. For more information, see Getting Started.
TreeModelListener
TreeModelEvent 		The interface and event type used for detecting tree model changes. For more information, see How to Write a Tree Model Listener.
TreeExpansionListener
TreeWillExpandListener
TreeExpansionEvent 		The interfaces and event type used for detecting tree expansion and collapse. For more information, see How to Write a Tree Expansion Listener and How to Write a Tree-Will-Expand Listener.
ExpandVetoException | An exception that a TreeWillExpandListener can throw to indicate that the impending expansion/collapse should not happen. For more information, see How to Write a Tree-Will-Expand Listener.

Creating and Setting Up a Tree
Constructor or Method | Purpose
JTree(TreeNode)
JTree(TreeNode, boolean)
JTree(TreeModel)
JTree()
JTree(Hashtable)
JTree(Object[])
JTree(Vector) 		Create a tree. The TreeNode argument specifies the root node, to be managed by the default tree model. The TreeModel argument specifies the model that provides the data to the table. The no-argument version of this constructor is for use in builders; it creates a tree that contains some sample data. If you specify a Hashtable, array of objects, or Vector as an argument, then the argument is treated as a list of nodes under the root node (which is not displayed), and a model and tree nodes are constructed accordingly.

The boolean argument, if present, specifies how the tree should determine whether a node should be displayed as a leaf. If the argument is false (the default), any node without children is displayed as a leaf. If the argument is true, a node is a leaf only if its getAllowsChildren method returns false.

void setCellRenderer(TreeCellRenderer) | Set the renderer that draws each node.
void setEditable(boolean)
void setCellEditor(TreeCellEditor) 		The first method sets whether the user can edit tree nodes. By default, tree nodes are not editable. The second sets which customized editor to use.
void setRootVisible(boolean) | Set whether the tree shows the root node. The default value is false if the tree is created using one of the constructors that takes a data structure, and true otherwise.
void setShowsRootHandles(boolean) | Set whether the tree shows handles for its leftmost nodes, letting you expand and collapse the nodes. The default is false. If the tree does not show the root node, then you should invoke setShowsRootHandles(true).
void setDragEnabled(boolean)
boolean getDragEnabled() 		Set or get the dragEnabled property, which must be true to enable drag handling on this component. The default value is false. See Drag and Drop for more details.

Implementing Selection
Method | Purpose
void addTreeSelectionListener(TreeSelectionListener) | Register a listener to detect when the a node is selected or deselected.
void setSelectionModel(TreeSelectionModel)
TreeSelectionModel getSelectionModel() 		Set or get the model used to control node selections. You can turn off node selection completely using setSelectionModel(null).
void setSelectionMode(int)
int getSelectionMode()
(in TreeSelectionModel) 		Set or get the selection mode. The value can be CONTIGUOUS_TREE_SELECTION, DISCONTIGUOUS_TREE_SELECTION, or SINGLE_TREE_SELECTION (all defined in TreeSelectionModel).
Object getLastSelectedPathComponent() | Get the object representing the currently selected node. This is equivalent to invoking getLastPathComponent on the value returned by tree.getSelectionPath().
void setSelectionPath(TreePath)
TreePath getSelectionPath() 		Set or get the path to the currently selected node.
void setSelectionPaths(TreePath[])
TreePath[] getSelectionPaths() 		Set or get the paths to the currently selected nodes.
void setSelectionPath(TreePath)
TreePath getSelectionPath() 		Set or get the path to the currently selected node.

Showing and Hiding Nodes
Method | Purpose
void addTreeExpansionListener(TreeExpansionListener)
void addTreeWillExpandListener(TreeWillExpandListener) 		Register a listener to detect when the tree nodes have expanded or collapsed, or will be expanded or collapsed, respectively. To veto an impending expansion or collapse, a TreeWillExpandListener can throw a ExpandVetoException.
void expandPath(TreePath)
void collapsePath(TreePath) 		Expand or collapse the specified tree path.
void scrollPathToVisible(TreePath) | Ensure that the node specified by the path is visible — that the path leading up to it is expanded and the node is in the scroll pane's viewing area.
void makeVisible(TreePath) | Ensure that the node specified by the path is viewable — that the path leading up to it is expanded. The node might not end up within the viewing area.
void setScrollsOnExpand(boolean)
boolean getScrollsOnExpand() 		Set or get whether the tree attempts to scroll to show previous hidden nodes. The default value is true.
void setToggleClickCount(int)
int getToggleClickCount() 		Set or get the number of mouse clicks before a node will expand or close. The default is two.
TreePath getNextMatch(String, int, Position.Bias) | Return the TreePath to the next tree element that begins with the specific prefix.

Examples that Use Trees

This table lists examples that use JTree and where those examples are described.

Example | Where Described | Notes
TreeDemo | Creating a Tree, Responding to Node Selection, Customizing a Tree's Display | Creates a tree that responds to user selections. It also has code for customizing the line style for the Java look and feel.
TreeIconDemo | Customizing a Tree's Display | Adds a custom leaf icon to TreeDemo.
TreeIconDemo2 | Customizing a Tree's Display | Customizes certain leaf icons and also provides tool tips for certain tree nodes.
DynamicTreeDemo | Dynamically Changing a Tree | Illustrates adding and removing nodes from a tree. Also allows editing of node text.
GenealogyExample | Creating a Data Model | Implements a custom tree model and custom node type.
TreeExpandEventDemo | How to Write a Tree Expansion Listener | Shows how to detect node expansions and collapses.
TreeExpandEventDemo2 | How to Write a Tree-Will-Expand Listener | Shows how to veto node expansions.
TreeTable, TreeTable II, Editable JTreeTable | Creating TreeTables in Swing, Creating TreeTables: Part 2, Editable JTreeTable | Examples in The Swing Connection that combine a tree and table to show detailed information about a hierarchy such as a file system. The tree is a renderer for the table.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Tool Tips
Next page: How to Use HTML in Swing Components


How to Use HTML in Swing Components (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use HTML in Swing Components
Many Swing components display a text string as part of their GUI. By default, a component's text is displayed in a single font and color, all on one line. You can determine the font and color of a component's text by invoking the component's setFont and setForeground methods, respectively. For example, the following code creates a label and then sets its font and color:
label = new JLabel("A label");
label.setFont(new Font("Serif", Font.PLAIN, 14));
label.setForeground(new Color(0xffffdd));
If you want to mix fonts or colors within the text, or if you want formatting such as multiple lines, you can use HTML. HTML formatting can be used in all Swing buttons, menu items, labels, tool tips, and tabbed panes, as well as in components such as trees and tables that use labels to render text.

To specify that a component's text has HTML formatting, just put the <html> tag at the beginning of the text, then use any valid HTML in the remainder. Here is an example of using HTML in a button's text:

button = new JButton("<html><b><u>T</u>wo</b><br>lines</html>");
Here is the resulting button. Screenshot of a button that shows HTML in the Metal look and feel.

An Example: HtmlDemo

An application called HtmlDemo lets you play with HTML formatting by setting the text on a label. You can find the entire code for this program in HtmlDemo.java. Here is a picture of the HtmlDemo example.

Screenshot of HtmlDemo in the Metal look and feel.

Try This:
  1. Click the Launch button to run HtmlDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    2. Launches the HtmlDemo Application

  2. Edit the HTML formatting in the text area at the left and click the "Change the label" button. The label at the right shows the result.
  3. Remove the <html> tag from the text area on the left. The label's text is no longer parsed as HTML.

Example 2: ButtonHtmlDemo

Let us look at another example that uses HTML. ButtonHtmlDemo adds font, color, and other text formatting to three buttons. You can find the entire code for this program in ButtonHtmlDemo.java. Here is a picture of the ButtonHtmlDemo example.

Screenshot of ButtonHtmlDemo in the Metal look and feel.

Click the Launch button to run ButtonHtmlDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the ButtonHtmlDemo Application

The left and right buttons have multiple lines and text styles and are implemented using HTML. The middle button, on the other hand, uses just one line, font, and color, so it does not require HTML. Here is the code that specifies the text formatting for these three buttons:

b1 = new JButton("<html><center><b><u>D</u>isable</b><br>"
                 + "<font color=#ffffdd>middle button</font>",
                 leftButtonIcon);
Font font = b1.getFont().deriveFont(Font.PLAIN);
b1.setFont(font);
...
b2 = new JButton("middle button", middleButtonIcon);
b2.setFont(font);
b2.setForeground(new Color(0xffffdd));
...
b3 = new JButton("<html><center><b><u>E</u>nable</b><br>"
                 + "<font color=#ffffdd>middle button</font>",
                 rightButtonIcon);
b3.setFont(font);
Note that we have to use a <u> tag to cause the mnemonic characters "D" and "E" to be underlined in the buttons that use HTML. Note also that when a button is disabled, its HTML text unfortunately remains black, instead of becoming gray. (Refer to bug #4783068 to see if this situation changes.)

This section discussed how to use HTML in ordinary, non-text components. For information on components whose primary purpose is formatting text, see Using Text Components.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Trees
Next page: How to Use Models


How to Use Models (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Models
Most Swing components have models. A button (JButton), for example, has a model (a ButtonModel object) that stores the button's state — what its keyboard mnemonic is, whether it's enabled, selected, or pressed, and so on. Some components have multiple models. A list (JList), for example, uses a ListModel to hold the list's contents, and a ListSelectionModel to track the list's current selection.

You often don't need to know about the models that a component uses. For example, programs that use buttons usually deal directly with the JButton object, and don't deal at all with the ButtonModel object.

Why then do models exist? The biggest reason is that they give you flexibility in determining how data is stored and retrieved. For example, if you're designing a spreadsheet application that displays data in a sparsely populated table, you can create your own table model that is optimized for such use.

Models have other benefits, too. They mean that data isn't copied between a program's data structures and those of the Swing components. Also, models automatically propagate changes to all interested listeners, making it easy for the GUI to stay in sync with the data. For example, to add items to a list you can invoke methods on the list model. When the model's data changes, the model fires events to the JList and any other registered listeners, and the GUI is updated accordingly.

Although Swing's model architecture is sometimes referred to as a Model-View-Controller (MVC) design, it really isn't. Swing components are generally implemented so that the view and controller are indivisible, implemented by a single UI object provided by the look and feel. The Swing model architecture is more accurately described as a separable model architecture. If you're interested in learning more about the Swing model architecture, see A Swing Architecture Overview, an article in The Swing Connection.

An Example: Converter

This section features an example called Converter, which is an application that continuously converts distance measurements between metric and U.S. units. You can run Converter ( download JDK 6). Or, to compile and run the example yourself, consult the example index.

As the following picture shows, Converter features two sliders, each tied to a text field. The sliders and text fields all display the same data — a distance — but using two different units of measure.

Converter screenshot in the Metal look and feel

The important thing for this program is ensuring that only one model controls the value of the data. There are various ways to achieve this; we did it by deferring to the top slider's model. The bottom slider's model (an instance of a custom class called FollowerRangeModel) forwards all data queries to the top slider's model (an instance of a custom class called ConverterRangeModel). Each text field is kept in sync with its slider, and vice versa, by event handlers that listen for changes in value. Care is taken to ensure that the top slider's model has the final say about what distance is displayed.

When we started implementing the custom slider models, we first looked at the API section of How to Use Sliders. It informed us that all slider data models must implement the BoundedRangeModel interface. The BoundedRangeModel API documentation tells us that the interface has an implementing class named DefaultBoundedRangeModel. The API documentation for DefaultBoundedRangeModel shows that it's a general-purpose implementation of BoundedRangeModel.

We didn't use DefaultBoundedRangeModel directly because it stores data as integers, and Converter uses floating-point data. Thus, we implemented ConverterRangeModel as a subclass of Object. We then implemented FollowerRangeModel as a subclass of ConverterRangeModel.

For Further Information

To find out about the models for individual components, see the "How to" pages and API documentation for individual components. Here are some of our examples that use models directly:

  • All but the simplest of the table examples implement custom table data models.
  • The color chooser demos have change listeners on the color chooser's selection model so they can be notified when the user selects a new color. In ColorChooserDemo2, the CrayonPanel class directly uses the color selection model to set the current color.
  • The DynamicTreeDemo example sets the tree model (to an instance of DefaultTreeModel), interacts directly with it, and listens for changes to it.
  • ListDemo sets the list data model (to an instance of DefaultListModel) and interacts directly with it.
  • SharedModelDemo defines a SharedDataModel class that extends DefaultListModel and implements TableModel. A JList and JTable share an instance of SharedDataModel, providing different views of the model's data.
  • In the event listener examples, ListDataEventDemo creates and uses a DefaultListModel directly.
  • Our spinner examples create spinner models.
  • As you've already seen, the Converter example defines two custom slider models.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use HTML in Swing Components
Next page: How to Use Icons


How to Use Icons (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Icons

Many Swing components, such as labels, buttons, and tabbed panes, can be decorated with an icon — a fixed-sized picture. An icon is an object that adheres to the Icon interface. Swing provides a particularly useful implementation of the Icon interface: ImageIcon, which paints an icon from a GIF, JPEG, or PNG image.

Here's a snapshot of an application with three labels, two decorated with an icon:

An example of using image icons to decorate labels.

The program uses one image icon to contain and paint the yellow splats. One statement creates the image icon and two more statements include the image icon on each of the two labels:

ImageIcon icon = createImageIcon("images/middle.gif",
                                 "a pretty but meaningless splat");
label1 = new JLabel("Image and Text", icon, JLabel.CENTER);
...
label3 = new JLabel(icon);

The createImageIcon method (used in the preceding snippet) is one we use in many of our code samples. It finds the specified file and returns an ImageIcon for that file, or null if that file couldn't be found. Here is a typical implementation:

/** Returns an ImageIcon, or null if the path was invalid. */
protected ImageIcon createImageIcon(String path,
                                           String description) {
    java.net.URL imgURL = getClass().getResource(path);
    if (imgURL != null) {
        return new ImageIcon(imgURL, description);
    } else {
        System.err.println("Couldn't find file: " + path);
        return null;
    }
}

In the preceding snippet, the first argument to the ImageIcon constructor is relative to the location of the current class, and will be resolved to an absolute URL. The description argument is a string that allows assistive technologies to help a visually impaired user understand what information the icon conveys.

Generally, applications provide their own set of images used as part of the application, as is the case with the images used by many of our demos. You should use the Class getResource method to obtain the path to the image. This allows the application to verify that the image is available and to provide sensible error handling if it is not. When the image is not part of the application, getResource should not be used and the ImageIcon constructor is used directly. For example:

ImageIcon icon = new ImageIcon("images/middle.gif",
                               "a pretty but meaningless splat");

When you specify a filename or URL to an ImageIcon constructor, processing is blocked until after the image data is completely loaded or the data location has proven to be invalid. If the data location is invalid (but non-null), an ImageIcon is still successfully created; it just has no size and, therefore, paints nothing. As shown in the createImageIcon method, it is advisable to first verify that the URL points to an existing file before passing it to the ImageIcon constructor. This allows graceful error handling when the file isn't present. If you want more information while the image is loading, you can register an observer on an image icon by calling its setImageObserver method.

Under the covers, each image icon uses an Image object to hold the image data.

The rest of this section covers the following topics:

  • A More Complex Image Icon Example
  • Loading Images Using getResource
  • Loading Images Into Applets
  • Improving Perceived Performance When Loading Image Icons
  • Creating a Custom Icon Implementation
  • The Image Icon API
  • Examples that Use Icons

A More Complex Image Icon Example

Here's an application that uses six image icons. Five of them display display thumbnail images and the sixth diplays the full size the photograph.

The initial view of the IconDemo application.

Try this:

  1. Click the Launch button to run IconDemo using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

    Launches the IconDemo example

  2. Click any of the thumbnail images to view the full size photographs.

  3. Hold the mouse over a photograph. A tool tip appears that displays the photograph caption.

IconDemoApp demonstrates icons used in the following ways:

  • As a GUI element attached to a button (the thumbnail images on the buttons).
  • To display an image (the five photographs).

The photographs are loaded in a separate thread by loadimages.execute. The loadimages code is shown a little later in this section.

The ThumbnailAction class, an inner class in IconDemoApp.java, is a descendant of AbstractAction that manages our full size image icon, a thumbnail version, and its description. When the actionPerformed method is called the full size image is loaded into the main display area. Each button has its own instance of ThumbnailAction which specifies a different image to show.

/**
 * Action class that shows the image specified in it's constructor.
 */
private class ThumbnailAction extends AbstractAction{

    /**
     *The icon if the full image we want to display.
     */
    private Icon displayPhoto;

    /**
     * @param Icon - The full size photo to show in the button.
     * @param Icon - The thumbnail to show in the button.
     * @param String - The descriptioon of the icon.
     */
    public ThumbnailAction(Icon photo, Icon thumb, String desc){
        displayPhoto = photo;

        // The short description becomes the tooltip of a button.
        putValue(SHORT_DESCRIPTION, desc);

        // The LARGE_ICON_KEY is actually the key for setting the
        // icon when an Action is applied to a button.
        putValue(LARGE_ICON_KEY, thumb);
    }

    /**
     * Shows the full image in the main area and sets the application title.
     */
    public void actionPerformed(ActionEvent e) {
        photographLabel.setIcon(displayPhoto);
        setTitle("Icon Demo: " + getValue(SHORT_DESCRIPTION).toString());
    }
}

Loading Images Using getResource

Most often, an image icon's data comes from an image file. There are a number of valid ways that your application's class and image files may be configured on your file server. You might have your class files in a JAR file, or your image files in a JAR file; they might be in the same JAR file, or they might be in different JAR files. The following figures illustrate a few of the ways these files can be configured:

Diagram showing MyDemo.class and images/myImage.png under the parent directory | Diagram showing MyDemo.class and image.jar under the parent directory
Class file next to an image directory containing the image file, in PNG format. | Class file in same directory as JAR file. The JAR file was created with all the images in an images directory.
Diagram showing MyDemo.jar and image.jar under the parent directory | Diagram showing MyDemo.class and images/myImage.png in the same JAR file
Class file in one JAR file and the images in another JAR file. | Class and image files in same JAR file.

If you are writing a real-world application, it is likely (and recommended) that you put your files into a package. For more information on packages, see Creating and Using Packages in the Learning the Java Language trail. Here are some possible configurations using a package named "omega":

Diagram showing omega package with MyDemo.class and image.jar
Class file in directory named omega. Image in omega/images directory. Class file in omega directory. Image in JAR file not inside of omega directory, but created with omega/images hierarchy.
One big JAR file with class files under omega directory and image files under omega/images directory.

All seven configurations shown are valid, and the same code reads the image:

java.net.URL imageURL = myDemo.class.getResource("images/myImage.gif");
...
if (imageURL != null) {
    ImageIcon icon = new ImageIcon(imageURL);
}

The getResource method causes the class loader to look through the directories and JAR files in the program's class path, returning a URL as soon as it finds the desired file. In the example the MyDemo program attempts to load the images/myImage.png file from the omega class. The class loader looks through the directories and JAR files in the program's class path for /omega/images/myImage.png. If the class loader finds the file, it returns the URL of the JAR file or directory that contained the file. If another JAR file or directory in the class path contains the images/myImage.png file, the class loader returns the first instance that contains the file.

Here are three ways to specify the class path:

  • Using the -cp or -classpath command-line argument. For example, in the case where the images are in a JAR file named images.jar and the class file is in the current directory:

    java -cp  .;image.jar  MyDemo  [Microsoft Windows]
java -cp ".;image.jar" MyDemo  [Unix-emulating shell on Microsoft
                                Windows — you must quote the path]
java -cp  .:image.jar  MyDemo  [Unix]

    If your image and class files are in separate JAR files, your command line will look something like:

    java -cp .;MyDemo.jar;image.jar MyDemo  [Microsoft Windows]

    In the situation where all the files are in one JAR file, you can use either of the following commands:

    java -jar MyAppPlusImages.jar
java -cp .;MyAppPlusImages.jar MyApp  [Microsoft Windows]

    For more information, see the JAR Files trail.

  • In the program's JNLP file (used by Java Web Start). For example, here is the JNLP file used by DragPictureDemo:

    <?xml version="1.0" encoding="utf-8"?>
<!-- JNLP File for DragPictureDemo -->
<jnlp
  spec="1.0+"
  codebase="http://java.sun.com/docs/books/tutorialJWS/src/uiswing/misc/examples"
  href="DragPictureDemo.jnlp">
  <information>
    <title>DragPictureDemo</title>
    <vendor>The Java(tm) Tutorial: Sun Microsystems, Inc.</vendor>
    <homepage href="http://java.sun.com/docs/books/tutorial/uiswing/misc/examples/index.html#DragPictureDemo"/>
    <description>DragPictureDemo</description>
    <description kind="short">A demo showing how to install
        data transfer on a custom component.</description>
    <offline-allowed/>
  </information>
  <resources>
    <j2se version="1.6+"/>
    <jar href="allClasses.jar"/>
    <jar href="images.jar"/>
  </resources>
  <application-desc main-class="DragPictureDemo"/>
</jnlp>

    In this example, the class files and the images files are in separate JAR files. The JAR files are specified using the XML jar tag.

  • Setting the CLASSPATH environment variable. This last approach is not recommended. If CLASSPATH is not set, the current directory (".") followed by the location of the system classes shipped with the JRE are used by default.

Most of the Swing Tutorial examples put the images in an images directory under the directory that contains the examples' class files. When we create JAR files for the examples, we keep the same relative locations, although often we put the class files in a different JAR file than the image JAR file. No matter where the class and image files are in the file system — in one JAR file, or in multiple JAR files, in a named package, or in the default package — the same code finds the image files using getResource.

For more information, see Accessing Resources in a Location-Independent Manner and the Application Development Considerations.

Loading Images Into Applets

Applets generally load image data from the computer that served up the applet. The APPLET tag is where you specify information about the images used in the applet. For more information on the APPLET tag see Using the APPLET Tag

Improving Perceived Performance When Loading Image Icons

Because the photograph images can be slow to access, IconDemoApp.java uses a SwingWorker to improve the performance of the program as perceived by the user.

Background image loading — the program uses a javax.swing.SwingWorker object to load each photograph image and compute it's thumbnail in a background thread. Using a SwingWorker prevents the program from appearing to freeze up while loading and scaling the images.

Here's the code to process each image:

/**
 * SwingWorker class that loads the images a background thread and calls publish
 * when a new one is ready to be displayed.
 *
 * We use Void as the first SwingWroker param as we do not need to return
 * anything from doInBackground().
 */
private SwingWorker loadimages = new SwingWorker() {

    /**
     * Creates full size and thumbnail versions of the target image files.
     */
    @Override
    protected Void doInBackground() throws Exception {
        for (int i = 0; i < imageCaptions.length; i++) {
            ImageIcon icon;
            icon = createImageIcon(imagedir + imageFileNames[i], imageCaptions[i]);

            ThumbnailAction thumbAction;
            if(icon != null){

                ImageIcon thumbnailIcon = new
                     ImageIcon(getScaledImage(icon.getImage(), 32, 32));

                thumbAction = new ThumbnailAction(icon, thumbnailIcon, imageCaptions[i]);

            } else {
                // the image failed to load for some reason
                // so load a placeholder instead
                thumbAction = new ThumbnailAction(placeholderIcon, placeholderIcon, imageCaptions[i]);
            }
            publish(thumbAction);
        }
        // unfortunately we must return something, and only null is valid to
        // return when the return type is void.
        return null;
    }

    /**
     * Process all loaded images.
     */
    @Override
    protected void process(List chunks) {
        for (ThumbnailAction thumbAction : chunks) {
            JButton thumbButton = new JButton(thumbAction);
            // add the new button BEFORE the last glue
            // this centers the buttons in the toolbar
            buttonBar.add(thumbButton, buttonBar.getComponentCount() - 1);
        }
    }
};
SwingWorker invokes the doInBackground method in a background thread. The method places a full size image, thumbnail size image and caption into a ThumbnailAction object. The SwingWorker then delivers the ThumbnailAction to the process method. The process method executes on the event dispatch thread and updates the GUI by adding a button to the toolbar. JButton has a constructor that takes an action object. The action object determines a number of the button's properties. In our case the button icon, the caption and the action to be performed when the button is pressed is all determined by the ThumbnailAction.

Overhead — this program eventually loads all the source images into memory. This may not be desirable in all situations. Loading a number of very large files could cause the program to allocate a very large amount or memory. Care should be taken to manage the number and size of images that are loaded.

As with all performance-related issues, this technique is applicable in some situations and not others. Also the technique described here is designed to improve the program's perceived performance, but does not necessarily impact its real performance.

Creating a Custom Icon Implementation

The createImageIcon method returns null when it cannot find an image, but what should the program do then? One possibility would be to ignore that image and move on. Another option would be to provide some sort of default icon to display when the real one cannot be loaded. Making another call to createImageIcon might result in another null so using that is not a good idea. Instead lets create a custom Icon implementation.

An example of MissingIcon.

You can find the implementation of the custom icon class in MissingIcon.java. Here are the interesting parts of its code:

/**
 * The "missing icon" is a white box with a black border and a red x.
 * It's used to display something when there are issues loading an
 * icon from an external location.
 *
 * @author Collin Fagan
 */
public class MissingIcon implements Icon{

    private int width = 32;
    private int height = 32;

    private BasicStroke stroke = new BasicStroke(4);

    public void paintIcon(Component c, Graphics g, int x, int y) {
        Graphics2D g2d = (Graphics2D) g.create();

        g2d.setColor(Color.WHITE);
        g2d.fillRect(x +1 ,y + 1,width -2 ,height -2);

        g2d.setColor(Color.BLACK);
        g2d.drawRect(x +1 ,y + 1,width -2 ,height -2);

        g2d.setColor(Color.RED);

        g2d.setStroke(stroke);
        g2d.drawLine(x +10, y + 10, x + width -10, y + height -10);
        g2d.drawLine(x +10, y + height -10, x + width -10, y + 10);

        g2d.dispose();
    }

    public int getIconWidth() {
        return width;
    }

    public int getIconHeight() {
        return height;
    }
}

The paintIcon method is passed a Graphics object. The Graphics object gives the paintIcon method access to the entire Java2D API. For more information about painting and Java2D, see Performing Custom Painting.

The following code demonstrates how the MissingIcon class is used in the SwingWorker doInBackground method.

private MissingIcon placeholderIcon = new MissingIcon();

...
if(icon != null) {
    ...

} else {
    // the image failed to load for some reason
    // so load a placeholder instead
    thumbAction = new ThumbnailAction(placeholderIcon, placeholderIcon, imageCaptions[i]);
}

Using a custom icon has a few implications:

  • Because the icon's appearance is determined dynamically, the icon painting code can use any information — component and application state, for example — to determine what to paint.

  • Depending on the platform and the type of image, you may get a performance boost with custom icons, since painting simple shapes can sometimes be faster than copying images.

  • Because MissingIcon does not do any file I/O there is no need for separate threads to load the image.

The Image Icon API

The following tables list the commonly used ImageIcon constructors and methods. Note that ImageIcon is not a descendent of JComponent or even of Component.

The API for using image icons falls into these categories:

  • Setting, Getting, and Painting the Image Icon's Image
  • Setting or Getting Information about the Image Icon
  • Watching the Image Icon's Image Load
Setting, Getting, and Painting the Image Icon's Image
Method or Constructor | Purpose
ImageIcon()
ImageIcon(byte[])
ImageIcon(byte[], String)
ImageIcon(Image)
ImageIcon(Image, String)
ImageIcon(String)
ImageIcon(String, String)
ImageIcon(URL)
ImageIcon(URL, String) 		Create an ImageIcon instance, initializing it to contain the specified image. The first argument indicates the source — image, byte array, filename, or URL — from which the image icon's image should be loaded. The source must be in a format supported by the java.awt.Image class: namely GIF, JPEG, or PNG. The second argument, when present, provides a description for the image. The description may also be set via setDescription and provides useful textual information for assistive technologies.
void setImage(Image)
Image getImage() 		Set or get the image displayed by the image icon.
void paintIcon(Component, Graphics, int, int) | Paint the image icon's image in the specified graphics context. You would override this only if you're implementing a custom icon that performs its own painting. The Component object is used as an image observer. You can rely on the default behavior provided by Component class, and pass in any component. The two int arguments specify the top-left corner where the icon is painted.
URL getResource(String)
in (java.lang.ClassLoader) 		Find the resource with the given name. For more information, see Loading Images Using getResource.
InputStream getResourceAsStream(String)
in (java.lang.ClassLoader) 		Find the resource with the given name and return an input stream for reading the resource. For more information, see the Loading Images Into Applets discussion.

Setting or Getting Information about the Image Icon
Method Purpose
void setDescription(String)
String getDescription() 		Set or get a description of the image. This description is intended for use by assistive technologies.
int getIconWidth()
int getIconHeight() 		Get the width or height of the image icon in pixels.

Watching the Image Icon's Image Load
Method | Purpose
void setImageObserver(ImageObserver)
ImageObserver getImageObserver() 		Set or get an image observer for the image icon.
int getImageLoadStatus() | Get the loading status of the image icon's image. The values returned by this method are defined by MediaTracker.

Examples that Use Icons

The following table lists just a few of the many examples that use ImageIcon.

Example | Where Described | Notes
LabelDemo This section and
How to Use Labels 		Demonstrates using icons in an application's label, with and without accompanying text.
IconDemo | This section | Uses a label to show large images; uses buttons that have both images and text.
CustomIconDemo | This section | Uses a custom icon class implemented by ArrowIcon.java.
TumbleItem | How to Make Applets | An applet. Uses image icons in an animation. Shows how to call ImageIcon's paintIcon method.
ButtonDemo | How to Use Buttons, Check Boxes, and Radio Buttons | Shows how to use icons in an application's buttons.
CheckBoxDemo | How to Use Check Boxes | Uses multiple GIF images.
TabbedPaneDemo | How to Use Tabbed Panes | Demonstrates adding icons to tabs in a tabbed pane.
DialogDemo | How to Make Dialogs | Shows how to use standard icons in dialogs.
TreeIconDemo | How to Use Trees | Shows how to change the icons displayed by a tree's nodes.
ActionDemo | How to Use Actions | Shows how to specify the icon in a tool-bar button or menu item using an Action.
FileChooserDemo2 | How to Use File Choosers | Uses a PNG image. Shows how to implement an image previewer and an image filter in a file chooser.
Note: The photographs used in the IconDemo are copyright ©2006 spriggs.net and licenced under a Creative Commons Licence.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Models
Next page: How to Use Borders


How to Use Borders (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
How to Use Borders
Every JComponent can have one or more borders. Borders are incredibly useful objects that, while not themselves components, know how to draw the edges of Swing components. Borders are useful not only for drawing lines and fancy edges, but also for providing titles and empty space around components.
Note: Our examples set borders on JPanels, JLabels, and custom subclasses of JComponent. Although technically you can set the border on any object that inherits from JComponent, the look and feel implementation of many standard Swing components doesn't work well with user-set borders. In general, when you want to set a border on a standard Swing component other than JPanel or JLabel, we recommend that you put the component in a JPanel and set the border on the JPanel.

To put a border around a JComponent, you use its setBorder method. You can use the BorderFactory class to create most of the borders that Swing provides. If you need a reference to a border — say, because you want to use it in multiple components — you can save it in a variable of type Border. Here is an example of code that creates a bordered container:

JPanel pane = new JPanel();
pane.setBorder(BorderFactory.createLineBorder(Color.black));

Here's a picture of the container, which contains a label component. The black line drawn by the border marks the edge of the container.

A line border

The rest of this page discusses the following topics:
  • The BorderDemo Example
  • Using the Borders Provided by Swing
  • Creating Custom Borders
  • The Border API
  • Examples of Using Borders

The BorderDemo Example

The following pictures show an application called BorderDemo that displays the borders Swing provides. We show the code for creating these borders a little later, in Using the Borders Provided by Swing.

Click the Launch button to run the BorderDemo example using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the BorderDemo example

BorderDemo: Simple Borders

The next picture shows some matte borders. When creating a matte border, you specify how many pixels it occupies at the top, left, bottom, and right of a component. You then specify either a color or an icon for the matte border to draw. You need to be careful when choosing the icon and determining your component's size; otherwise, the icon might get chopped off or have mismatch at the component's corners.

BorderDemo: Matte Borders

The next picture shows titled borders. Using a titled border, you can convert any border into one that displays a text description. If you don't specify a border, a look-and-feel-specific border is used. For example, the default titled border in the Java look and feel uses a gray line, and the default titled border in the Windows look and feel uses an etched border. By default, the title straddles the upper left of the border, as shown at the top of the following figure.

BorderDemo: Titled Borders

The next picture shows compound borders. With compound borders, you can combine any two borders, which can themselves be compound borders.

BorderDemo: Compound Borders

Using the Borders Provided by Swing

The code that follows shows how to create and set the borders you saw in the preceding figures. You can find the program's code in BorderDemo.java.

//Keep references to the next few borders,
//for use in titles and compound borders.
Border blackline, raisedetched, loweredetched,
       raisedbevel, loweredbevel, empty;

blackline = BorderFactory.createLineBorder(Color.black);
raisedetched = BorderFactory.createEtchedBorder(EtchedBorder.RAISED);
loweredetched = BorderFactory.createEtchedBorder(EtchedBorder.LOWERED);
raisedbevel = BorderFactory.createRaisedBevelBorder();
loweredbevel = BorderFactory.createLoweredBevelBorder();
empty = BorderFactory.createEmptyBorder();

//Simple borders
jComp1.setBorder(blackline);
jComp2.setBorder(raisedbevel);
jComp3.setBorder(loweredbevel);
jComp4.setBorder(empty);

//Matte borders
ImageIcon icon = createImageIcon("images/wavy.gif",
                                 "wavy-line border icon"); //20x22

jComp5.setBorder(BorderFactory.createMatteBorder(
                                   -1, -1, -1, -1, icon));
jComp6.setBorder(BorderFactory.createMatteBorder(
                                    1, 5, 1, 1, Color.red));
jComp7.setBorder(BorderFactory.createMatteBorder(
                                    0, 20, 0, 0, icon));

//Titled borders
TitledBorder title;
title = BorderFactory.createTitledBorder("title");
jComp8.setBorder(title);

title = BorderFactory.createTitledBorder(
               blackline, "title");
title.setTitleJustification(TitledBorder.CENTER);
jComp9.setBorder(title);

title = BorderFactory.createTitledBorder(
               loweredetched, "title");
title.setTitleJustification(TitledBorder.RIGHT);
jComp10.setBorder(title);

title = BorderFactory.createTitledBorder(
               loweredbevel, "title");
title.setTitlePosition(TitledBorder.ABOVE_TOP);
jComp11.setBorder(title);

title = BorderFactory.createTitledBorder(
               empty, "title");
title.setTitlePosition(TitledBorder.BOTTOM);
jComp12.setBorder(title);

//Compound borders
Border compound;
Border redline = BorderFactory.createLineBorder(Color.red);

//This creates a nice frame.
compound = BorderFactory.createCompoundBorder(
              raisedbevel, loweredbevel);
jComp13.setBorder(compound);

//Add a red outline to the frame.
compound = BorderFactory.createCompoundBorder(
              redline, compound);
jComp14.setBorder(compound);

//Add a title to the red-outlined frame.
compound = BorderFactory.createTitledBorder(
              compound, "title",
              TitledBorder.CENTER,
              TitledBorder.BELOW_BOTTOM);
jComp15.setBorder(compound);
As you probably noticed, the code uses the BorderFactory class to create each border. The BorderFactory class, which is in the javax.swing package, returns objects that implement the Border interface.

The Border interface, as well as its Swing-provided implementations, is in the javax.swing.border package. You often don't need to directly use anything in the border package, except when specifying constants that are specific to a particular border class or when referring to the Border type.

Creating Custom Borders

If BorderFactory doesn't offer you enough control over a border's form, then you might need to directly use the API in the border package — or even define your own border. In addition to containing the Border interface, the border package contains the classes that implement the borders you've already seen: LineBorder, EtchedBorder, BevelBorder, EmptyBorder, MatteBorder, TitledBorder, and CompoundBorder. The border package also contains a class named SoftBevelBorder, which produces a result similar to BevelBorder, but with softer edges.

If none of the Swing borders is suitable, you can implement your own border. Generally, you do this by creating a subclass of the AbstractBorder class. In your subclass, you must implement at least one constructor and the following two methods:

  • paintBorder, which contains the drawing code that a JComponent executes to draw the border.
  • getBorderInsets, which specifies the amount of space the border needs to draw itself.

If a custom border has insets (and they typically have insets) you need to override both AbstractBorder.getBorderInsets(Component c) and AbstractBorder.getBorderInsets(Component c, Insets insets) to provide the correct insets.

For examples of implementing borders, see the source code for the classes in the javax.swing.border package.

The Border API

The following tables list the commonly used border methods. The API for using borders falls into two categories:
  • Creating a Border with BorderFactory
  • Setting or Getting a Component's Border

Creating a Border with BorderFactory
Method | Purpose
Border createLineBorder(Color)
Border createLineBorder(Color, int) 		Create a line border. The first argument is a java.awt.Color object that specifies the color of the line. The optional second argument specifies the width in pixels of the line.
Border createEtchedBorder()
Border createEtchedBorder(Color, Color)
Border createEtchedBorder(int)
Border createEtchedBorder(int, Color, Color) 		Create an etched border. The optional Color arguments specify the highlight and shadow colors to be used. In release 1.3, methods with int arguments were added that allow the border methods to be specified as either EtchedBorder.RAISED or EtchedBorder.LOWERED. The methods without the int arguments create a lowered etched border.
Border createLoweredBevelBorder() | Create a border that gives the illusion of the component being lower than the surrounding area.
Border createRaisedBevelBorder() | Create a border that gives the illusion of the component being higher than the surrounding area.

Border createBevelBorder(int, Color, Color)
Border createBevelBorder(int, Color, Color, Color, Color) 		Create a raised or lowered beveled border, specifying the colors to use. The integer argument can be either BevelBorder.RAISED or BevelBorder.LOWERED. With the three-argument constructor, you specify the highlight and shadow colors. With the five-argument constructor, you specify the outer highlight, inner highlight, outer shadow, and inner shadow colors, in that order.
Border createEmptyBorder()
Border createEmptyBorder(int, int, int, int) 		Create an invisible border. If you specify no arguments, then the border takes no space, which is useful when creating a titled border with no visible boundary. The optional arguments specify the number of pixels that the border occupies at the top, left, bottom, and right (in that order) of whatever component uses it. This method is useful for putting empty space around your components.
MatteBorder createMatteBorder(int, int, int, int, Color)
MatteBorder createMatteBorder(int, int, int, int, Icon) 		Create a matte border. The integer arguments specify the number of pixels that the border occupies at the top, left, bottom, and right (in that order) of whatever component uses it. The color argument specifies the color which with the border should fill its area. The icon argument specifies the icon which with the border should tile its area.
TitledBorder createTitledBorder(String)
TitledBorder createTitledBorder(Border)
TitledBorder createTitledBorder(Border, String)
TitledBorder createTitledBorder(Border, String, int, int)
TitledBorder createTitledBorder(Border, String, int, int, Font)
TitledBorder createTitledBorder(Border, String, int, int, Font, Color) 		Create a titled border. The string argument specifies the title to be displayed. The optional font and color arguments specify the font and color to be used for the title's text. The border argument specifies the border that should be displayed along with the title. If no border is specified, then a look-and-feel-specific default border is used.

By default, the title straddles the top of its companion border and is left-justified. The optional integer arguments specify the title's position and justification, in that order. TitledBorder defines these possible positions: ABOVE_TOP, TOP (the default), BELOW_TOP, ABOVE_BOTTOM, BOTTOM, and BELOW_BOTTOM. You can specify the justification as LEADING (the default), CENTER, or TRAILING. In locales with Western alphabets LEADING is equivalent to LEFT and TRAILING is equivalent to RIGHT.

CompoundBorder createCompoundBorder(Border, Border) 		Combine two borders into one. The first argument specifies the outer border; the second, the inner border.

Setting or Getting a Component's Border
Method Purpose
void setBorder(Border)
Border getBorder() 		Set or get the border of the receiving JComponent.
void setBorderPainted(boolean)
boolean isBorderPainted()
(in AbstractButton, JMenuBar, JPopupMenu, JProgressBar, and JToolBar) 		Set or get whether the border of the component should be displayed.

Examples that Use Borders

Many examples in this lesson use borders. The following table lists a few interesting cases.

Example | Where Described | Notes
BorderDemo | This section | Shows an example of each type of border that BorderFactory can create. Also uses an empty border to add breathing space between each pane and its contents.
BoxAlignmentDemo | How to Use BoxLayout | Uses titled borders.
BoxLayoutDemo | How to Use BoxLayout | Uses a red line to show where the edge of a container is, so that you can see how the extra space in a box layout is distributed.
ComboBoxDemo2 | How to Use Combo Boxes | Uses a compound border to combine a line border with an empty border. The empty border provides space between the line and the component's innards.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Icons
Next page: Solving Common Component Problems


Solving Common Component Problems (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
Solving Common Component Problems
This section discusses problems that you might encounter while using components. If you do not find your problem in this section, consult the following sections:
  • Solving Common Problems Using Other Swing Features
  • Solving Common Layout Problems
  • Solving Common Event-Handling Problems
  • Solving Common Painting Problems

Problem: I am having trouble implementing a model (or some other code that is similar to something already in Java SE Platform, Standard Edition).

  • Look at the Java SE source code. It is distributed with the JDK, and it is a great resource for finding code examples of implementing models, firing events, and the like.
Problem: Whenever the text in my text field updates, the text field's size changes.
  • You should specify the preferred width of the text field by specifying the number of columns it should have room to display. To do this, you can use either an int argument to the JTextField constructor or the setColumns method.
Problem: Certain areas of the content pane look weird when they are repainted.
  • If you set the content pane, make sure it is opaque. You can do this by invoking setOpaque(true) on your content pane. Note that although JPanels are opaque in most look and feels, that is not true in the GTK+ look and feel. See Adding Components to the Content Pane for details.
  • If one or more of your components performs custom painting, make sure you implemented it correctly. See Solving Common Painting Problems for help.
  • You might have a thread safety problem. See the next entry.

Problem: My program is exhibiting weird symptoms that sometimes seem to be related to timing.

  • Make sure your code is thread-safe. See Concurrency in Swing for details.

Problem: My modal dialog gets lost behind other windows.

  • If the dialog has a null parent component, try setting it to a valid frame or component when you create it.
  • This bug was fixed in the 6.0 release. For more information, see 4255200.

Problem: The scroll bar policies do not seem to be working as advertised.

  • Some Swing releases contain bugs in the implementations for the VERTICAL_SCROLLBAR_AS_NEEDED and the HORIZONTAL_SCROLLBAR_AS_NEEDED policies. If feasible for your project, use the most recent release of Swing.
  • If the scroll pane's client can change size dynamically, the program should set the client's preferred size and then call revalidate on the client.
  • Make sure you specified the policy you intended for the orientation you intended.
Problem: My scroll pane has no scroll bars.
  • If you want a scroll bar to appear all the time, specify either VERTICAL_SCROLLBAR_ALWAYS or HORIZONTAL_SCROLLBAR_ALWAYS for the scroll bar policy as appropriate.
  • If you want the scroll bars to appear as needed, and you want to force the scroll bars to be needed when the scroll pane is created, you have two choices: either set the preferred size of scroll pane or its container, or implement a scroll-savvy class and return a value smaller than the component's standard preferred size from the getPreferredScrollableViewportSize method. Refer to Sizing a Scroll Pane for information.
Problem: The divider in my split pane does not move!
  • You need to set the minimum size of at least one of the components in the split pane. Refer to Positioning the Divider and Restricting Its Range for information.
Problem: The setDividerLocation method of JSplitPane does not work.
  • The setDividerLocation(double) method has no effect if the split pane has no size (typically true if it is not onscreen yet). You can either use setDividerLocation(int) or specify the preferred sizes of the split pane's contained components and the split pane's resize weight instead. Refer to Positioning the Divider and Restricting Its Range for information.
Problem: The borders on nested split panes look too wide.
  • If you nest split panes, the borders accumulate — the border of the inner split panes display next to the border of the outer split pane causing borders that look extra wide. The problem is particularly noticeable when nesting many split panes. The workaround is to set the border to null on any split pane that is placed within another split pane. For information, see bug # 4131528 in the Bug Database at the Sun Developer Network (SDN).
Problem: The buttons in my tool bar are too big.
  • Try reducing the margin for the buttons. For example:
    button.setMargin(new Insets(0,0,0,0));
Problem: The components in my layered pane are not layered correctly. In fact, the layers seem to be inversed — the lower the depth the higher the component.
  • This can happen if you use an int instead of an Integer when adding components to a layered pane. To see what happens, make the following change to LayeredPaneDemo:

    Change this... | to this...
    layeredPane.add(label, new Integer(i)); | layeredPane.add(label, i);

Problem: The method call colorChooser.setPreviewPanel(null) does not remove the color chooser's preview panel as expected.

  • A null argument specifies the default preview panel. To remove the preview panel, specify a standard panel with no size, like this: colorChooser.setPreviewPanel(new JPanel());

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Borders
Next page: Questions and Exercises: Using Swing Components


Questions and Exercises: Using Swing Components (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Questions and Exercises: Using Swing Components

Use the information in this lesson and the component how-to sections to help you complete these questions and exercises.

Questions

1. Find the component that best fits each of the following needs. Write down both the component’s common name (such as “frame”) and find the component's how-to page online. [Hint: You can use A Visual Index to the Swing Components to help you answer this question.]

a. A component that lets the user pick a color.

b. A component that displays an icon, but that doesn’t react to user clicks.

c. A component that looks like a button and that, when pressed, brings up a menu of items for the user to choose from.

d. A container that looks like a frame, but that appears (usually with other, similar containers) within a real frame.

e. A container that lets the user determine how two components share a limited amount of space.

2. Which method do you use to add a menu bar to a top-level container such as a JFrame?

3. Which method do you use to specify the default button for a top-level container such as a JFrame or JDialog?

4. Which method do you use to enable and disable components such as JButtons? What class is it defined in?

5. a. Which Swing components use ListSelectionModel? [Hint: The “Use” link at the top of the specification for each interface and class takes you to a page showing where in the API that interface or class is referenced.]

b. Do those components use any other models to handle other aspects of the components’ state? If so, list the other models’ types.

6. Which type of model holds a text component’s content?

Exercises

1. Implement a program with a GUI that looks like the one shown below. Put the main method in a class named MyDemo1.

2. Make a copy of MyDemo1.java named MyDemo2.java. Add a menu bar to MyDemo2.

3. Copy MyDemo1.java to MyDemo3.java. Add a button (JButton) to MyDemo3.java. Make it the default button.

Check your answers.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Solving Common Component Problems
Next page: Concurrency in Swing


Lesson: Concurrency in Swing (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Concurrency in Swing
Initial Threads
The Event Dispatch Thread
Worker Threads and SwingWorker
Simple Background Tasks
Tasks that Have Interim Results
Canceling Background Tasks
Bound Properties and Status Methods
Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Lesson: Concurrency in Swing
Examples Index

This lesson discusses concurrency as it applies to Swing programming. It assumes that you are already familiar with the content of the Concurrency lesson in the Essential Classes trail.

Careful use of concurrency is particularly important to the Swing programmer. A well-written Swing program uses concurrency to create a user interface that never "freezes" — the program is always responsive to user interaction, no matter what it's doing. To create a responsive program, the programmer must learn how the Swing framework employs threads.

A Swing programmer deals with the following kinds of threads:

  • Initial threads, the threads that execute initial application code.
  • The event dispatch thread, where all event-handling code is executed. Most code that interacts with the Swing framework must also execute on this thread.
  • Worker threads, also known as background threads, where time-consuming background tasks are executed.
The programmer does not need to provide code that explicitly creates these threads: they are provided by the runtime or the Swing framework. The programmer's job is to utilize these threads to create a responsive, maintainable Swing program.

Like any other program running on the Java platform, a Swing program can create additional threads and thread pools, using the tools described in the Concurrency lesson. But for basic Swing programs the threads described here are sufficient.

This lesson discuss each of the three kinds of threads in turn. Worker threads require the most discussion because tasks that run on them are created using javax.swing.SwingWorker. This class has many useful features, including communication and coordination between worker thread tasks and the tasks on other threads.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Initial Threads


Initial Threads (The Java™ Tutorials > Creating a GUI with JFC/Swing > Concurrency in Swing)

Trail: Creating a GUI with JFC/Swing
Lesson: Concurrency in Swing
Concurrency in Swing
Initial Threads
The Event Dispatch Thread
Worker Threads and SwingWorker
Simple Background Tasks
Tasks that Have Interim Results
Canceling Background Tasks
Bound Properties and Status Methods
Home Page > Creating a GUI with JFC/Swing > Concurrency in Swing
« Previous • Trail • Next »
Initial Threads
Every program has a set of threads where the application logic begins. In standard programs, there's only one such thread: the thread that invokes the main method of the program class. In applets the initial threads are the ones that construct the applet object and invoke its init and start methods; these actions may occur on a single thread, or on two or three different threads, depending on the Java platform implementation. In this lesson, we call these threads the initial threads.

In Swing programs, the initial threads don't have a lot to do. Their most essential job is to create a Runnable object that initializes the GUI and schedule that object for execution on the event dispatch thread. Once the GUI is created, the program is primarily driven by GUI events, each of which causes the execution of a short task on the event dispatch thread. Application code can schedule additionals tasks on the event dispatch thread (if they complete quickly, so as not to interfere with event processing) or a worker thread (for long-running tasks).

An initial thread schedules the GUI creation task by invoking javax.swing.SwingUtilities.invokeLater or javax.swing.SwingUtilities.invokeAndWait . Both of these methods take a single argument: the Runnable that defines the new task. Their only difference is indicated by their names: invokeLater simply schedules the task and returns; invokeAndWait waits for the task to finish before returning.

You can see examples of this throughout the Swing tutorial:

SwingUtilities.invokeLater(new Runnable() {
    public void run() {
        createAndShowGUI();
    }
}
In an applet, the GUI-creation task must be launched from the init method using invokeAndWait; otherwise, init may return before the GUI is created, which may cause problems for a web browser launching an applet. In any other kind of program, scheduling the GUI-creation task is usually the last thing the initial thread does, so it doesn't matter whether it uses invokeLater or invokeAndWait.

Why does not the initial thread simply create the GUI itself? Because almost all code that creates or interacts with Swing components must run on the event dispatch thread. This restriction is discussed further in the next section.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Concurrency in Swing
Next page: The Event Dispatch Thread


The Event Dispatch Thread (The Java™ Tutorials > Creating a GUI with JFC/Swing > Concurrency in Swing)

Trail: Creating a GUI with JFC/Swing
Lesson: Concurrency in Swing
Concurrency in Swing
Initial Threads
The Event Dispatch Thread
Worker Threads and SwingWorker
Simple Background Tasks
Tasks that Have Interim Results
Canceling Background Tasks
Bound Properties and Status Methods
Home Page > Creating a GUI with JFC/Swing > Concurrency in Swing
« Previous • Trail • Next »
The Event Dispatch Thread
Swing event handling code runs on a special thread known as the event dispatch thread. Most code that invokes Swing methods also runs on this thread. This is necessary because most Swing object methods are not "thread safe": invoking them from multiple threads risks thread interference or memory consistency errors. Some Swing component methods are labelled "thread safe" in the API specification; these can be safely invoked from any thread. All other Swing component methods must be invoked from the event dispatch thread. Programs that ignore this rule may function correctly most of the time, but are subject to unpredictable errors that are difficult to reproduce.
A note on thread safety: It may seem strange that such an important part of the Java platform is not thread safe. It turns out that any attempt to create a thread-safe GUI library faces some fundamental problems. For more on this issue, see the following entry in Graham Hamilton's blog: MultiThreaded toolkits: A failed dream?
It's useful to think of the code running on the event dispatch thread as a series of short tasks. Most tasks are invocations of event-handling methods, such as ActionListener.actionPerformed. Other tasks can be scheduled by application code, using invokeLater or invokeAndWait. Tasks on the event dispatch thread must finish quickly; if they don't, unhandled events back up and the user interface becomes unresponsive.

If you need to determine whether your code is running on the event dispatch thread, invoke javax.swing.SwingUtilities.isEventDispatchThread.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Initial Threads
Next page: Worker Threads and SwingWorker


Worker Threads and SwingWorker (The Java™ Tutorials > Creating a GUI with JFC/Swing > Concurrency in Swing)

Trail: Creating a GUI with JFC/Swing
Lesson: Concurrency in Swing
Concurrency in Swing
Initial Threads
The Event Dispatch Thread
Worker Threads and SwingWorker
Simple Background Tasks
Tasks that Have Interim Results
Canceling Background Tasks
Bound Properties and Status Methods
Home Page > Creating a GUI with JFC/Swing > Concurrency in Swing
« Previous • Trail • Next »
Worker Threads and SwingWorker
When a Swing program needs to execute a long-running task, it usually uses one of the worker threads, also known as the background threads. Each task running on a worker thread is represented by an instance of javax.swing.SwingWorker. SwingWorker itself is an abstract class; you must define a subclass in order to create a SwingWorker object; anonymous inner classes are often useful for creating very simple SwingWorker objects.

SwingWorker provides a number of communication and control features:

  • The SwingWorker subclass can define a method, done, which is automatically invoked on the event dispatch thread when the background task is finished.
  • SwingWorker implements java.util.concurrent.Future. This interface allows the background task to provide a return value to the other thread. Other methods in this interface allow cancellation of the background task and discovering whether the background task has finished or been cancelled.
  • The background task can provide intermediate results by invoking SwingWorker.publish, causing SwingWorker.process to be invoked from the event dispatch thread.
  • The background task can define bound properties. Changes to these properties trigger events, causing event-handling methods to be invoked on the event dispatch thread.
These features are discussed in the following subsections.
Note: The javax.swing.SwingWorker class was added to the Java platform in Java SE 6. Prior to this, another class, also called SwingWorker, was widely used for some of the same purposes. The old SwingWorker was not part of the Java platform specification, and was not provided as part of the JDK.

The new javax.swing.SwingWorker is a completly new class. Its functionality is not a strict superset of the old SwingWorker. Methods in the two classes that have the same function do not have the same names. Also, instances of the old SwingWorker class were reusable, while a new instance of javax.swing.SwingWorker is needed for each new background task.

Throughout the Java Tutorials, any mention of SwingWorker now refers to javax.swing.SwingWorker.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Event Dispatch Thread
Next page: Simple Background Tasks


Simple Background Tasks (The Java™ Tutorials > Creating a GUI with JFC/Swing > Concurrency in Swing)

Trail: Creating a GUI with JFC/Swing
Lesson: Concurrency in Swing
Section: Worker Threads and SwingWorker
Concurrency in Swing
Initial Threads
The Event Dispatch Thread
Worker Threads and SwingWorker
Simple Background Tasks
Tasks that Have Interim Results
Canceling Background Tasks
Bound Properties and Status Methods
Home Page > Creating a GUI with JFC/Swing > Concurrency in Swing
« Previous • Trail • Next »
Simple Background Tasks
Let's start with a task that is very simple, but potentially time-consuming. The TumbleItem applet loads a set of graphic files used in an animation. If the graphic files are loaded from an initial thread, there may be a delay before the GUI appears. If the graphic files are loaded from the event dispatch thread, the GUI may be temporarily unresponsive.

To avoid these problems, TumbleItem creates and executes an instance of SwingWorker from its initial threads. The object's doInBackground method, executing in a worker thread, loads the images into an ImageIcon array, and returns a reference to it. Then the done method, executing in the event dispatch thread, invokes get to retrieve this reference, which it assigns to to an applet class field named imgs This allows TumbleItem to contruct the GUI immediately, without waiting for the images to finish loading.

Here is the code that defines and executes the SwingWorker object.

SwingWorker worker = new SwingWorker<ImageIcon[], Void>() {
    @Override
    public ImageIcon[] doInBackground() {
        final ImageIcon[] innerImgs = new ImageIcon[nimgs];
        for (int i = 0; i < nimgs; i++) {
            innerImgs[i] = loadImage(i+1);
        }
        return innerImgs;
    }

    @Override
    public void done() {
        //Remove the "Loading images" label.
        animator.removeAll();
        loopslot = -1;
        try {
            imgs = get();
        } catch (InterruptedException ignore) {}
        catch (java.util.concurrent.ExecutionException e) {
            String why = null;
            Throwable cause = e.getCause();
            if (cause != null) {
                why = cause.getMessage();
            } else {
                why = e.getMessage();
            }
            System.err.println("Error retrieving file: " + why);
        }
    }
};
All concrete subclasses of SwingWorker implement doInBackground; implementation of done is optional.

Notice that SwingWorker is a generic class, with two type parameters. The first type parameter specifies a return type for doInBackground, and also for the get method, which is invoked by other threads to retrieve the object returned by doInBackground. SwingWorker's second type parameter specifies a type for interim results returned while the background task is still active. Since this example doesn't return interim results, Void is used as a placeholder.

You may wonder if the code that sets imgs is unnecessarily complicated. Why make doInBackground return an object and use done to retrieve it? Why not just have doInBackground set imgs directly? The problem is that the object imgs refers to is created in the worker thread and used in the event dispatch thread. When objects are shared between threads in this way, you must make sure that changes made in one thread are visible to the other. Using get guarantees this, because using get creates a happens before relationship between the code that creates imgs and the code that uses it. For more on the happens before relationship, refer to Memory Consistency Errors in the Concurrency lesson.

There are actually two ways to retrieve the object returned by doInBackground.

  • Invoke SwingWorker.get with no arguments. If the background task is not finished, get blocks until it is.
  • Invoke SwingWorker.get with arguments indicating a timeout. If the background task is not finished, get blocks until it is — unless the timeout expires first, in which case get throws java.util.concurrent.TimeoutException.
Be careful when invoking either overload of get from the event dispatch thread; until get returns, no GUI events are being processed, and the GUI is "frozen". Don't invoke get without arguments unless you are confident that the background task is complete or close to completion.

For more on the TumbleItem example, refer to How to Use Swing Timers in the lesson Using Other Swing Features.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Worker Threads and SwingWorker
Next page: Tasks that Have Interim Results


Tasks that Have Interim Results (The Java™ Tutorials > Creating a GUI with JFC/Swing > Concurrency in Swing)

Trail: Creating a GUI with JFC/Swing
Lesson: Concurrency in Swing
Section: Worker Threads and SwingWorker
Concurrency in Swing
Initial Threads
The Event Dispatch Thread
Worker Threads and SwingWorker
Simple Background Tasks
Tasks that Have Interim Results
Canceling Background Tasks
Bound Properties and Status Methods
Home Page > Creating a GUI with JFC/Swing > Concurrency in Swing
« Previous • Trail • Next »
Tasks that Have Interim Results
It is often useful for a background task to provide interim results while it is still working. The task can do this by invoking SwingWorker.publish. This method accepts a variable number of arguments. Each argument must be of the type specified by SwingWorker's second type parameter.

To collect results provided by publish, override SwingWorker.process This method will be invoked from the event dispatch thread. Results from multiple invocations of publish are often accumulated for a single invocation of process.

Let's look at the way the Flipper.java example uses publish to provide interim results. Click the Launch button to run Flipper using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

Launches the Flipper example

This program tests the fairness of java.util.Random by generating a series of random boolean values in a background task. This is equivalent to flipping a coin; hence the name Flipper. To report its results, the background task uses an object of type FlipPair

private static class FlipPair {
    private final long heads, total;
    FlipPair(long heads, long total) {
        this.heads = heads;
        this.total = total;
    }
}
The heads field is the number of times the random value has been true; the total field is the total number of random values.

The background task is represented by an instance of FlipTask:

private class FlipTask extends SwingWorker<Void, FlipPair> {
Since the task does not return a final result, it does not matter what the first type parameter is; Void is used as a placeholder. The task invokes publish after each "coin flip":
@Override
protected Void doInBackground() {
    long heads = 0;
    long total = 0;
    Random random = new Random();
    while (!isCancelled()) {
        total++;
        if (random.nextBoolean()) {
            heads++;
        }
        publish(new FlipPair(heads, total));
    }
    return null;
}
(The isCancelled method is discussed in the next section.) Because publish is invoked very frequently, a lot of FlipPair values will probably be accumulated before process is invoked in the event dispatch thread; process is only interested in the last value reported each time, using it to update the GUI:
protected void process(List pairs) {
    FlipPair pair = pairs.get(pairs.size() - 1);
    headsText.setText(String.format("%d", pair.heads));
    totalText.setText(String.format("%d", pair.total));
    devText.setText(String.format("%.10g",
            ((double) pair.heads)/((double) pair.total) - 0.5));
}
If Random is fair, the value displayed in devText should get closer and closer to 0 as Flipper runs.
Note: The setText method used in Flipper is actually "thread safe" as defined in its specification. That means that we could dispense with publish and process and set the text fields directly from the worker thread. We've chosen to ignore this fact in order to provide a simple demonstration of SwingWorker interim results.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Simple Background Tasks
Next page: Canceling Background Tasks


Canceling Background Tasks (The Java™ Tutorials > Creating a GUI with JFC/Swing > Concurrency in Swing)

Trail: Creating a GUI with JFC/Swing
Lesson: Concurrency in Swing
Section: Worker Threads and SwingWorker
Concurrency in Swing
Initial Threads
The Event Dispatch Thread
Worker Threads and SwingWorker
Simple Background Tasks
Tasks that Have Interim Results
Canceling Background Tasks
Bound Properties and Status Methods
Home Page > Creating a GUI with JFC/Swing > Concurrency in Swing
« Previous • Trail • Next »
Canceling Background Tasks
To cancel a running background task, invoke SwingWorker.cancel The task must cooperate with its own cancellation. There are two ways it can do this:
  • By terminating when it receives an interrupt. This procedures is described in Interrupts in Concurrency.
  • By invoking SwingWorker.isCanceled at short intervals. This method returns true if cancel has been invoked for this SwingWorker.

The cancel method takes a single boolean argument. If the argument is true, cancel sends the background task an interrupt. Whether the argument is true or false, invoking cancel changes the cancellation status of the object to true. This is the value returned by isCanceled. Once changed, the cancellation status cannot be changed back.

The Flipper example from the previous section uses the status-only idiom. The main loop in doInBackground exits when isCancelled returns true. This will occur when the user clicks the "Cancel" button, triggering code that invokes cancel with an argument of false.

The status-only approach makes sense for Flipper because its implementation of SwingWorker.doInBackground does not include any code that might throw InterruptedException. To respond to an interrupt, the background task would have to invoke Thread.isInterrupted at short intervals. It's just as easy to use SwingWorker.isCancelled for the same purpose

Note: If get is invoked on a SwingWorker object after its background task has been cancelled, java.util.concurrent.CancellationException is thrown.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Tasks that Have Interim Results
Next page: Bound Properties and Status Methods


Bound Properties and Status Methods (The Java™ Tutorials > Creating a GUI with JFC/Swing > Concurrency in Swing)

Trail: Creating a GUI with JFC/Swing
Lesson: Concurrency in Swing
Section: Worker Threads and SwingWorker
Concurrency in Swing
Initial Threads
The Event Dispatch Thread
Worker Threads and SwingWorker
Simple Background Tasks
Tasks that Have Interim Results
Canceling Background Tasks
Bound Properties and Status Methods
Home Page > Creating a GUI with JFC/Swing > Concurrency in Swing
« Previous • Trail • Next »
Bound Properties and Status Methods
SwingWorker supports bound properties, which are useful for communicating with other threads. Two bound properties are predefined: progress and state. As with all bound properties, progress and state can be used to trigger event-handling tasks on the event dispatch thread.

By implementing a property change listener, a program can track changes to progress, state, and other bound properties. For more information, refer to How to Write a Property Change Listener in Writing Event Listeners.

The progress Bound Variable

The progress bound variable is an int value that can range from 0 to 100. It has a predefined setter method (the protected SwingWorker.setProgress) and a predefined getter method (the public SwingWorker.getProgress).

The ProgressBarDemo example uses progress to update a ProgressBar control from a background task. For a detailed discussion of this example, refer to How to Use Progress Bars in Using Swing Components.

The state Bound Variable

The state bound variable indicates where the SwingWorker object is in its lifecycle. The bound variable contains an enumeration value of type SwingWorker.StateValue. Possible values are:
PENDING
The state during the period from the construction of the object until just before doInBackground is invoked.
STARTED
The state during the period from shortly before doInBackground is invoked until shortly before done is invoked. DONE
The state for the remainder of the existence of the object.
The current value of the state bound variable is returned by SwingWorker.getState.

Status Methods

Two methods, part of the Future interface, also report on the status of the background task. As we saw in Canceling Background Tasks, isCancelled returns true if the task has been canceled. In addition, isDone returns true if the task has finished, either normally, or by being cancelled.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Canceling Background Tasks
Next page: Questions and Exercises: Concurrency in Swing


Questions and Exercises: Concurrency in Swing (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Questions and Exercises: Concurrency in Swing

Questions

  1. For each of the following tasks, specify which thread it should be executed in and why.
    • Initializing the GUI.
    • Loading a large file.
    • Invoking javax.swing.JComponent.setFont to change the font of a component.
    • Invoking javax.swing.text.JTextComponent.setText to change the text of a component.
  2. One set of threads is not used for any of the tasks mentioned in the previous question. Name this thread and explain why its applications are so limited.
  3. SwingWorker has two type parameters. Explain how these type parameters are used, and why it often doesn't matter what they are.

Exercises

  1. Modify the Flipper example so that it pauses 5 seconds between "coin flips." If the user clicks the "Cancel", the coin-flipping loop terminates immediately.
Check your answers.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Bound Properties and Status Methods
Next page: Using Other Swing Features


Lesson: Using Other Swing Features (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Lesson: Using Other Swing Features
Examples Index

This lesson contains a collection of how-to pages to help you use miscellaneous Swing features.

How to Integrate with the Desktop Class

With the Desktop class you can enable your Java application to interact with default applications associated with specific file types on the host platform.

How to Use Actions

With Action objects, you can coordinate the state and event handling of two or more components that generate action events. For example, you can use a single Action to create and coordinate a tool-bar button and a menu item that perform the same function.

How to Use Swing Timers

With the Swing Timer class, you can implement a thread that performs an action after a delay, and optionally continues to repeat the action. The action executes in the event dispatch thread.

How to Support Assistive Technologies

Swing components have built-in support for assistive technologies. Your program can provide even better support by following a few rules.

How to Use the Focus Subsystem

Some programs need to manipulate focus — for example, to validate input, or change the tab-order of components. This section describes some techniques you can use to customize focus in your program.

How to Use Key Bindings

With key bindings, you can specify how components react to user typing.

How to Use Modality in Dialogs

This section describes a new modality model emerged in the Java™ SE version 6 and enables you to apply different modality types to dialog boxes.

How to Print Tables

This section describes the printing capabilities for tables and explains how to add printing support to your programs.

How to Print Text

This section describes the printing capabilities for text components and explains how to add printing support to your programs.

How to Create a Splash Screen

With the SplashScreen class you can close the splash screen, change the splash-screen image, obtain the image position or size, and paint in the splash screen.

How to Use the System Tray

This section describes how to add a tray icon to the system tray and apply a text tooltip, a pop-up menu, ballon messages, and a set of listeners associated with it.

Solving Common Problems Using Other Swing Features

This section tells you how to fix problems you might encounter while trying to use the information in this lesson.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: How to Integrate with the Desktop Class


How to Integrate with the Desktop Class (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Other Swing Features)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Other Swing Features
Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Home Page > Creating a GUI with JFC/Swing > Using Other Swing Features
« Previous • Trail • Next »
How to Integrate with the Desktop Class

Java™ Standard Edition version 6 narrows the gap between performance and integration of native applications and Java applications. Along with the new system tray fuctionality, splash screen support, and enhanced printing for JTables , Java SE version 6 provides the Desktop API (java.awt.Desktop) API, which allows Java applications to interact with default applications associated with specific file types on the host platform.

New functionality is provided by the Desktop class. The API arises from the JDesktop Integration Components (JDIC) project. The goal of the JDIC project is to make "Java technology-based applications first-class citizens" of the desktop, enabling seamless integration. JDIC provides Java applications with access to functionalities and facilities provided by the native desktop. Regarding the new Desktop API, this means that a Java application can perform the following operations:

  • Launch the host system's default browser with a specific Uniform Resource Identifier (URI)
  • Launch the host system's default email client
  • Launch applications to open, edit, or print files associated with those applications

Note: The Desktop API uses the host operating system's file associations to launch applications associated with specific file types. For example, if OpenDocument text (.odt) file extensions are associated with the OpenOffice Writer application, a Java application could launch OpenOffice Writer to open, edit, or even print files with that association. Depending on the host system, different applications may be associated with different actions. For example, if a particular file cannot be printed, check first whether its extension has a printing association on the given operating system.

Use the isDesktopSupported() method to determine whether the Desktop API is available. On the Solaris Operating System and the Linux platform, this API is dependent on Gnome libraries. If those libraries are unavailable, this method will return false. After determining that the Desktop API is supported, that is, the isDesktopSupported() returns true, the application can retrieve a Desktop instance using the static method getDesktop() .

If an application runs in an environment without a keyboard, mouse, or monitor (a "headless" environment), the getDesktop() method will throw a java.awt.HeadlessException.

Once retrieved, the Desktop instance allows an application to browse, mail, open, edit, or even print a file or URI, but only if the retrieved Desktop instance supports these activities. Each of these activities is called an action, and each is represented as a Desktop.Action enumeration instance:

  • BROWSE — Represents a browse action performed by the host's default browser.
  • MAIL — Represents a mail action performed by the host's default email client.
  • OPEN — Represents an open action performed by an application associated with opening a specific file type.
  • EDIT — Represents an edit action performed by an application associated with editing a specific file type
  • PRINT — Represents a print action performed by an application associated with printing a specific file type.
Different applications may be registered for these different actions even on the same file type. For example, the Firefox browser may be launched for the OPEN action, Emacs for the EDIT action, and yet a different application for the PRINT action. Your host desktop's associations are used to determine which application should be invoked. The ability to manipulate desktop file associations is not possible with the current version of the Desktop API in JDK 6, and those associations can be created or changed only with platform-dependent tools at this time.

The following example shows the capabilities mentioned above.

Try this:
  1. Compile and run the example, consult the example index.
  2. The DesktopDemo dialog box will appear.

  3. Enter an URI value into the URI text field, for example &ndash http://java.sun.com/docs/books/tutorial.
  4. Press the Launch Browser button.
  5. Ensure that the default browser window opens and the Tutorial main page is loaded.
  6. Change URI to an arbitrary value, press the Launch Browser button, and ensure that the web page you requested is loaded successfully.
  7. Switch back to the DesktopDemo dialog box and enter a mail recipient name in the E-mail text field. You can also use the mailto scheme supporting CC, BCC, SUBJECT, and BODY fields, for example – duke@sun.com?SUBJECT=Hello Duke!.
  8. Press the Launch Mail button.
  9. The compositing dialog box of the default email client will appear. Be sure that the To and Subject fields are as follows.

  10. You can continue to compose a message or try to enter different combinations of the mail schema in the E-mail field.
  11. Switch back to the DesktopDemo dialog box and press the ellipsis button to choose any text file.
  12. Select either Open, Edit, or Print to set the type of operation, then press the Launch Application button.
  13. Be sure that operation completes correctly. Try other file formats, for example .odt, .html, .pdf. Note: If you try to edit .pdf file, the DesktopDemo returns the following message:
    14. Cannot perform the given operation to the < file name> file

The following code snippets provide more details on the DeskDemo application implementation. The DesktopDemo constructor disables the few components right after instantiating the UI and checks whether the Desktop API is available.

 public DesktopDemo() {
        // init all gui components
        initComponents();
        // disable buttons that launch browser, email client,
        // disable buttons that open, edit, print files
        disableActions();
        // before any Desktop APIs are used, first check whether the API is
        // supported by this particular VM on this particular host
        if (Desktop.isDesktopSupported()) {
            desktop = Desktop.getDesktop();
            // now enable buttons for actions that are supported.
            enableSupportedActions();
        }
    ...

    /**
     * Disable all graphical components until we know
     * whether their functionality is supported.
     */
    private void disableActions() {
        txtBrowserURI.setEnabled(false);
        btnLaunchBrowser.setEnabled(false);

        txtMailTo.setEnabled(false);
        btnLaunchEmail.setEnabled(false);

        rbEdit.setEnabled(false);
        rbOpen.setEnabled(false);
        rbPrint.setEnabled(false);

        txtFile.setEnabled(false);
        btnLaunchApplication.setEnabled(false);
    }

   ...

Once a Desktop object is acquired, you can query the object to find out which specific actions are supported. If the Desktop object does not support specific actions, or if the Desktop API itself is unsupported, DesktopDemo simply keeps the affected graphical components disabled.

/**
     * Enable actions that are supported on this host.
     * The actions are the following: open browser,
     * open email client, and open, edit, and print
     * files using their associated application.
     */
    private void enableSupportedActions() {
        if (desktop.isSupported(Desktop.Action.BROWSE)) {
            txtBrowserURI.setEnabled(true);
            btnLaunchBrowser.setEnabled(true);
        }

        if (desktop.isSupported(Desktop.Action.MAIL)) {
            txtMailTo.setEnabled(true);
            btnLaunchEmail.setEnabled(true);
        }

        if (desktop.isSupported(Desktop.Action.OPEN)) {
            rbOpen.setEnabled(true);
        }
        if (desktop.isSupported(Desktop.Action.EDIT)) {
            rbEdit.setEnabled(true);
        }
        if (desktop.isSupported(Desktop.Action.PRINT)) {
            rbPrint.setEnabled(true);
        }

        if (rbEdit.isEnabled() || rbOpen.isEnabled() || rbPrint.isEnabled()) {
            txtFile.setEnabled(true);
            btnLaunchApplication.setEnabled(true);
        }
    }
The browse(uri) method can throw a variety of exceptions, including a NullPointerException if the URI is null, and an UnsupportedOperationException if the BROWSE action is unsupported. This method can throw an IOException if the default browser or application cannot be found or launched, and a SecurityException if a security manager denies the invocation.
private void onLaunchBrowser(ActionEvent evt) {
        URI uri = null;
        try {
            uri = new URI(txtBrowserURI.getText());
            desktop.browse(uri);
        } catch(IOException ioe) {
            System.out.println("The system cannot find the " + uri +
            " file specified");
            //ioe.printStackTrace();
        } catch(URISyntaxException use) {
            System.out.println("Illegal character in path");
            //use.printStackTrace();
        }
    }
Applications can launch the host's default email client, if that action is supported, by calling the mail(uriMailTo) method of this Desktop instance.
private void onLaunchMail(ActionEvent evt) {
        String mailTo = txtMailTo.getText();
        URI uriMailTo = null;
        try {
            if (mailTo.length() > 0) {
                uriMailTo = new URI("mailto", mailTo, null);
                desktop.mail(uriMailTo);
            } else {
                desktop.mail();
            }
        } catch(IOException ioe) {
            ioe.printStackTrace();
        } catch(URISyntaxException use) {
            use.printStackTrace();
        }
    }
Java applications can open, edit, and print files from their associated application using the open(), edit(), and print() methods of the Desktop class, respectively.
private void onLaunchDefaultApplication(ActionEvent evt) {
        String fileName = txtFile.getText();
        File file = new File(fileName);

        try {
            switch(action) {
                case OPEN:
                    desktop.open(file);
                    break;
                case EDIT:
                    desktop.edit(file);
                    break;
                case PRINT:
                    desktop.print(file);
                    break;
            }
        } catch (IOException ioe) {
            //ioe.printStackTrace();
            System.out.println("Cannot perform the given operation
            to the " + file + " file");
        }
    }

The complete code for this demo is available in the DesktopDemo.java file.

The Desktop API

The Desktop class allows Java applications to launch the native desktop applications that handle URIs or files.

Method | Purpose
isDesktopSupported() | Tests whether this class is supported on the current platform. If it is supported, use getDesktop() to retrieve an instance.
getDesktop() | Returns the Desktop instance of the current browser context. On some platforms the Desktop API may not be supported. Use the isDesktopSupported() method to determine if the current desktop is supported.
isSupported(Desktop.Action) | Tests whether an action is supported on the current platform. Use the following constans of the Desktop.Action enum: BROWSE, EDIT, MAIL, OPEN, PRINT.
browse(URI) | Launches the default browser to display a URI. If the default browser is not able to handle the specified URI, the application registered for handling URIs of the specified type is invoked. The application is determined from the protocol and path of the URI, as defined by the URI class.
mail(URI) | Launches the mail composing window of the user default mail client, filling the message fields specified by a mailto: URI.
open(File) | Launches the associated application to open a file.
edit(File) | Launches the associated editor application and opens a file for editing.
print(File) | Prints a file with the native desktop printing facility, using the associated application's print command.

Examples That Use Desktop API

The following table lists the example that uses the Desktop class integration.

Example | Where Described | Notes
DesktopDemo | This section | Launches the host system's default browser with the specified URI and default email client; launches an application to open, edit, or print a file.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Other Swing Features
Next page: How to Use Actions


How to Use Actions (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Other Swing Features)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Other Swing Features
Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Home Page > Creating a GUI with JFC/Swing > Using Other Swing Features
« Previous • Trail • Next »
How to Use Actions

An Action can be used to separate functionality and state from a component. For example, if you have two or more components that perform the same function, consider using an Action object to implement the function. An Action object is an action listener that provides not only action-event handling, but also centralized handling of the state of action-event-firing components such as tool bar buttons, menu items, common buttons, and text fields. The state that an action can handle includes text, icon, mnemonic, enabled, and selected status.

You typically attach an action to a component using the setAction method. Here's what happens when setAction is invoked on a component:

  • The component's state is updated to match the state of the Action. For example, if the Action's text and icon values were set, the component's text and icon are set to those values.
  • The Action object is registered as an action listener on the component.
  • If the state of the Action changes, the component's state is updated to match the Action. For example, if you change the enabled status of the action, all components it's attached to change their enabled states to match the action.

Here's an example of creating a tool-bar button and menu item that perform the same function:

Action leftAction = new LeftAction(); //LeftAction code is shown later
...
button = new JButton(leftAction)
...
menuItem = new JMenuItem(leftAction);

To create an Action object, you generally create a subclass of AbstractAction and then instantiate it. In your subclass, you must implement the actionPerformed method to react appropriately when the action event occurs. Here's an example of creating and instantiating an AbstractAction subclass:

leftAction = new LeftAction("Go left", anIcon,
             "This is the left button.",
             new Integer(KeyEvent.VK_L));
...
class LeftAction extends AbstractAction {
    public LeftAction(String text, ImageIcon icon,
                      String desc, Integer mnemonic) {
        super(text, icon);
        putValue(SHORT_DESCRIPTION, desc);
        putValue(MNEMONIC_KEY, mnemonic);
    }
    public void actionPerformed(ActionEvent e) {
        displayResult("Action for first button/menu item", e);
    }
}

When the action created by the preceding code is attached to a button and a menu item, the button and menu item display the text and icon associated with the action. The L character is used for mnemonics on the button and menu item, and their tool-tip text is set to the SHORT_DESCRIPTION string followed by a representation of the mnemonic key.

For example, we have provided a simple example, ActionDemo.java, which defines three actions. Each action is attached to a button and a menu item. Thanks to the mnemonic values set for each button's action, the key sequence Alt-L activates the left button, Alt-M the middle button, and Alt-R the right button. The tool tip for the left button displays This is the left button. Alt-L. All of this configuration occurs automatically, without the program making explicit calls to set the mnemonic or tool-tip text. As we'll show later, the program does make calls to set the button text, but only to avoid using the values already set by the actions.

A snapshot of ActionDemo, which uses actions to coordinate menus and buttons.

Try this:

  1. Click the Launch button to run ActionDemo using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

    Launches the ActionDemo example

  2. Choose the top item from the left menu (Menu > Go left).
    The text area displays some text identifying both the event source and the action listener that received the event.

  3. Click the leftmost button in the tool bar.
    The text area again displays information about the event. Note that although the source of the events is different, both events were detected by the same action listener: the Action object attached to the components.

  4. Choose the top item from the Action State menu.
    This disables the "Go left" Action object, which in turn disables its associated menu item and button.

Here is what the user sees when the "Go left" action is disabled:

A snapshot of ActionDemo when

A snapshot of ActionDemo when

Here's the code that disables the "Go left" action:

boolean selected = ...//true if the action should be enabled;
                      //false, otherwise
leftAction.setEnabled(selected);
After you create components using an Action, you might well need to customize them. For example, you might want to customize the appearance of one of the components by adding or deleting the icon or text. For example, ActionDemo.java has no icons in its menus, and no text in its buttons. Here's the code that accomplishes this:
menuItem = new JMenuItem();
menuItem.setAction(leftAction);
menuItem.setIcon(null); //arbitrarily chose not to use icon in menu
...
button = new JButton();
button.setAction(leftAction);
button.setText(""); //an icon-only button

We chose to create an icon-only button and a text-only menu item from the same action by setting the icon property to null and the text to an empty string. However, if a property of the Action changes, the widget may try to reset the icon and text from the Action again.

The Action API

The following tables list the commonly used Action constructors and methods. The API for using Action objects falls into three categories:
  • Components that Support set/getAction
  • Creating and Using an AbstractAction
  • Action Properties

Components that Support set/getAction
Class Purpose
AbstractButton
JComboBox
JTextField 		These components and their subclasses may have an action directly assigned to them via setAction. For further information about components that are often associated with actions, see the sections on tool bar buttons, menu items, common buttons, and text fields. For details on which properties each component takes from the Action, see the API documentation for the relevant class's configurePropertiesFromAction method. Also refer to the buttonActions table.

Creating and Using an AbstractAction
Constructor or Method Purpose
AbstractAction()
AbstractAction(String)
AbstractAction(String, Icon) 		Create an Action object. Through arguments, you can specify the text and icon to be used in the components that the action is attached to.
void setEnabled(boolean)
boolean isEnabled() 		Set or get whether the components the action controls are enabled. Invoking setEnabled(false) disables all the components that the action controls. Similarly, invoking setEnabled(true) enables the action's components.
void putValue(String, Object)
Object getValue(String) 		Set or get an object associated with a specified key. Used for setting and getting properties associated with an action.

Action Properties

This table defines the properties that can be set on an action. The second column lists which components automatically use the properties (and what method is specifically called). For example, setting the ACCELERATOR_KEY on an action that is then attached to a menu item, means that JMenuItem.setAccelerator(KeyStroke) is called automatically.

Property Auto-Applied to:
Class
(Method Called) 		Purpose
ACCELERATOR_KEY JMenuItem
(setAccelerator) 		The KeyStroke to be used as the accelerator for the action. For a discussion of accelerators versus mnemonics, see Enabling Keyboard Operation. Introduced in 1.3.
ACTION_COMMAND_KEY AbstractButton, JCheckBox, JRadioButton
(setActionCommand) 		The command string associated with the ActionEvent.
LONG_DESCRIPTION None The longer description for the action. Can be used for context-sensitive help.
MNEMONIC_KEY AbstractButton, JMenuItem, JCheckBox, JRadioButton
(setMnemonic) 		The mnemonic for the action. For a discussion of accelerators versus mnemonics, see Enabling Keyboard Operation. Introduced in 1.3.
NAME AbstractButton, JMenuItem, JCheckBox, JRadioButton
(setText) 		The name of the action. You can set this property when creating the action using the AbstractAction(String) or AbstractAction(String, Icon) constructors.
SHORT_DESCRIPTION AbstractButton, JCheckBox, JRadioButton
(setToolTipText) 		The short description of the action.
SMALL_ICON AbstractButton, JMenuItem
(setIcon) 		The icon for the action used in the tool bar or on a button. You can set this property when creating the action using the AbstractAction(name, icon) constructor.

Examples that Use Actions

The following examples use Action objects.

Example | Where Described | Notes
ActionDemo | This section | Uses actions to bind buttons and menu items to the same function.
TextComponentDemo | Text Component Features | Uses text actions to create menu items for text editing commands, such as cut, copy, and paste, and to bind key strokes to caret movement. Also implements custom AbstractAction subclasses to implement undo and redo. The text action discussion begins in Concepts: About Editor Kits.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Integrate with the Desktop Class
Next page: How to Use Swing Timers


How to Use Swing Timers (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Other Swing Features)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Other Swing Features
Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Home Page > Creating a GUI with JFC/Swing > Using Other Swing Features
« Previous • Trail • Next »
How to Use Swing Timers
A Swing timer (an instance of javax.swing.Timer) fires one or more action events after a specified delay. Don't confuse Swing timers with the general-purpose timer facility that was added to the java.util package in release 1.3. This page describes only Swing timers.

In general, we recommend using Swing timers rather than general-purpose timers for GUI-related tasks because Swing timers all share the same, pre-existing timer thread and the GUI-related task automatically executes on the event-dispatch thread. However, you might use a general-purpose timer if you don't plan on touching the GUI from the timer, or need to perform lengthy processing.

You can use Swing timers in two ways:

  • To perform a task once, after a delay.
    For example, the tool tip manager uses Swing timers to determine when to show a tool tip and when to hide it.
  • To perform a task repeatedly.
    For example, you might perform animation or update a component that displays progress toward a goal.

Swing timers are very easy to use. When you create the timer, you specify an action listener to be notified when the timer "goes off". The actionPerformed method in this listener should contain the code for whatever task you need to be performed. When you create the timer, you also specify the number of milliseconds between timer firings. If you want the timer to go off only once, you can invoke setRepeats(false) on the timer. To start the timer, call its start method. To suspend it, call stop.

Note that the Swing timer's task is performed in the event dispatch thread. This means that the task can safely manipulate components, but it also means that the task should execute quickly. If the task might take a while to execute, then consider using a SwingWorker instead of or in addition to the timer. See Concurrency in Swing for instructions about using the SwingWorker class and information on using Swing components in multi-threaded programs.

Let's look at an example of using a timer to periodically update a component. The TumbleItem applet uses a timer to update its display at regular intervals. (To see this applet running, go to How to Make Applets. This applet begins by creating and starting a timer:

timer = new Timer(speed, this);
timer.setInitialDelay(pause);
timer.start();
The speed and pause variables represent applet parameters; as configured on the other page, these are 100 and 1900 respectively, so that the first timer event will occur in approximately 1.9 seconds, and recur every 0.1 seconds. By specifying this as the second argument to the Timer constructor, TumbleItem specifies that it is the action listener for timer events.

After starting the timer, TumbleItem begins loading a series of images in a background thread. Meanwhile, the timer events begin to occur, causing the actionPerformed method to execute:

public void actionPerformed(ActionEvent e) {
    //If still loading, can't animate.
    if (!worker.isDone()) {
        return;
    }

    loopslot++;

    if (loopslot >= nimgs) {
        loopslot = 0;
        off += offset;

        if (off < 0) {
            off = width - maxWidth;
        } else if (off + maxWidth > width) {
            off = 0;
        }
    }

    animator.repaint();

    if (loopslot == nimgs - 1) {
        timer.restart();
    }
}
Until the images are loaded, worker.isDone returns false, so timer events are effectively ignored. The first part of the event handling code simply sets values that are employed in the animation control's paintComponent method: loopslot (the index of the next graphic in the animation) and off (the horizontal offset of the next graphic).

Eventually, loopslot will reach the end of the image array and start over. When this happens, the code at the end of actionPerformed restarts the timer. Doing this causes a short delay before the animation sequence begins again.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Actions
Next page: How to Support Assistive Technologies


How to Support Assistive Technologies (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Other Swing Features)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Other Swing Features
Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Home Page > Creating a GUI with JFC/Swing > Using Other Swing Features
« Previous • Trail • Next »
How to Support Assistive Technologies
You might be wondering what exactly assistive technologies are, and why you should care. Primarily, assistive technologies exist to enable people with permanent or temporary disabilities to use the computer. For example, if you get carpal tunnel syndrome, you can use assistive technologies to accomplish your work without using your hands.

Assistive technologies — voice interfaces, screen readers, alternate input devices, and so on — are useful not only for people with disabilities, but also for people using computers in non-office environments. For example, if you're stuck in a traffic jam, you might use assistive technologies to check your email, using only voice input and output. The information that enables assistive technologies can be used for other tools, as well, such as automated GUI testers and input devices such as touchscreens. Assistive technologies get information from components using the Accessibility API, which is defined in the javax.accessibility package.

Because support for the Accessibility API is built into the Swing components, your Swing program will probably work just fine with assistive technologies, even if you do nothing special. For example, assistive technologies can automatically get the text information that is set by the following lines of code:

JButton button = new JButton("I'm a Swing button!");
label = new JLabel(labelPrefix + "0    ");
label.setText(labelPrefix + numClicks);
JFrame frame = new JFrame("SwingApplication");
Assistive technologies can also grab the tool-tip text (if any) associated with a component and use it to describe the component to the user.

Making your program function smoothly with assistive technologies is easy to do and, in the United States, may be required by federal law. For more information see Global Legal Resources for IT Related Accessibility Issues.

The rest of this section covers these topics:

  • Rules for Supporting Accessibility
  • Testing for Accessibility
  • Setting Accessible Names and Descriptions on Components
  • Concepts: How Accessibility Works
  • Making Custom Components Accessible
  • The Accessibility API
  • Examples that Use the Accessibility API

Rules for Supporting Accessibility
Here are a few things you can do to make your program work as well as possible with assistive technologies:
  • If a component doesn't display a short string (which serves as its default name), specify a name with the setAccessibleName method. You might want to do this for image-only buttons, panels that provide logical groupings, text areas, and so on.

  • Set tool tip text for components whenever it makes sense to do so. For example:
    aJComponent.setToolTipText(
     "Clicking this component causes XYZ to happen.");

  • If you don't want to provide a tool tip for a component, use the setAccessibleDescription method to provide a description that assistive technologies can give the user. For example:
    aJComponent.getAccessibleContext().
    setAccessibleDescription(
    "Clicking this component causes XYZ to happen.");

  • Specify keyboard alternatives wherever possible. Make sure you can use your program with only the keyboard. Try hiding your mouse! Note that if the focus is in an editable text component, you can use Shift-Tab to move focus to the next component.

    Support for keyboard alternatives varies by component. Buttons support keyboard alternatives with the setMnemonic method. Menus inherit the button mnemonic support and also support accelerators, as described in Enabling Keyboard Operation. Other components can use key bindings to associate user typing with program actions.

  • Assign a textual description to all ImageIcon objects in your program. You can set this property by using either the setDescription method or one of the String forms of the ImageIcon constructors.

  • If a bunch of components form a logical group, try to put them into one container. For example, use a JPanel to contain all the radio buttons in a radio button group.

  • Whenever you have a label that describes another component, use the setLabelFor method so that assistive technologies can find the component that the label is associated with. This is especially important when the label displays a mnemonic for another component (such as a text field).

  • If you create a custom component, make sure it supports accessibility. In particular, be aware that subclasses of JComponent are not automatically accessible. Custom components that are descendants of other Swing components should override inherited accessibility information as necessary. For more information, see Concepts: How Accessibility Works and Making Custom Components Accessible.

  • Use the examples provided with the accessibility utilities to test your program. Although the primary purpose of these examples is to show programmers how to use the Accessibility API when implementing assistive technologies, these examples are also quite useful for testing application programs for accessibility. Testing for Accessibility shows ScrollDemo running with Monkey—one of the accessibility utilities examples. Monkey shows the tree of accessible components in a program and lets you interact with those components.

  • Finally, don't break what you get for free! If your GUI has an inaccessible container—for example, your own subclass of Container or JComponent or any other container that doesn't implement the Accessible interface—any components inside that container become inaccessible.

Testing for Accessibility
The examples that come with the accessibility utilities can give you an idea of how accessible your program is. For instructions on getting these utilities, see the Accessibility home page. Follow the instructions in the accessibility utilities documentation for setting up the Java Virtual Machine (VM) to run one or more of the utilities automatically.

Let's use an accessibility utility to compare the original version of one of our demos to a version in which the rules for supporting accessibility have been applied. Here's a picture of a program called ScrollDemo.

A snapshot of the original, inaccessible ScrollDemo.

Try this:

  1. Click the Launch button to run ScrollDemo using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

    Launches the ScrollDemo example

  2. Next, click the Launch button to run AccessibleScrollDemo using Java™ Web Start (download JDK 6). Or, to compile and run the example yourself, consult the example index.

    Launches the AccessibleScrollDemo example

  3. Compare the two versions side by side. The only noticeable difference is that the cm toggle button and the photograph have tool tips in the accessible version.

  4. Now run the two versions under the accessibility utility called Monkey. Note that when the accessibility tools have been downloaded and configured in the accessibility.properties file, the Monkey window automatically comes up when you click on the Run ScrollDemo and AccessibleScrollDemo links (in steps 1 and 2).

    If the Monkey window does not appear on startup, the problem may be that the accessibility.properties file is not present in the version of the VM being used by Java Web Start. You can change the VM you use by running the Java Web Start Application Manager and selecting File > Preferences > Java.

  5. Note that when the Monkey window comes up you need to select File > Refresh Trees to see information appear under Accessible Tree. You can then expand the tree by successively clicking on the horizontal icons displayed by each folder icon. When the tree has been expanded, you can see detailed information for the various components. The custom components (rules and corners) that weren't accessible in the original version are accessible in the modified version. This can make quite a difference to assistive technologies.

Here's a snapshot of Monkey running on ScrollDemo:

Monkey running on inaccessible version of ScrollDemo.

The left side of the split pane shows the actual component hierarchy for the program. The right side shows the accessible components in the hierarchy, which is what interests us.

The first thing to notice is that, even with no explicit support in ScrollDemo, Monkey is able to discover a lot of information about the various components in the program. Most of the components and their children appear in the tree. However, the names for most of the components are empty (null), which is rather unhelpful. The descriptions are also empty.

Further trouble comes with the program's custom components. The two rulers are inaccessible, so they are not included in the accessible tree. The viewports that contain the rulers are displayed as leaf nodes because they have no accessible children. The custom corners are also missing from the accessible tree.

Now here's a picture of the Monkey window for AccessibleScrollDemo:

Monkey running on accessible version of ScrollDemo.

The rules are now listed as children of the viewports, and the corners are listed as children of the scroll pane. Furthermore, many of the components now have non-null names.

In the previous snapshot of Monkey, the Column Header item is selected. Monkey highlights the corresponding component in ScrollDemo program.

ScrollDemo shown when Column Header selected in Monkey.

When an item is selected, you can use Monkey's Panels menu to bring up one of four different panels that let you interact with the selected component. Choosing Panels > Accessibility API panel brings up a panel like the one shown in the following figure. This panel displays information available through methods defined in the AccessibleContext base class and the AccessibleComponent interface.

Accessibility API Panel for Column Header.

Monkey has three other panels:
  • AccessibleAction— Shows the actions supported by an accessible component and lets you invoke the action. Works only with an accessible component whose context implements the AccessibleAction interface.
  • AccessibleSelection— Shows the current selection of an accessible component and lets you manipulate the selection. Works only with accessible component whose context implements the AccessibleSelection interface.
  • AccessibleHypertext— Shows any hyperlinks contained within an accessible component and lets you traverse them. Works only with accessible component whose context implements the AccessibleHypertext interface.
The accessibility utilities examples are handy as testing tools and can give you an idea of how accessible the components in your program are. However, even if your components behave well in Monkey or the other examples, they still might not be completely accessible because Monkey and the other examples exercise only certain portions of the Accessibility API. The only true test of accessibility is to run your programs with real-world assistive technologies.

Setting Accessible Names and Descriptions on Components
Giving your program's components accessible names and descriptions is one of the easiest and most important steps in making your program accessible. Following is a complete listing of the AccessibleScrollDemo constructor that creates the scroll pane and the custom components it uses. The boldface statements give components names and descriptions that assistive technologies can use.
public AccessibleScrollDemo() {
    // Get the image to use.
    ImageIcon david = createImageIcon("images/youngdad.jpeg",
                      "Photograph of David McNabb in his youth.");

    // Create the row and column headers.
    columnView = new Rule(Rule.HORIZONTAL, true);
    if (david != null) {
        columnView.setPreferredWidth(david.getIconWidth());
    } else {
        columnView.setPreferredWidth(320);
    }
    columnView.getAccessibleContext().setAccessibleName("Column Header");
    columnView.getAccessibleContext().
            setAccessibleDescription("Displays horizontal ruler for " +
                                     "measuring scroll pane client.");
    rowView = new Rule(Rule.VERTICAL, true);
    if (david != null) {
        rowView.setPreferredHeight(david.getIconHeight());
    } else {
        rowView.setPreferredHeight(480);
    }
    rowView.getAccessibleContext().setAccessibleName("Row Header");
    rowView.getAccessibleContext().
            setAccessibleDescription("Displays vertical ruler for " +
                                     "measuring scroll pane client.");

    // Create the corners.
    JPanel buttonCorner = new JPanel();
    isMetric = new JToggleButton("cm", true);
    isMetric.setFont(new Font("SansSerif", Font.PLAIN, 11));
    isMetric.setMargin(new Insets(2,2,2,2));
    isMetric.addItemListener(this);
    isMetric.setToolTipText("Toggles rulers' unit of measure " +
                            "between inches and centimeters.");
    buttonCorner.add(isMetric); //Use the default FlowLayout
    buttonCorner.getAccessibleContext().
                 setAccessibleName("Upper Left Corner");

    String desc = "Fills the corner of a scroll pane " +
                  "with color for aesthetic reasons.";
    Corner lowerLeft = new Corner();
    lowerLeft.getAccessibleContext().
              setAccessibleName("Lower Left Corner");
    lowerLeft.getAccessibleContext().setAccessibleDescription(desc);

    Corner upperRight = new Corner();
    upperRight.getAccessibleContext().
               setAccessibleName("Upper Right Corner");
    upperRight.getAccessibleContext().setAccessibleDescription(desc);

    // Set up the scroll pane.
    picture = new ScrollablePicture(david,
                                    columnView.getIncrement());
    picture.setToolTipText(david.getDescription());
    picture.getAccessibleContext().setAccessibleName(
                                     "Scroll pane client");

    JScrollPane pictureScrollPane = new JScrollPane(picture);
    pictureScrollPane.setPreferredSize(new Dimension(300, 250));
    pictureScrollPane.setViewportBorder(
            BorderFactory.createLineBorder(Color.black));

    pictureScrollPane.setColumnHeaderView(columnView);
    pictureScrollPane.setRowHeaderView(rowView);

    // In theory, to support internationalization you would change
    // UPPER_LEFT_CORNER to UPPER_LEADING_CORNER,
    // LOWER_LEFT_CORNER to LOWER_LEADING_CORNER, and
    // UPPER_RIGHT_CORNER to UPPER_TRAILING_CORNER.  In practice,
    // bug #4467063 makes that impossible (at least in 1.4.0).
    pictureScrollPane.setCorner(JScrollPane.UPPER_LEFT_CORNER,
                                buttonCorner);
    pictureScrollPane.setCorner(JScrollPane.LOWER_LEFT_CORNER,
                                lowerLeft);
    pictureScrollPane.setCorner(JScrollPane.UPPER_RIGHT_CORNER,
                                upperRight);

    // Put it in this panel.
    setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
    add(pictureScrollPane);
    setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
}
Often, the program sets a component's name and description directly through the component's accessible context. Other times, the program sets an accessible description indirectly with tool tips. In the case of the cm toggle button, the description is set automatically to the text on the button.

Concepts: How Accessibility Works
An object is accessible if it implements the Accessible interface. The Accessible interface defines just one method, getAccessibleContext, which returns an AccessibleContext object. The AccessibleContext object is an intermediary that contains the accessible information for an accessible object. The following figure shows how assistive technologies get the accessible context from an accessible object and query it for information:

How assistive technologies get information from accessible objects.

AccessibleContext is an abstract class that defines the minimum set of information an accessible object must provide about itself. The minimum set includes name, description, role, state set, and so on. To identify its accessible object as having particular capabilities, an accessible context can implement one or more of the interfaces as shown in the Accessible Interfaces table. For example, JButton implements AccessibleAction, AccessibleValue, AccessibleText, and AccessibleExtendedComponent. It is not necessary for JButton to implement AccessibleIcon because that is implemented by the ImageIcon attached to the button.

Because the JComponent class itself does not implement the Accessible interface, instances of its direct subclasses are not accessible. If you write a custom component that inherits directly from JComponent, you need to explicitly make it implement the Accessible interface. JComponent does have an accessible context, called AccessibleJComponent, that implements the AccessibleComponent interface and provides a minimal amount of accessible information. You can provide an accessible context for your custom components by creating a subclass of AccessibleJComponent and overriding important methods. Making Custom Components Accessible shows two examples of doing this.

All the other standard Swing components implement the Accessible interface and have an accessible context that implements one or more of the preceding interfaces as appropriate. The accessible contexts for Swing components are implemented as inner classes and have names of this style:

Component.AccessibleComponent
If you create a subclass of a standard Swing component and your subclass is substantially different from its superclass, then you should provide a custom accessible context for it. The easiest way is to create a subclass of the superclass's accessible context class and override methods as necessary. For example, if you create a JLabel subclass substantially different from JLabel, then your JLabel subclass should contain an inner class that extends AccessibleJLabel. The next section shows how to do so, using examples in which JComponent subclasses extend AccessibleJComponent.

Making Custom Components Accessible
The scroll demo program uses three custom component classes. ScrollablePicture is a subclass of JLabel, and Corner and Rule are both subclasses of JComponent.

The ScrollablePicture class relies completely on accessibility inherited from JLabel through JLabel.AccessibleJLabel. The code that creates an instance of ScrollablePicture sets the tool-tip text for the scrollable picture. The tool-tip text is used by the context as the component's accessible description. This behavior is provided by AccessibleJLabel.

The accessible version of the Corner class contains just enough code to make its instances accessible. We implemented accessibility support by adding the code shown in bold to the original version of Corner.

public class Corner extends JComponent implements Accessible {

    protected void paintComponent(Graphics g) {
        //Fill me with dirty brown/orange.
        g.setColor(new Color(230, 163, 4));
        g.fillRect(0, 0, getWidth(), getHeight());
    }

    public AccessibleContext getAccessibleContext() {
        if (accessibleContext == null) {
            accessibleContext = new AccessibleCorner();
        }
        return accessibleContext;
    }

    protected class AccessibleCorner extends AccessibleJComponent {
        //Inherit everything, override nothing.
    }
}
All of the accessibility provided by this class is inherited from AccessibleJComponent. This approach is fine for Corner because AccessibleJComponent provides a reasonable amount of default accessibility information and because corners are uninteresting— they exist only to take up a little bit of space onscreen. Other classes, such as Rule, need to provide customized information.

Rule provides an accessible context for itself in the same manner as Corner, but the context overrides two methods to provide details about the component's role and state:

protected class AccessibleRuler extends AccessibleJComponent {

    public AccessibleRole getAccessibleRole() {
        return AccessibleRuleRole.RULER;
    }

    public AccessibleStateSet getAccessibleStateSet() {
        AccessibleStateSet states =
            super.getAccessibleStateSet();
        if (orientation == VERTICAL) {
            states.add(AccessibleState.VERTICAL);
        } else {
            states.add(AccessibleState.HORIZONTAL);
        }
        if (isMetric) {
            states.add(AccessibleRulerState.CENTIMETERS);
        } else {
            states.add(AccessibleRulerState.INCHES);
        }
        return states;
    }
}
AccessibleRole is an enumeration of objects that identify roles that Swing components can play. It contains predefined roles such as label, button, and so on. The rulers in our example don't fit well into any of the predefined roles, so the program invents a new one in a subclass of AccessibleRole:
class AccessibleRuleRole extends AccessibleRole {
    public static final AccessibleRuleRole RULER
        = new AccessibleRuleRole("ruler");

    protected AccessibleRuleRole(String key) {
        super(key);
    }

    //Should really provide localizable versions of these names.
    public String toDisplayString(String resourceBundleName,
                                  Locale locale) {
        return key;
    }
}
Any component that has state can provide state information to assistive technologies by overriding the getAccessibleStateSet method. A rule has two sets of states: its orientation can be either vertical or horizontal, and its units of measure can be either centimeters or inches. AccessibleState is an enumeration of predefined states. This program uses its predefined states for vertical and horizontal orientation. Because AccessibleState contains nothing for centimeters and inches, the program makes a subclass to provide appropriate states:
class AccessibleRulerState extends AccessibleState {
    public static final AccessibleRulerState INCHES
        = new AccessibleRulerState("inches");
    public static final AccessibleRulerState CENTIMETERS
        = new AccessibleRulerState("centimeters");

    protected AccessibleRulerState(String key) {
        super(key);
    }

    //Should really provide localizable versions of these names.
    public String toDisplayString(String resourceBundleName,
                                  Locale locale) {
        return key;
    }
}
You've seen how to implement accessibility for two simple components, that exist only to paint themselves onscreen. Components that do more, such as responding to mouse or keyboard events, need to provide more elaborate accessible contexts. You can find examples of implementing accessible contexts by delving in the source code for the Swing components.

The Accessibility API

The tables in this section cover just part of the accessibility API. For more information about the accessibility API, see the API documentation for the classes and packages in the accessibility package. Also, refer to the API documentation for the accessible contexts for individual Swing components.

The API for supporting accessibility falls into the following categories:

  • Naming and Linking Components
  • Making a Custom Component Accessible
  • Accessible Interfaces
Naming and Linking Components
Method Purpose
getAccessibleContext().setAccessibleName(String)
getAccessibleContext().setAccessibleDescription(String)
(on a JComponent or Accessible object) 		Provide a name or description for an accessible object.
void setToolTipText(String)
(in JComponent) 		Set a component's tool tip. If you don't set the description, than many accessible contexts use the tool-tip text as the accessible description.
void setLabelFor(Component)
(in JLabel) 		Associate a label with a component. This tells assistive technologies that a label describes another component.
void setDescription(String)
(in ImageIcon) 		Provide a description for an image icon.

Making a Custom Component Accessible
Interface or Class Purpose
Accessible
(an interface) 		Components that implement this interface are accessible. Subclasses of JComponent must implement this explicitly.
AccessibleContext
JComponent.AccessibleJComponent
(an abstract class and its subclasses) 		AccessibleContext defines the minimal set of information required of accessible objects. The accessible context for each Swing component is a subclass of this and named as shown. For example, the accessible context for JTree is JTree.AccessibleJTree. To provide custom accessible contexts, custom components should contain an inner class that is a subclass of AccessibleContext. For more information, see Making Custom Components Accessible.
AccessibleRole
AccessibleStateSet
(classes) 		Define the objects returned by an AccessibleContext object's getAccessibleRole and getAccessibleStateSet methods, respectively.
AccessibleRelation
AccessibleRelationSet
(classes introduced in 1.3) 		Define the relations between components that implement this interface and one or more other objects.

Accessible Interfaces
Interface | Purpose
AccessibleAction | Indicates that the object can perform actions. By implementing this interface, the accessible context can give information about what actions the accessible object can perform and can tell the accessible object to perform them.
AccessibleComponent | Indicates that the accessible object has an onscreen presence. Through this interface, an accessible object can provide information about its size, position, visibility and so on. The accessible contexts for all standard Swing components implement this interface, directly or indirectly. The accessible contexts for your custom components should do the same. As of 1.4, AccessibleExtendedComponent is preferred.
AccessibleEditableText
(Introduced in 1.4) 		Indicates that the accessible object displays editable text. In addition to the information available from its superinterface, AccessibleText, methods are provided for cutting, pasting, deleting, selecting, and inserting text.
AccessibleExtendedComponent
(Introduced in 1.4) 		In addition to the information available from its superinterface, AccessibleComponent, methods are provided for obtaining key bindings, border text, and tool-tip text.
AccessibleExtendedTable
(Introduced in 1.4) 		In addition to the information available from its superinterface, AccessibleTable, methods are provided to convert between an index and its row or column.
AccessibleHypertext | Indicates that the accessible object contains hyperlinks. Through this interface, an accessible object can provide information about its links and allow them to be traversed.
AccessibleIcon
(Introduced in 1.3) 		Indicates that the accessible object has an associated icon. Methods are provided that return information about the icon, such as size and description.
AccessibleKeyBinding
(Introduced in 1.4) 		Indicates that the accessible object supports one or more keyboard shortcuts that can be used to select the object. Methods are provided that return the key bindings for a given object.
AccessibleSelection | Indicates that the accessible object can contain a selection. Accessible contexts that implement this interface can report information about the current selection and can modify the selection.
AccessibleTable
(Introduced in 1.3) 		Indicates that the accessible object presents data in a two-dimensional data object. Through this interface information about the table such as table caption, row and column size, description, and name are provided. As of 1.4, AccessibleExtendedTable is preferred.
AccessibleText | Indicates that the accessible object displays text. This interface provides methods for returning all or part of the text, attributes applied to it, and other information about the text such as its length.
AccessibleValue | Indicates that the object has a numeric value. Through this interface an accessible object provides information about its current value and its minimum and maximum values.

Examples that Use the Accessibility API

The following table lists some of our examples that have good support for assistive technologies.

Example | Where Described | Notes
AccessibleScrollDemo | This section | Contains two custom components that implement the Accessible interface. To see a less accessible version of this program see How to Use Scroll Panes.
ButtonDemo | How to Use the Common Button API | Uses three buttons. Supports accessibility through button text, mnemonics, and tool tips.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Swing Timers
Next page: How to Use the Focus Subsystem


How to Use the Focus Subsystem (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Other Swing Features)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Other Swing Features
Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Home Page > Creating a GUI with JFC/Swing > Using Other Swing Features
« Previous • Trail • Next »
How to Use the Focus Subsystem
Many components — even those primarily operated with the mouse, such as buttons — can be operated with the keyboard. For a key press to affect a component, the component must have the keyboard focus.

From the user's point of view, the component with the keyboard focus is generally prominent — with a dotted or black border, for example. The window containing the component is also more prominent than other windows onscreen. These visual cues let the user know to which component any typing will relate. Only one component at a time in the window system can have the keyboard focus.

Exactly how a window gains the focus depends on the windowing system. There is no foolproof way, across all platforms, to ensure that a window gains the focus. On some operating systems, such as Microsoft Windows, the front window usually becomes the focused window. In these cases, the Window.toFront method moves the window to the front, thereby giving it the focus. However, on other operating systems, such as Solaris™ Operating System, the window manager may choose the focused window based on cursor position, and in these cases the behavior of the Window.toFront method is different.

A component generally gains the focus when the user clicks it, or when the user tabs between components, or otherwise interacts with a component. A component can also be given the focus programmatically, such as when its containing frame or dialog-box is made visible. This code snippet shows how to give a particular component the focus every time the window gains the focus:

//Make textField get the focus whenever frame is activated.
frame.addWindowListener(new WindowAdapter() {
    public void windowGainedFocus(WindowEvent e) {
        textField.requestFocusInWindow();
    }
});

If you want to ensure that a particular component gains the focus the first time a window is activated, you can call the requestFocusInWindow method on the component after the component has been realized, but before the frame is displayed. The following sample code shows how this operation can be done:

    //...Where initialization occurs...
    JFrame frame = new JFrame("Test");
    JPanel panel = new JPanel(new BorderLayout());

    //...Create a variety of components here...

    //Create the component that will have the initial focus.
    JButton button = new JButton("I am first");
    panel.add(button);
    frame.getContentPane().add(panel);  //Add it to the panel

    frame.pack();  //Realize the components.
    //This button will have the initial focus.
    button.requestFocusInWindow();
    frame.setVisible(true); //Display the window.

Alternatively, you can apply a custom FocusTraversalPolicy to the frame and call the getDefaultComponent method to determine which component will gain the focus.

Version note: This section describes the focus architecture implemented in JDK 1.4. Prior to the 1.4 release, JComponent methods, such as setNextFocusableComponent, getNextFocusableComponent, requestDefaultFocus, and isManagingFocus, were used to manage the keyboard focus. These methods are now deprecated. Another method, requestFocus, is discouraged because it tries to give the focus to the component's window, which is not always possible. As of JDK 1.4, you should instead use the requestFocusInWindow method, which does not attempt to make the component's window focused. The method returns a boolean value indicating whether the method succeeded.

The rest of this section covers the following topics:

  • Introduction to the Focus Subsystem
  • Validating Input
  • Making a Custom Component Focusable
  • Customizing Focus Traversal
  • Tracking Focus Changes to Multiple Components
  • Timing Focus Transfers
  • The Focus API
  • Focus Examples

Introduction to the Focus Subsystem

The focus subsystem is designed to do the right thing as invisibly as possible. In most cases it behaves in a reasonable manner, and if it does not you can tweak its behavior in various ways. Some common scenarios might include:

  • The ordering is right but the first component with the focus is not set. As shown a code snippet in the preceding section, you can use the requestFocusInWindow method to set the focus on a component when the window becomes visible.
  • The ordering is wrong. To fix this issue, you can change the containment hierarchy, you can change the order that the components are added to their containers, or you can create a custom focus traversal policy. For more details see Customizing Focus Traversal.
  • A component must to be prevented from losing focus, or you need to check a value in a component before it loses focus. Input verification is a solution to this problem.
  • A custom component is not getting the focus. To fix this issue, you need to make sure that it satisfies all the requirements outlined in Making a Custom Component Focusable.

The FocusConceptsDemo example illustrates a few concepts.

The FocusConceptsDemo example

Try this:
  1. Click the Launch button to run FocusConceptsDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the FocusConceptsDemo application

  2. If necessary, click the window to give it the focus.
  3. Move the focus from component to component using the Tab key.
    You will notice that when the focus moves into the text area, it stays in the text area.
  4. Move the focus out of the text area using Control-Tab.
  5. Move the focus in the opposite direction using Shift-Tab.
  6. Move the focus out of the text area in the opposite direction using Control-Shift-Tab.

The KeyboardFocusManager is a critical element of the focus subsystem. It manages state and initiates changes. The keyboard manager tracks the focus owner — the component that receives typing from the keyboard. The focused window is the window that contains the focus owner.

JWindow and focus: To use a JWindow component in your GUI, you should know that the JWindow component's owning frame must be visible in order for any components in the window to get the focus. By default, if you do not specify an owning frame for a JWindow component, an invisible owning frame is created for it. The result is that components in the JWindow component might not be able to get the focus. The solution is either to specify a visible owning frame when creating the JWindow component, or to use an undecorated JFrame component instead.

A focus cycle (or focus traversal cycle) is a set of components that share a common ancestor in the containment hierarchy. The focus cycle root is the container that is the root for a particular focus traversal cycle. By default, every JWindow and JInternalFrame component can be a focus cycle root. A focus cycle root can itself contain one or more focus cycle roots. The following Swing objects can be focus cycle roots: JApplet, JDesktopPane, JDialog, JEditorPane, JFrame, JInternalFrame, and JWindow. While it might appear that JTable and JTree objects are focus cycle roots, they are not.

A focus traversal policy determines the order in which a group of components are navigated. Swing provides the LayoutFocusTraversalPolicy class, which decides the order of navigation based on layout manager-dependent factors, such as size, location, and orientation of components. Within a focus cycle, components can be navigated in a forward or backward direction. In a hierarchy of focus cycle roots, upwards traversal takes the focus out of the current cycle into the parent cycle.

In most Look and Feel models, components are navigated using the Tab and Shift-Tab keys. These keys are the default focus traversal keys and can be changed programmatically. For example, you can add Enter as a forward focus traversal key with the following four lines of code:

Set forwardKeys = getFocusTraversalKeys(
    KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS);
Set newForwardKeys = new HashSet(forwardKeys);
newForwardKeys.add(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0));
setFocusTraversalKeys(KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS,
    newForwardKeys);
Tab shifts the focus in the forward direction. Shift-Tab moves the focus in the backward direction. For example, in FocusConceptsDemo, the first button has the initial focus. Tabbing moves the focus through the buttons into the text area. Additional tabbing moves the cursor within the text area but not out of the text area because, inside a text area, Tab is not a focus traversal key. However, Control-Tab moves the focus out of the text area and into the first text field. Likewise, Control-Shift-Tab moves the focus out of the text area and into the previous component. The Control key is used by convention to move the focus out of any component that treats Tab in a special way, such as JTable.

You have just received a brief introduction to the focus architecture. If you want more details, see the specification for the Focus Subsystem.

Validating Input

A common requirement of GUI design is a component that restricts the user's input — for example, a text field that allows only numeric input in decimal format (money, for example) or a text field that allows only 5 digits for a zip code. Release 1.4 provides a handy, easy-to-use formatted text field component that allows input to be restricted to a variety of localizable formats. You can also specify a custom formatter for the text field, which can perform special checking such as determining whether values are not only formatted correctly, but also reasonable.

You can use an input verifier as an alternative to a custom formatter, or when you have a component that is not a text field. An input verifier allows you to reject specific values, such as a properly formatted but invalid zip code, or values outside of a desired range, for example a body temperature higher than 110°F. To use an input verifier, you create a subclass of InputVerifier (a class introduced in JDK 1.3), create an instance of your subclass, and set the instance as the input verifier for one or more components.

A component's input verifier is consulted whenever the component is about to lose the focus. If the component's value is not acceptable, the input verifier can take appropriate action, such as refusing to yield the focus on the component or replacing the user's input with the last valid value and then allowing the focus to transfer to the next component. However, InputVerifier is not called when the focus is transferred to another toplevel component.

The following two examples show mortgage calculators. One uses formatted text fields and the other uses input verification with standard text fields.

The InputVerificationDemo and example, which demonstrates

Try this:
  1. Click the Launch button to run the FormattedTextFieldDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the FormattedTextFieldDemo application

  2. Click the Launch button to run the InputVerificationDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the InputVerificationDemo application

  3. Compare the two mortgage calculators side by side. You will see that the input verification demo specifies valid input values in the associated label for each editable text field. Try entering badly formatted values in both examples to observe behavior. Then try entering a properly formatted, but unacceptable value.

You can find the code for the Input Verification demo in InputVerificationDemo.java. Here is the code for the InputVerifier subclass, MyVerifier:

class MyVerifier extends InputVerifier
                 implements ActionListener {
    double MIN_AMOUNT = 10000.0;
    double MAX_AMOUNT = 10000000.0;
    double MIN_RATE = 0.0;
    int MIN_PERIOD = 1;
    int MAX_PERIOD = 40;

   public boolean shouldYieldFocus(JComponent input) {
        boolean inputOK = verify(input);
        makeItPretty(input);
        updatePayment();

        if (inputOK) {
            return true;
        } else {
            Toolkit.getDefaultToolkit().beep();
            return false;
        }
    }

    protected void updatePayment() {
        double amount = DEFAULT_AMOUNT;
        double rate = DEFAULT_RATE;
        int numPeriods = DEFAULT_PERIOD;
        double payment = 0.0;

        //Parse the values.
        try {
            amount = moneyFormat.parse(amountField.getText()).
                              doubleValue();
        } catch (ParseException pe) {pe.printStackTrace();}
        try {
            rate = percentFormat.parse(rateField.getText()).
                                 doubleValue();
        } catch (ParseException pe) {pe.printStackTrace();}
        try {
            numPeriods = decimalFormat.parse(numPeriodsField.getText()).
                              intValue();
        } catch (ParseException pe) {pe.printStackTrace();}

        //Calculate the result and update the GUI.
        payment = computePayment(amount, rate, numPeriods);
        paymentField.setText(paymentFormat.format(payment));
    }

    //This method checks input, but should cause no side effects.
    public boolean verify(JComponent input) {
        return checkField(input, false);
    }

    protected void makeItPretty(JComponent input) {
        checkField(input, true);
    }

    protected boolean checkField(JComponent input, boolean changeIt) {
        if (input == amountField) {
            return checkAmountField(changeIt);
        } else if (input == rateField) {
            return checkRateField(changeIt);
        } else if (input == numPeriodsField) {
            return checkNumPeriodsField(changeIt);
        } else {
            return true; //should not happen
        }
    }

    //Checks that the amount field is valid.  If it is valid,
    //it returns true; otherwise, returns false.  If the
    //change argument is true, this method sets the
    //value to the minimum or maximum value if necessary and (even if not) sets it to the
    //parsed number so that it looks good -- no letters,
    //for example.
    protected boolean checkAmountField(boolean change) {
        boolean wasValid = true;
        double amount = DEFAULT_AMOUNT;

        //Parse the value.
        try {
            amount = moneyFormat.parse(amountField.getText()).
                              doubleValue();
        } catch (ParseException pe) {
            pe.printStackTrace();
        wasValid = false;
        }

        //Value was invalid.
        if ((amount < MIN_AMOUNT) || (amount > MAX_AMOUNT)) {
            wasValid = false;
            if (change) {
                if (amount < MIN_AMOUNT) {
                    amount = MIN_AMOUNT;
                } else { // amount is greater than MAX_AMOUNT
                    amount = MAX_AMOUNT;
                }
            }
        }

        //Whether value was valid or not, format it nicely.
        if (change) {
            amountField.setText(moneyFormat.format(amount));
            amountField.selectAll();
        }

        return wasValid;
    }

    //Checks that the rate field is valid.  If it is valid,
    //it returns true; otherwise, returns false.  If the
    //change argument is true, this method reigns in the
    //value if necessary and (even if not) sets it to the
    //parsed number so that it looks good -- no letters,
    //for example.
    protected boolean checkRateField(boolean change) {
        ...//Similar to checkAmountField...
    }

    //Checks that the numPeriods field is valid.  If it is valid,
    //it returns true; otherwise, returns false.  If the
    //change argument is true, this method reigns in the
    //value if necessary and (even if not) sets it to the
    //parsed number so that it looks good -- no letters,
    //for example.
    protected boolean checkNumPeriodsField(boolean change) {
        ...//Similar to checkAmountField...
    }

    public void actionPerformed(ActionEvent e) {
        JTextField source = (JTextField)e.getSource();
        shouldYieldFocus(source); //ignore return value
        source.selectAll();
    }
}

Note that the verify method is implemented to detect invalid values but does nothing else. The verify method exists only to determine whether the input is valid — it should never bring up a dialog-box or cause any other side effects. The shouldYieldFocus method calls verify and, if a values is invalid, sets it to the minimum or maximum value. The shouldYieldFocus method is allowed to cause side effects, in this case, it always formats the text field and may also change its value. In our example, the shouldYieldFocus method always returns true so that the transfer of the focus is never actually prevented. This is just one way verification can be implemented. Find another version of this demo called InputVerificationDialogDemo that puts up a dialog-box when user input is invalid and requires the user to enter a legal value.

The input verifier is installed using the setInputVerifier method of the JComponent class. For example, the InputVerificationDemo has the following code:

private MyVerifier verifier = new MyVerifier();
...
amountField.setInputVerifier(verifier);

Making a Custom Component Focusable

For a component to gain the focus, it must satisfy three requirements: it must be visible, enabled, and focusable. An input map may also be given. For more information about input map, read How to Use Key Bindings.

The TrackFocusDemo example defines the simple component Picture. Its constructor is shown below:

public Picture(Image image) {
    this.image = image;
    setFocusable(true);
    addMouseListener(this);
    addFocusListener(this);
}

The call to the setFocusable(true) method makes the component focusable. If you explicitly give your component key bindings in its WHEN_FOCUSED input map, you do not need to call the setFocusable method.

To visually show changes in the focus (by drawing a red border only when the component has the focus), Picture has a focus listener.

To gain the focus when the user clicks on the picture, the component has a mouse listener. The listener's mouseClicked method requests for the focus to be transferred to the picture. Here is the code:

public void mouseClicked(MouseEvent e) {
    //Since the user clicked on us, let us get focus!
    requestFocusInWindow();
}

See Tracking Focus Changes to Multiple Components for more discussion of the TrackFocusDemo example.

Customizing Focus Traversal

The focus subsystem determines a default order that is applied when using the focus traversal keys (such as Tab) to navigate. The policy of a Swing application is determined by LayoutFocusTraversalPolicy . You can set a focus traversal policy on any Container by using the setFocusCycleRoot method. However, if the container is not a focus cycle root, it may have no apparent effect. Alternatively you can pass focus traversal policy providers to the FocusTraversalPolicy methods instead of focus cycle roots. Use the isFocusTraversalPolicyProvider() method to determine whether a Container is a focus traversal policy provider. Use the setFocusTraversalPolicyProvider() method to set a container for providing focus traversal policy.

The FocusTraversalDemo example demonstrates how to customize focus behavior.

The Focus Traversal Demo, which demonstrates a custom FocusTraversalPolicy.

Try this:
  1. Click the Launch button to run FocusTraversalDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the FocusTraversalDemo application

  2. Click the window, if necessary, to give it the focus.
  3. Note the focus order as you tab through the components. The focus order was determined by the order that the components were added to the content pane. Note also that the check box never gets the focus; we removed it from the focus cycle.
  4. To move the focus out of the table, use Control-Tab or Control-Shift-Tab.
  5. Click the Custom FocusTraversalPolicy check box. This box installs a custom focus traversal policy on the frame.
  6. Try tabbing through the components again. Note that the focus order is now in left-to-right, top-down order.

You can find the demo's code in FocusTraversalDemo.java.

The check box was removed from the focus cycle with this line of code:

togglePolicy.setFocusable(false);
Here is the application's custom FocusTraversalPolicy:
    ...
    JTextField tf1 = new JTextField("Field 1");
    JTextField tf2 = new JTextField("A Bigger Field 2");
    JTextField tf3 = new JTextField("Field 3");
    JTextField tf4 = new JTextField("A Bigger Field 4");
    JTextField tf5 = new JTextField("Field 5");
    JTextField tf6 = new JTextField("A Bigger Field 6");
    JTable table = new JTable(4,3);
    ...
    public FocusTraversalDemo() {
        super(new BorderLayout());

        JTextField tf1 = new JTextField("Field 1");
        JTextField tf2 = new JTextField("A Bigger Field 2");
        JTextField tf3 = new JTextField("Field 3");
        JTextField tf4 = new JTextField("A Bigger Field 4");
        JTextField tf5 = new JTextField("Field 5");
        JTextField tf6 = new JTextField("A Bigger Field 6");
        JTable table = new JTable(4,3);
        togglePolicy = new JCheckBox("Custom FocusTraversalPolicy");
        togglePolicy.setActionCommand("toggle");
        togglePolicy.addActionListener(this);
        togglePolicy.setFocusable(false);  //Remove it from the focus cycle.
        //Note that HTML is allowed and will break this run of text
        //across two lines.
        label = new JLabel("Use Tab (or Shift-Tab) to navigate from component to component.
Control-Tab
    (or Control-Shift-Tab) allows you to break out of the JTable.");

        JPanel leftTextPanel = new JPanel(new GridLayout(3,2));
        leftTextPanel.add(tf1, BorderLayout.PAGE_START);
        leftTextPanel.add(tf3, BorderLayout.CENTER);
        leftTextPanel.add(tf5, BorderLayout.PAGE_END);
        leftTextPanel.setBorder(BorderFactory.createEmptyBorder(0,0,5,5));
        JPanel rightTextPanel = new JPanel(new GridLayout(3,2));
        rightTextPanel.add(tf2, BorderLayout.PAGE_START);
        rightTextPanel.add(tf4, BorderLayout.CENTER);
        rightTextPanel.add(tf6, BorderLayout.PAGE_END);
        rightTextPanel.setBorder(BorderFactory.createEmptyBorder(0,0,5,5));
        JPanel tablePanel = new JPanel(new GridLayout(0,1));
        tablePanel.add(table, BorderLayout.CENTER);
        tablePanel.setBorder(BorderFactory.createEtchedBorder());
        JPanel bottomPanel = new JPanel(new GridLayout(2,1));
        bottomPanel.add(togglePolicy, BorderLayout.PAGE_START);
        bottomPanel.add(label, BorderLayout.PAGE_END);

        add(leftTextPanel, BorderLayout.LINE_START);
        add(rightTextPanel, BorderLayout.CENTER);
        add(tablePanel, BorderLayout.LINE_END);
        add(bottomPanel, BorderLayout.PAGE_END);
        setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
        Vector order = new Vector(7);
        order.add(tf1);
        order.add(tf2);
        order.add(tf3);
        order.add(tf4);
        order.add(tf5);
        order.add(tf6);
        order.add(table);
        newPolicy = new MyOwnFocusTraversalPolicy(order);
    }

To use a custom FocusTraversalPolicy, implement the following code on any focus cycle root.

    MyOwnFocusTraversalPolicy newPolicy = new MyOwnFocusTraversalPolicy();
    frame.setFocusTraversalPolicy(newPolicy);

You can remove the custom focus traversal policy by setting the FocusTraversalPolicy to null, which will restore the default policy.

Tracking Focus Changes to Multiple Components

In some situations an application may need to track which component has the focus. This information might be used to dynamically update menus or perhaps a status bar. If you need to track the focus only on specific components, it may make sense to implement a focus event listener.

If a focus listener is not appropriate, you can instead register a PropertyChangeListener on the KeyboardFocusManager. The property change listener is notified of every change involving the focus, including changes to the focus owner, the focused window, and the default focus traversal policy. See the KeyboardFocusManager Properties table for a complete list.

The following example demonstrates tracking the focus owner by installing a property change listener on the keyboard focus manager.

The TrackFocusDemo example, which demonstrates tracking the focus owner.

Try this:
  1. Click the Launch button to run TrackFocusDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TrackFocusDemo application

  2. If necessary, click the window to give it the focus.
  3. The window shows six images, each of which is displayed by a Picture component. The Picture that has the focus is indicated with a red border. A label at the bottom of the window describes the Picture that has the focus.
  4. Move the focus to another Picture by using Tab or Shift-Tab, or by clicking an image. Because a property change listener has been registered on the keyboard focus manager, the change in focus is detected and the label is updated appropriately.

You can view the demo's code in TrackFocusDemo.java. The custom component used for drawing the images can be found in Picture.java. Here is the code that defines and installs the property change listener:

KeyboardFocusManager focusManager =
    KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addPropertyChangeListener(
    new PropertyChangeListener() {
        public void propertyChange(PropertyChangeEvent e) {
            String prop = e.getPropertyName();
            if (("focusOwner".equals(prop)) &&
                  ((e.getNewValue()) instanceof Picture)) {
                Component comp = (Component)e.getNewValue();
                String name = comp.getName();
                Integer num = new Integer(name);
                int index = num.intValue();
                if (index < 0 || index > comments.length) {
                    index = 0;
                }
                info.setText(comments[index]);
            }
        }
    }
);

The custom component, Picture, is responsible for drawing the image. All six components are defined in this manner:

pic1 = new Picture(createImageIcon("images/" +
            mayaString + ".gif", mayaString).getImage());
pic1.setName("1");

Timing Focus Transfers

Focus transfers are asynchronous. This quality can lead to some odd timing-related problems and assumptions, especially during automatic transfers of the focus. For example, imagine an application with a window containing a Start button, a Cancel button and a text field. The components are added in this order:

  1. Start button
  2. Text field
  3. Cancel button
When the application is launched, the LayoutFocusTraversalPolicy determines the focus traversal policy — in this case, it is the order that the components were added to their container. In this example, the desired behavior is that the Start button has the initial focus, and when the Start button is clicked, it is disabled, and then the Cancel button receives the focus. The correct way to implement this behavior would be to add the components to the container in the desired order or to create a custom focus traversal policy. If, for some reason, that is not possible, then you can implement this behavior with the following code snippet:
public void actionPerformed(ActionEvent e) {
    //This works.
    start.setEnabled(false);
    cancel.requestFocusInWindow();
}

As desired, the focus goes from the Start button to the Cancel button, rather than to the text field. But a different result would occur if the same methods were called in the opposite order as follows:

public void actionPerformed(ActionEvent e) {
    //This does not work.
    cancel.requestFocusInWindow();
    start.setEnabled(false);
}
In this case, the focus is requested on the Cancel button before it has left the Start button. The call to the requestFocusInWindow method initiates the focus transfer, but it does not immediately move the focus to the Cancel button. When the Start button is disabled, the focus is transferred to the next component (so there is always a component with the focus) and, in this case, it would then move the focus to the text field, not to the Cancel button.

There are several situations in which you need to make focus requests after all other changes that might affect the focus applies to:

  • Hiding the focus owner.
  • Making the focus owner non-focusable.
  • Calling the removeNotify method on the focus owner.
  • Doing any of the above operations to the container of the focus owner, or causing changes to the focus policy so that the container no longer accepts the component as the focus owner.
  • Disposing of the top-level window that contains the focus owner.

The Focus API

The following tables list the commonly used constructors and methods related to focus. The focus API falls into four categories:
  • Useful Methods for Components
  • Creating and Using a Custom FocusTraversalPolicy
  • Input Verification API
  • KeyboardFocusManager Properties

For more detailed information about the focus architecture, see the specification for the Focus Subsystem. You may also find How to Write a Focus Listener useful.

Useful Methods for Components

All of this API was introduced in JDK 1.4.
Method (in Component) | Purpose
isFocusOwner() | Returns true if the component is the focus owner. This method, introduced in JDK 1.4, renders obsolete hasFocus.
setRequestFocusEnabled(boolean)
isRequestFocusEnabled()
(in JComponent) 		Sets or checks on whether this component should get the focus. Setting the setRequestFocusEnabled to false typically prevents mouse clicks from giving the component the focus, while still allowing keyboard navigation to give the component the focus. This method applies only to components that receive mouse events. For example, you can use this method on a JButton, but not on a JPanel. If you write a custom component it is up to you to honor this property. This method is recommended over the setFocusable method and will allow your program to work better for users employing assistive technologies.
setFocusable(boolean)
isFocusable() 		Sets or gets the focusable state of the component. A component must be focusable in order to gain the focus. When a component has been removed from the focus cycle with setFocusable(false), it can no longer be navigated with the keyboard. The setRequestFocusEnabled method is recommended so that your program can be run by users employing assistive technologies.
requestFocusInWindow() | Requests that this component should get the focus. The component's window must be the current focused window. For this request to be granted a subclass of JComponent must be visible, enabled, and focusable, and have an input map for this request to be granted. It should not be assumed that the component has the focus until it fires a FOCUS_GAINED event. This method is preferred to the requestFocus method, which is platform-dependent.
setFocusTraversalKeys(int, Set)
getFocusTraversalKeys(int)
areFocusTraversalKeysSet(int)
(in java.awt.Container) 		Sets or gets the focus traversal keys for a particular direction or determines whether any focus traversal keys have been explicitly set on this container. If no focus traversal keys have been set, they are inherited from an ancestor or from the keyboard focus manager. Focus traversal keys can be set for the following directions: KeyboardFocusManager.FORWARD_TRAVERSAL_KEYS, KeyboardFocusManager.BACKWARD_TRAVERSAL_KEYS KeyboardFocusManager.UP_CYCLE_TRAVERSAL_KEYS, or KeyboardFocusManager.DOWN_CYCLE_TRAVERSAL_KEYS. If you set the UP_CYCLE_TRAVERSAL_KEYS or the DOWN_CYCLE_TRAVERSAL_KEYS, you must also invoke setImplicitDownCycleTraversal(false) on the focus traversal policy.

Creating and Using a Custom FocusTraversalPolicy

Class or Method | Purpose
LayoutFocusTraversalPolicy | The class that, by default, determines the focus traversal policy for Swing components.
getComponentAfter(Container, Component) | Given the component that is passed as input, returns the component that should next have the focus.
getComponentBefore(Container, Component) | Given the component that is passed as input, returns the component that should have the focus before this component. The method is used for backward tabbing.
getDefaultComponent(Container)
(in javax.swing.SortingFocusTraversalPolicy) 		Returns the component that should have the default focus.
getFirstComponent(Container) | Returns the first component in the traversal cycle.
getInitialComponent(Container) | Returns the component that should receive the focus when a window is made visible for the first time.
getLastComponent(Container) | Returns the last component in the traversal cycle.
setFocusTraversalPolicy(FocusTraversalPolicy)
getFocusTraversalPolicy(FocusTraversalPolicy)
(in java.awt.Container) 		Sets or gets the focus traversal policy or determines if a policy has been set. Note that setting a focus traversal policy on a container that is not the focus cycle root may have no apparent effect. A value of null means that a policy has not been explicitly set. If no policy has been set, a policy is inherited from the parent focus cycle root.
isFocusCycleRoot()
setFocusCycleRoot(boolean)
(in java.awt.Container) 		Checks or sets whether a container is the root of a focus traversal cycle.
isFocusTraversalPolicyProvider()
setFocusTraversalPolicyProvider(boolean)
(in java.awt.Container) 		Checks or sets whether a container will be used to provide focus traversal policy.

Input Verification API

All of this API was introduced in JDK 1.3.
Class or Method | Purpose
InputVerifier | Abstract class that allows input validation via the focus mechanism. When an attempt is made to shift the focus from a component containing an input verifier, the focus is not relinquished until the verifier is satisfied.
shouldYieldFocus(JComponent)
(in InputVerifier) 		When a component has an input verifier, this method is called by the system to determine whether the focus can leave this component. This method may cause side effects, such as bringing up a dialog-box. If this method returns false, the focus remains on the component passed in to the method.
verify(JComponent)
(in InputVerifier) 		You need to override this method to check that the component's input is valid. It should return true if valid, otherwise return false. This method should not cause any side effects, such as bringing up a dialog-box. This method is called by shouldYieldFocus.
setInputVerifier(inputVerifier)
getInputVerifier()
(in JComponent) 		Sets or gets the input verifier assigned to the component. By default, components have no input verifier.
setVerifyInputWhenFocusTarget(boolean)
getVerifyInputWhenFocusTarget()
(in JComponent) 		Sets or gets whether the input verifier for the current focus owner is called before this component requests the focus. The default is true. This method should be set to false for components, such as a Cancel button or a scroll bar, that should receive the focus even if input is invalid.

KeyboardFocusManager Properties

This table defines the bound properties for KeyboardFocusManager. A listener can be registered for these properties by calling addPropertyChangeListener.

All of this API was introduced in JDK 1.4.
Property | Purpose
focusOwner | The component that currently receives key events.
permanentFocusOwner | The component that most recently received a permanent FOCUS_GAINED event. Typically the same as focusOwner, unless a temporary focus change is currently in effect.
focusedWindow | The window that is or that contains the focus owner.
activeWindow | The component must always be either a Frame or a Dialog. The active window is either the focused window, or the first frame or dialog-box that is an owner of the focused window.
defaultFocusTraversalPolicy | The default focus traversal policy, which can be set by the setFocusTraversalPolicy method of the Container class.
forwardDefaultFocusTraversalKeys | The set of default focus keys for a forward traversal. For multi-line text components, these keys default to Control-Tab. For all other components, these keys default to Tab and Control-Tab.
backwardDefaultFocusTraversalKeys | The set of default focus keys for a backward traversal. For multi-line text components these keys default to Control-Shift-Tab. For all other components these keys default to Shift-Tab and Control-Shift-Tab.
upCycleDefaultFocusTraversalKeys | The set of default focus keys for an up cycle. These keys are null, by default, for Swing components. If you set these keys on the KeyboardFocusManager, or if you set the downCycleFocusTraversalKeys on a focus cycle root, you must also invoke the setImplicitDownCycleTraversal(false) method on the focus traversal policy.
downCycleDefaultFocusTraversalKeys | The set of default focus keys for a down cycle. These keys are null, by default, for Swing components. If you set these keys on the KeyboardFocusManager, or if you set the upCycleFocusTraversalKeys on a focus cycle root, you must also invoke the setImplicitDownCycleTraversal(false) method on the focus traversal policy.
currentFocusCycleRoot | The container that is the current focus cycle root.

Examples that Use Focus

The following table lists examples that manipulate the focus:

Example | Where Described | Notes
FocusConceptsDemo | This section | Demonstrates basic default focus behavior.
FocusTraversalDemo | This section | Demonstrates how to override the default focus order.
TrackFocusDemo | This section | Demonstrates how to use a PropertyChangeListener to track the focus owner. Also implements a custom focusable component.
InputVerificationDemo | This section | Demonstrates how to implement an InputVerifier to validate user input.
InputVerificationDialogDemo | This section | Demonstrates how to implement an InputVerifier that puts up a dialog-box when user input is invalid.
FocusEventDemo | How to Write a Focus Listener | Reports all focus events that occur on several components to demonstrate the circumstances under which focus events are fired.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Support Assistive Technologies
Next page: How to Use Key Bindings


How to Use Key Bindings (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Other Swing Features)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Other Swing Features
Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Home Page > Creating a GUI with JFC/Swing > Using Other Swing Features
« Previous • Trail • Next »
How to Use Key Bindings
The JComponent class supports key bindings as a way of responding to individual keys typed by a user. Here are some examples of when key bindings are appropriate:
  • You're creating a custom component and want to support keyboard access to it.
    For example, you might want the component to react when it has the focus and the user presses the Space key.

  • You want to override the behavior of an existing key binding.
    For example, if your application normally reacts to presses of the F2 key in a particular way, you might want it to perform a different action or ignore the key press.

  • You want to provide a new key binding for an existing action.
    For example, you might feel strongly that Control-Shift-Insert should perform a paste operation.

You often don't need to use key bindings directly. They're used behind the scenes by mnemonics (supported by all buttons and by tabbed panes as well as by JLabel) and accelerators (supported by menu items). You can find coverage of mnemonics and accelerators in the section Enabling Keyboard Operation.

An alternative to key bindings is using key listeners. Key listeners have their place as a low-level interface to keyboard input, but for responding to individual keys key bindings are more appropriate and tend to result in more easily maintained code. Key listeners are also difficult if the key binding is to be active when the component doesn't have focus. Some of the advantages of key bindings are they're somewhat self documenting, take the containment hierarchy into account, encourage reusable chunks of code (Action objects), and allow actions to be easily removed, customized, or shared. Also, they make it easy to change the key to which an action is bound. Another advantage of Actions is that they have an enabled state which provides an easy way to disable the action without having to track which component it is attached to.

The rest of this section gives you the details you need to use key bindings:

  • How Key Bindings Work
  • How to Make and Remove Key Bindings
  • The Key Binding API
  • Examples that Use Key Bindings

How Key Bindings Work

The key binding support provided by JComponent relies on the InputMap and ActionMap classes, which were introduced in 1.3. An input map binds key strokes to action names, and an action map specifies the action corresponding to each action name. Technically, you don't need to use action names in the maps; you can use any object as the "key" into the maps. By convention, however, you use a string that names an action.

Each InputMap/ActionMap has a parent that typically comes from the UI. Any time the look and feel is changed, the parent is reset. In this way, any bindings specified by the developer are never lost on look and feel changes.

Version Note: Prior to 1.3, the JComponent method registerKeyboardAction was used instead of input and action maps. registerKeyboardAction is now obsolete. (To ensure compatibility for older programs, registerKeyboardAction was reimplemented to use InputMap and ActionMap.)

Each JComponent has one action map and three input maps. The input maps correspond to the following focus situations:

JComponent.WHEN_FOCUSED
The component has the keyboard focus. The WHEN_FOCUSED input map is typically used when the component has no children. For example, buttons bind the Space key using the WHEN_FOCUSED map.
These bindings are only effective when the component has focus.

JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT
The component contains (or is) the component that has the focus. This input map is commonly used for a composite component — a component whose implementation depends on child components. For example, JTables make all their bindings using WHEN_ANCESTOR_OF_FOCUSED_COMPONENT so that if the user is editing, the up-arrow key (for example) still changes the selected cell.

JComponent.WHEN_IN_FOCUSED_WINDOW
The component's window either has the focus or contains the component that has the focus. This input map is commonly used for mnemonics or accelerators, which need to be active regardless of where focus is in the window.
When the user types a key, the JComponent key event processing code searches through one or more input maps to find a valid binding for the key. When it finds a binding, it looks up the corresponding action in the action map. If the action is enabled, the binding is valid and the action is executed. If it's disabled, the search for a valid binding continues.

If more than one binding exists for the key, only the first valid one found is used. Input maps are checked in this order:

  1. The focused component's WHEN_FOCUSED input map.
  2. The focused component's WHEN_ANCESTOR_OF_FOCUSED_COMPONENT input map.
  3. The WHEN_ANCESTOR_OF_FOCUSED_COMPONENT input maps of the focused component's parent, and then its parent's parent, and so on, continuing up the containment hierarchy. Note: Input maps for disabled components are skipped.
  4. The WHEN_IN_FOCUSED_WINDOW input maps of all the enabled components in the focused window are searched. Because the order of searching the components is unpredictable, avoid duplicate WHEN_IN_FOCUSED_WINDOW bindings!

Let's consider what happens in two typical key binding cases: a button reacting to the Space key, and a frame with a default button reacting to the Enter key.

In the first case, assume the user presses the Space key while a JButton has the keyboard focus. First, the button's key listeners are notified of the event. Assuming none of the key listeners consumes the event (by invoking the consume method on the KeyEvent) the button's WHEN_FOCUSED input map is consulted. A binding is found because JButton uses that input map to bind Space to an action name. The action name is looked up in the button's action map, and the actionPerformed method of the action is invoked. The KeyEvent is consumed, and processing stops.

In the second case, assume the Enter key is pressed while the focus is anywhere inside a frame that has a default button (set using the JRootPane setDefaultButton method). Whatever the focused component is, its key listeners are first notified. Assuming none of them consumes the key event the focused component's WHEN_FOCUSED input map is consulted. If it has no binding for the key or the Action bound to the key is disabled, the focused component's WHEN_ANCESTOR_OF_FOCUSED_COMPONENT input map is consulted and then (if no binding is found or the Action bound to the key is disabled) the WHEN_ANCESTOR_OF_FOCUSED_COMPONENT input maps of each of the component's ancestors in the containment hierarchy. Eventually, the root pane's WHEN_ANCESTOR_OF_FOCUSED_COMPONENT input map is searched. Since that input map has a valid binding for Enter, the action is executed, causing the default button to be clicked.

How to Make and Remove Key Bindings

Here is an example of specifying that a component should react to the F2 key:

component.getInputMap().put(KeyStroke.getKeyStroke("F2"),
                            "doSomething");
component.getActionMap().put("doSomething",
                             anAction);
//where anAction is a javax.swing.Action

As the preceding code shows, to get a component's action map you use the getActionMap method (inherited from JComponent). To get an input map, you can use the getInputMap(int) method, where the integer is one of the JComponent.WHEN_*FOCUSED* constants shown in the preceding list. Or, in the usual case where the constant is JComponent.WHEN_FOCUSED, you can just use getInputMap with no arguments.

To add an entry to one of the maps, use the put method. You specify a key using a KeyStroke object, which you can get using the KeyStroke.getKeyStroke(String) method. You can find examples of creating an Action (to put in an action map) in How to Use Actions.

Here's a slightly more complex example that specifies that a component should react to the Space key as if the user clicked the mouse.

component.getInputMap().put(KeyStroke.getKeyStroke("SPACE"),
                            "pressed");
component.getInputMap().put(KeyStroke.getKeyStroke("released SPACE"),
                            "released");
component.getActionMap().put("pressed",
                             pressedAction);
component.getActionMap().put("released",
                             releasedAction);
//where pressedAction and releasedAction are javax.swing.Action objects

To make a component ignore a key that it normally responds to, you can use the special action name "none". For example, the following code makes a component ignore the F2 key.

component.getInputMap().put(KeyStroke.getKeyStroke("F2"),
                            "none");
Note: The preceding code doesn't prevent the relevant WHEN_ANCESTOR_OF_FOCUSED_COMPONENT and WHEN_IN_FOCUSED_WINDOW input maps from being searched for an F2 key binding. To prevent this search, you must use a valid action instead of "none". For example:
Action doNothing = new AbstractAction() {
    public void actionPerformed(ActionEvent e) {
        //do nothing
    }
};
component.getInputMap().put(KeyStroke.getKeyStroke("F2"),
                            "doNothing");
component.getActionMap().put("doNothing",
                             doNothing);

The Key Binding API

The following tables list the commonly used API for key bindings. Also see the API table Creating and Using an Action, in the section How to Use Actions.
  • Creating and Using InputMaps
  • Creating and Using ActionMaps

Getting and Using InputMaps
Method Purpose
InputMap getInputMap()
InputMap getInputMap(int)
(in JComponent) 		Get one of the input maps for the component. The arguments can be one of these JComponent constants: WHEN_FOCUSED, WHEN_IN_FOCUSED_WINDOW, or WHEN_ANCESTOR_OF_FOCUSED_COMPONENT. The no-argument method gets the WHEN_FOCUSED input map.
void put(KeyStroke, Object)
(in InputMap) 		Set the action name associated with the specified key stroke. If the second argument is null, this method removes the binding for the key stroke. To make the key stroke be ignored, use "none" as the second argument.
static KeyStroke getKeyStroke(String)
(in KeyStroke) 		Get the object specifying a particular user keyboard activity. Typical arguments are "alt shift X", "INSERT", and "typed a". See the KeyStroke API documentation for full details and for other forms of the getKeyStroke method.

Getting and Using ActionMaps
Method Purpose
ActionMap getActionMap()
(in JComponent) 		Get the object that maps names into actions for the component.
void put(Object, Action)
(in ActionMap) 		Set the action associated with the specified name. If the second argument is null, this method removes the binding for the name.

Examples that Use Key Bindings

The following table lists examples that use key bindings:

Example | Where Described | Notes
TableFTFEditDemo | How to Use Tables | The IntegerEditor class registers a key binding on a formatted text field to validate the input when the user presses the Enter key.
SliderDemo3 | How to Use Sliders | A key binding is registered on a text field to validate the input when the user presses the Enter key.
TextComponentDemo | Text Component Features | Key bindings are registered on a text pane to navigate through the text when the user presses the Control-B, Control-F, Control-P, and Control-N keys.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use the Focus Subsystem
Next page: How to Use Modality in Dialogs


How to Use Modality in Dialogs (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Other Swing Features)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Other Swing Features
Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Home Page > Creating a GUI with JFC/Swing > Using Other Swing Features
« Previous • Trail • Next »
How to Use Modality in Dialogs

Java™ SE 6 has resolved modality issues that arose in earlier versions of the platform. The new modality model enables the developer to scope, or limit, a dialog box's modality blocking.

Before proceding with the new modality model, review the following terms:

  • Dialog box — A top-level pop-up window with a title and a border that typically takes some form of input from the user. A dialog box can be modal or modeless. For more information about dialog boxes, see An Overview of Dialogs in the How to Make Dialogs page.
  • Modal dialog box — A dialog box that blocks input to some other top-level windows in the application, except for windows created with the dialog box as their owner. The modal dialog box captures the window focus until it is closed, usually in response to a button press.
  • Modeless dialog box — A dialog box that enables you to operate with other windows while this dialog box is shown.

In Java SE 6 the behavior of both modal and modeless dialog boxes has been changed so that they always appear on top of both not only of their parent windows and of all blocked windows as well.

The following modality types are supported in Java SE 6:

  • Modeless type — A modeless dialog box does not block any other window while it is visible.
  • Document-modal type — A document-modal dialog box blocks all windows from the same document, except windows from its child hierarchy. In this context, a document is a hierarchy of windows that share a common ancestor, called the document root, which is the closest ancestor window without an owner.
  • Application-modal type — An application-modal dialog box blocks all windows from the same application, except windows from its child hierarchy. If several applets are launched in a browser environment, the browser is allowed to treat them either as separate applications or as a single application. This behavior is implementation-dependent.
  • Toolkit-modal type — A toolkit-modal dialog box blocks all windows that run in the same toolkit, except windows from its child hierarchy. If several applets are launched, all of them run with the same toolkit. Hence, a toolkit-modal dialog box shown from an applet may affect other applets and all windows of the browser instance that embeds the Java runtime environment for this toolkit.

Additionally, you can set up the modality exclusion mode:

  • Exclusion mode — Any top-level window can be marked not to be blocked by modal dialogs. This property enables you to set up the modal exclusion mode. The Dialog.ModalExclusionType enum specifies the possible modal exclusion types.
Note : The new modality model does not implement a system modality, which blocks all applications (including Java applications) that are displayed on the desktop while a modal dialog box is active.

The ModalityDemo example demonstrates the first three of the four modality types mentioned above.

Four frames to demonstrate different modality types
This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Try this:
  1. Click the Launch button to run ModalityDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ModalityDemo application

  2. The following dialog boxes will appear:
    • Book 1 (parent frame)
    • Book 2 (parent frame)
    • Feedback (parent frame)
    • Classics (excluded frame)
  3. Switch to the Book 1 frame and choose the Biography title for the book, then select OK.
  4. The Biography title will be displayed in the title of the dialog box. Enter the name, for example - “John”, into the text field.
  5. Switch to the Book 1 frame and change the title to Funny Tale, then select OK. Since the dialog box for entering the name is modeless, you can easily switch to its parent frame.
    6. Note : The modeless dialog box title has been changed to Funny Tale.
  6. Select OK in the modeless dialog box.
  7. The Funny tale document-modal dialog box appears.
  8. Type some text in the text field. Notice that it is signed by the name you entered in the modeless dialog box.
  9. Switch to the modeless dialog box and try to change your name. You will not be able to do so, because the document-modal dialog box blocks all windows in its parent hierarchy.
  10. Perform the same sequence of operations (steps 3 - 9) for the Book 2 parent frame.
  11. Try switching to different dialog boxes. You will notice that you can switch either to the Classics frame or to the Feedback frame as well as to the dialog box of either the Book 1 frame or the Book 2 frame.
  12. Switch to the Feedback parent frame. Select Rate Yourself.
  13. The confirmation dialog box will appear. Try switching to different dialog boxes. You are only enabled to switch to the Classics dialog box because the standard confirmation dialog box is an application-modal dialog box and it blocks all windows from the same application. However, you will notice that you can select your favorite classical author in the Classics frame. This frame has been created by using the APPLICATION_EXCLUDE modality exclusion type, which prevents all top-level windows from being blocked by any application-modal dialog boxes.

The following code snippet shows how to create dialog boxes of different modality types:

//The Book 1 parent frame
f1 = new JFrame("Book 1 (parent frame)");

...

//The modeless dialog box
d2 = new JDialog(f1);

...

//The document-modal dialog box
d3 = new JDialog(d2, "", Dialog.ModalityType.DOCUMENT_MODAL);

...

    //The Book2 parent frame
f4 = new JFrame("Book 2 (parent frame)");

...

//The modeless dialog box
d5 = new JDialog(f4);

...

//The document-modality dialog box
d6 = new JDialog(d5, "", Dialog.ModalityType.DOCUMENT_MODAL);

...

//The excluded frame
f7 = new JFrame("Classics (excluded frame)");
f7.setModalityExclusionType(Dialog.ModalExclusionType.APPLICAION_EXCLUDED);

...

//The Feedback parent frame and Confirm Dialog box
f8 = new JFrame("Feedback (parent frame)");
...

JButton b8 = new JButton("Rate yourself");
b8.addActionListener(new ActionListener() {
    public void actionPerformed(ActionEvent e) {
        JOptionPane.showConfirmationDialog(null,
                                           "I really like my book",
                                           "Question (application-modal dialog)",
                                           JOptionPane.Yes_NO_OPTION,
                                           JOptionPane.QUESTION_MESSAGE);
    }
});
Find the demo's complete code in the ModalityDemo.java file.

In Java SE 6 you can create a document-modal dialog box without a parent. Because the Dialog class is a subclass of the Window class, a Dialog instance automatically becomes the root of the document if it has no owner. Thus, if such a dialog box is document-modal, its scope of blocking is empty, and it behaves as if it were a modeless dialog box.

The Modality API

The JDialog class constructors enable you to create dialog boxes of various modality types.

Constructor | Purpose
JDialog(Dialog owner) | Creates a modeless dialog box with the specified Dialog owner but without a title.
JDialog(Dialog owner, boolean modal) | Creates a dialog box with the specified Dialog owner and modality.
JDialog(Dialog owner, String title) | Creates a modeless dialog box with the specified Dialog owner and title.
JDialog(Dialog owner, String title, boolean modal) | Creates a dialog box with the specified Dialog owner, title, and modality.
JDialog(Dialog owner, String title, boolean modal, GraphicsConfiguration gc) | Creates a dialog box with the specified Dialog owner, title, modality, and graphics configuration.
JDialog(Frame owner) | Creates a modeless dialog box without a title with the specified Frame owner. If the value for the owner is null, a shared, hidden frame will be set as the owner of the dialog box.
JDialog(Window owner, String title, Dialog.ModalityType modalityType) | Creates a dialog box with the specified Window owner, title, and modality.

The following table lists methods inherited from the java.awt.Dialog class.

Method | Purpose
getModalityType | Returns the modality type for this dialog box.
setModalityType | Sets the modality type for this dialog box. See ModalityType for possible modality types. If the given modality type is not supported, then the MODELESS type is used. To ensure that the modality type has been set, call the getModalityType() method after calling this method.

Examples That Use Modality API
The following table lists the example that uses modality in dialogs.

Example | Where Described | Notes
ModalityDemo | This section | Creates dialog boxes of different modality types, demonstrates scope blocking for those types.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Key Bindings
Next page: How to Print Tables


How to Print Tables (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Other Swing Features)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Other Swing Features
Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Home Page > Creating a GUI with JFC/Swing > Using Other Swing Features
« Previous • Trail • Next »
How to Print Tables
The JTable class provides support for printing tables. The JTable printing API includes methods that allow you to implement both basic and advanced printing tasks. For common printing tasks, when you need to simply print a table, use the print method directly. The print method has several forms with various argument sets. This method prepares your table, gets a corresponding Printable object, and sends it to a printer.

If the default implementation of the Printable object does not meet your needs, you can customize the printing layout by overriding the getPrintable method to wrap the default Printable or even replace it altogether.

The easiest way to print your table is to call the print method without parameters. See the code example below.

try {
    boolean complete = table.print();
    if (complete) {
        /* show a success message  */
        ...
    } else {
        /*show a message indicating that printing was cancelled */
        ...
    }
} catch (PrinterException pe) {
    /* Printing failed, report to the user */
    ...
}
When you call the print method with no parameters, a print dialog is displayed, and then your table is printed interactively in the FIT_WIDTH mode without a header or a footer. The code example below shows the print method signature with the complete set of arguments.

boolean complete = table.print(JTable.PrintMode printMode,
                               MessageFormat headerFormat,
                         MessageFormat footerFormat,
                               boolean showPrintDialog,
                               PrintRequestAttributeSet attr,
                               boolean interactive,
                               PrintService service);
When you call the print method with all arguments, you explicitly choose printing features such as a printing mode, a header and a footer text, printing attributes, a destination print service, and also whether to show a print dialog or not, and whether to print interactively or non-interactively. To decide which parameters suit your needs best, see the description of available features below.

The JTable printing API provides the following features:

  • Printing Interactively or Non-interactively
  • Displaying a Print Dialog
  • Adding a Header or a Footer (or Both) to a Printing Layout
  • Selecting a Printing Mode
  • Automatic Layout and Pagination

Printing Interactively or Non-interactively

In interactive mode a progress dialog with an abort option is shown for the duration of printing. Here is a sample of a progress dialog.

A screenshot of a printing progress dialog

This dialog enables the user to keep track of printing progress. The progress dialog is modal, which means that while it is shown on the screen, the user cannot interact with the table. It is important that your table remain unchanged while it is being printed, otherwise the printing behavior will be undefined. Nevertheless, printing interactively does not block other developer's code from changing the table. For example, there is another thread that posts updates using the SwingUtilities.invokeLater method. Therefore, to ensure correct printing behavior, you should be sure that your own code refrains from modifying the table during printing.

Alternatively, you can print your table non-interactively. In this mode, printing begins immediately on the event dispatch thread and completely blocks any events to be processed. On the one hand, this mode securely keeps the table against any changes until printing is done. On the other hand, this mode completely deprives the user of any interaction with the GUI. That is why printing non-interactively can only be recommended when printing from applications with non-visible GUI.

Print Dialog

You can display a standard print dialog which allows the user to do the following:
  • Select a printer
  • Specify number of copies
  • Change printing attributes
  • Cancel printing before it has been started
  • Start printing

A screenshot of a printing dialog

You may notice that the print dialog does not specify the total number of pages in the printout. This is because the table printing implementation uses the Printable API and the total number of pages is not known ahead of printing time.

Adding a Header or a Footer (or Both) to a Printing Layout

Headers and footers are provided by MessageFormat parameters. These parameters allow the header and footer to be localized. Read the documentation for the MessageFormat class, as some characters, such as single quotes, are special and need to be avoided. Both headers and footers are centered. You can insert a page number by using {0}.

MessageFormat footer = new MessageFormat("Page - {0}");

Since the total number of pages in the output is not known before printing time, there is no way to specify a numbering format like "Page 1 of 5".

Printing Modes

Printing modes are responsible for scaling the output and spreading it across pages. You can print your table in one of the following modes:
  • PrintMode.NORMAL
  • PrintMode.FIT_WIDTH

In the NORMAL mode a table is printed at its current size. If columns do not fit a page, they spread across additional pages according to the table's ComponentOrientation. In the FIT_WIDTH mode a table has a smaller size, if necessary, to fit all columns on each page. Note that both width and height are scaled to provide an output of the same aspect ratio. In both modes rows spread across multiple pages sequentially with as many rows on a page as possible.

Automatic Layout and Pagination

With the use of the JTable printing API you do not need to take care of layout and pagination. You only need to specify appropriate parameters to the print method such as printing mode and footer text format (if you want to insert the page number in the footer). As demonstrated earlier, you can specify the page number in your footer by including "{0}" in the string given to the MessageFormat footer parameter. In the printed output, {0} will be replaced by the current page number.

Table Printing Examples

Let us look at an example called TablePrintDemo1. The entire code for this program can be found in TablePrintDemo1.java. This demo's rich GUI is built automatically by the NetBeans IDE GUI builder. Here is a picture of the TablePrintDemo1 application.

A screenshot of TablePrintDemo1

Try this:
  1. Click the Launch button to run TablePrintDemo1 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TablePrintDemo1 Application

  2. Each checkbox in the bottom part of the application window has a tool tip. Hold the cursor over a checkbox to find out its purpose.
  3. Edit the text in the Header or Footer checkboxes or both to provide a different header or footer.
  4. Clear the Header or Footer checkboxes or both to turn the header or footer off.
  5. Clear the Show print dialog checkbox to turn the print dialog off.
  6. Clear the Fit width to printed page checkbox to select printing in the NORMAL mode.
  7. Clear the Interactive (Show status dialog) checkbox to turn the print dialog off.
  8. Click the Print button to print the table according to the selected options.
Whenever a web-launched application tries to print, Java Web Start pops up a security dialog asking the user for permission to print. To proceed with printing, the user has to accept the request.

Note when you clear the Interactive checkbox, a message appears that warns the user about the disadvantage of printing non-interactively. You can find the printing code in the PrintGradesTable method. When called, this method first obtains the set of selected options from the GUI components and then calls the print method as follows.

boolean complete = gradesTable.print(mode, header, footer,
                                     showPrintDialog, null,
                                     interactive, null);
The value returned by the print method is then used to show either the success message or the message saying that the user cancelled printing.

Another important feature is the table printing API's use of table renderers. By using the table's renderers, the API provides a printed output that looks like the table on the screen. Look at the last column of the table on the screen. It contains custom images denoting the passed or failed status of each student. Now look at the printed result. You can see that the check and X marks look the same.

Here is a picture of the TablePrintDemo1 printed result in the FIT_WIDTH mode.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

TablePrintDemo2 Example

The TablePrintDemo2 example is based on the previous demo and has an identical interface. The only difference is in the printed output. If you look at the TablePrintDemo1's printed result more attentively, you may notice that the check and X marks are fuzzy. The TablePrintDemo2 example shows how to customize the table to make the images more distinguishable in the table printout. In this demo, the overridden getTableCellRendererComponent method finds out whether the table is being printed and returns clearer black and white images. If the table is not being printed, it returns colored images that you can see on the screen.

Click the Launch button to run TablePrintDemo2 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the TablePrintDemo2 Application

The isPaintingForPrint method defined in the JComponent class allows us to customize what we print compared with what we see on the screen. The code of the custom cell renderer, taken from TablePrintDemo2.java, is listed below. This code chooses which images to use depending on the value returned by the isPaintingForPrint method.
    /**
     * A custom cell renderer that extends TablePrinteDemo1's renderer, to instead
     * use clearer black and white versions of the icons when printing.
     */
    protected static class BWPassedColumnRenderer extends PassedColumnRenderer {
            public Component getTableCellRendererComponent(JTable table,
                                                           Object value,
                                                           boolean isSelected,
                                                           boolean hasFocus,
                                                           int row,
                                                           int column) {

            super.getTableCellRendererComponent(table, value, isSelected,
                                                hasFocus, row, column);

            /* if we're currently printing, use the black and white icons */
            if (table.isPaintingForPrint()) {
                boolean status = (Boolean)value;
                setIcon(status ? passedIconBW : failedIconBW);
            } /* otherwise, the superclass (colored) icons are used */

            return this;
        }
    }

Here is a picture of the TablePrintDemo2 printed result in the FIT_WIDTH mode.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

TablePrintDemo3 Example

The TablePrintDemo3 example is based on the two previous demos. This example shows how to provide a customized Printable implementation by wrapping the default Printable with extra decoration. This demo has a similar interface but the Header and Footer checkboxes are disabled since the customized printable object will provide its own header and footer.

Click the Launch button to run TablePrintDemo3 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the TablePrintDemo3 Application

This example prints the table inside an image of a clipboard. Here is a picture of the printed result in the FIT_WIDTH mode.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

The entire code for this program can be found in TablePrintDemo3.java. In this demo, a custom subclass of the JTable class is used called FancyPrintingJTable. This FancyPrintingJTable class overrides the getPrintable method to return a custom printable object that wraps the default printable with its own decorations and header and footer. Here is the implementation of the getPrintable method.
public Printable getPrintable(PrintMode printMode,
                              MessageFormat headerFormat,
                              MessageFormat footerFormat) {

     MessageFormat pageNumber = new MessageFormat("- {0} -");

     /* Fetch the default printable */
     Printable delegate = super.getPrintable(printMode, null, pageNumber);

     /* Return a fancy printable that wraps the default */
     return new FancyPrintable(delegate);
}
The FancyPrintable class is responsible for wrapping the default printable object into another printable object and setting up the clipboard image. When an instance of this class is instantiated, it loads the images needed to assemble the clipboard image, calculates the area required for the clipboard image, calculates the shrunken area for the table, prints the table into the smaller area, and assembles and prints the clipboard image.

Pay attention to the flexibility of the code that assembles the clipboard image with respect to the page size. The code takes into account the actual page dimensions and puts together the auxiliary images, stretching some of them as necessary so that the final clipboard image fits the actual page size. The picture below shows the auxiliary images and indicates how those images form the final output.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

The Table Printing API

This section lists methods defined in the JTable class that allow you to print tables.

Method | Purpose
boolean print()
boolean print(printMode)
boolean print(printMode, MessageFormat, MessageFormat)
boolean print(printMode, MessageFormat, MessageFormat, boolean, PrintRequestAttributeSet, boolean)
boolean print(printMode, MessageFormat, MessageFormat, boolean, PrintRequestAttributeSet, boolean, PrintService) 		When called without arguments, displays a print dialog, and then prints this table interactively in the FIT_WIDTH mode without a header or a footer text. Returns true if the user continued printing and false if the user cancelled printing.
When called with a full set of arguments, prints this table according to the specified arguments. The first argument specifies the printing mode. Two MessageFormat arguments specify header and footer text. The first boolean argument defines whether to show a print dialog or not. Another boolean argument specifies whether to print interactively or not. With two other arguments you can specify printing attributes and a print service.
Whenever a PrintService argument is omitted, the default printer will be used.
Printable getPrintable(PrintMode, MessageFormat, MessageFormat) | Returns a Printable for printing a table. Override this method to get a customized Printable object. You can wrap one Printable object into another to get various layouts.

Examples That Use Table Printing

This table lists examples that use table printing and points to where those examples are described.

Example | Where Described | Notes
TablePrintDemo | How to Use Tables | Demonstrates basic features in table printing such as displaying a print dialogue, and then printing interactively in the FIT_WIDTH mode with a page number as a header.
TablePrintDemo1 | This page | Demostrates the basics of table printing and provides a rich GUI. Allows the user to specify a header or a footer text, select the printing mode, turn the print dialog on or off, and select printing interactively or non-interactively.
TablePrintDemo2 | This page | Based on the TablePrintDemo1, this example has an identical interface. This demo shows how to customize the table so that the printed result looks differently compared to the table being shown on the screen.
TablePrintDemo3 | This page | This demo shows advanced table printing features such as wrapping the default table printable into another printable to get a different layout.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Modality in Dialogs
Next page: How to Print Text


How to Print Text (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Other Swing Features)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Other Swing Features
Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Home Page > Creating a GUI with JFC/Swing > Using Other Swing Features
« Previous • Trail • Next »
How to Print Text
The JTextComponent class provides support for printing text documents. The JTextComponent API includes methods that allow you to implement both basic and advanced printing tasks. Supported formats include HTML, RTF, and plain text. For common printing tasks such as simply printing a text document, use the print method directly. The print method has several forms with various argument sets. This method prepares your text document, gets a corresponding Printable object, and sends it to a printer.

If the default implementation of the Printable object does not meet your needs, you can customize the printing layout by overriding the getPrintable method to wrap the default Printable or even replace it altogether.

The easiest way to print your text component is to call the print method without parameters. See the code example below.

try {
    boolean complete = textComponent.print();
    if (complete) {
        /* show a success message  */
        ...
    } else {
        /*show a message indicating that printing was cancelled */
        ...
    }
} catch (PrinterException pe) {
    /* Printing failed, report to the user */
    ...
}
When you call the print method with no parameters, a print dialog is displayed, and then your text component is printed interactively without a header or a footer. The code example below shows the print method signature with the complete set of arguments.

boolean complete = textComponent.print(MessageFormat headerFormat,
                                 MessageFormat footerFormat,
                                       boolean showPrintDialog,
                                       PrintService service
                           PrintRequestAttributeSet attributes,
                                       boolean interactive);
When you call the print method with all arguments, you explicitly choose printing features such as header and footer text, printing attributes, a destination print service, and also whether to show a print dialog or not, and whether to print interactively or non-interactively. To decide which parameters suit your needs best, see the description of available features below.

The JTextComponent printing API provides the following features:

  • Printing Interactively or Non-interactively
  • Displaying a Print Dialog
  • Adding a Header or a Footer (or Both) to a Printing Layout
  • Automatic Layout and Pagination

Printing Interactively or Non-interactively

In interactive mode a progress dialog with an abort option is shown for the duration of printing. Here is a sample of a progress dialog.

A screenshot of a printing progress dialog

This dialog allows the user to keep track of printing progress. The progress dialog is modal when the print method is called on the event dispatch thread and non-modal otherwise. It is important that your document remain unchanged while being printed, otherwise the printing behavior is undefined. The print method ensures that your document will not be changed and disables the component for the duration of printing.

If you call the print method on the event dispatch thread in non-interactive mode, then all events including repaints will be blocked. That is why printing non-interactively on EDT is only recommended for applications with non-visible GUI.

Print Dialog

You can display a standard print dialog which allows the user to do the following:
  • Select a printer
  • Specify number of copies
  • Change printing attributes
  • Cancel printing before it has been started
  • Start printing

A screenshot of a printing dialog

You may notice that the print dialog does not specify the total number of pages in the printout. This is because the text printing implementation uses the Printable API and the total number of pages is not known before printing time.

Adding a Header or a Footer (or Both) to a Printing Layout

Headers and footers are provided by MessageFormat parameters. These parameters allow the header and footer to be localized. Read the documentation for the MessageFormat class as characters such as single quotes are special and need to be avoided. Both headers and footers are centered. You can insert a page number by using {0}.

MessageFormat footer = new MessageFormat("Page - {0}");

Since the total number of pages in the output is not known before printing time, there is no way to specify a numbering format like "Page 1 of 5".

Automatic Layout and Pagination

With the use of the JTextComponent printing API you do not need to take care of layout and pagination. Both layout and pagination are done automatically. The document content is formatted to fit the page size and spreads across multiple pages. You only need to specify an appropriate footer text format to the print method if you want to insert a page number in the footer. As demonstrated earlier, you can specify the page number in your footer by including "{0}" in the string given to the MessageFormat footer parameter. In the printed output, {0} will be replaced by the current page number.

Text Area Printing Example

Let us look at an example called TextAreaPrintingDemo. The main feature of this demo is printing a text document either on the event dispatch thread or on a background thread depending on the user's choice. This demo displays a text area, allows to select several printing features, and prints the text area's content according to the selected options. The entire code for this program can be found in TextAreaPrintingDemo.java. This demo's rich GUI is built in the NetBeans IDE GUI builder. Here is a picture of the TextAreaPrintingDemo application.

A screenshot of TextAreaPrintingDemo

Try this:
  1. Click the Launch button to run TextAreaPrintingDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TextAreaPrintingDemo Application

  2. Edit the text in the Header or Footer checkboxes or both to provide a different header or footer.
  3. Clear the Show Progress Dialog checkbox if you want to print without displaying a progress dialog, which means printing non-interactively. Note that you will not be able to cancel printing once it has been started.
  4. Clear the Print in Background checkbox to select printing on the event dispatch thread. Note that printing on EDT non-interactively will make your application unresponsive — interaction with your application will be blocked for the duration of the printing process.
  5. Click the Print button to print the text area's content according to the selected options.
Whenever a web-launched application tries to print, Java Web Start opens up a security dialog asking the user for permission to print unless this permission has already been granted in the system settings. To proceed with printing the user has to accept the request.

An action listener is registered for the Print button. As the user clicks the Print button the actionPerformed method calls the print method, which initiates a printing task. The printing task is a SwingWorker object. The code example below shows how the PrintingTask class is implemented.

private class PrintingTask extends SwingWorker {
        private final MessageFormat headerFormat;
        private final MessageFormat footerFormat;
        private final boolean interactive;
        private volatile boolean complete = false;
        private volatile String message;

        public PrintingTask(MessageFormat header, MessageFormat footer,
                            boolean interactive) {
            this.headerFormat = header;
            this.footerFormat = footer;
            this.interactive = interactive;
        }

        @Override
        protected Object doInBackground() {
            try {
                complete = text.print(headerFormat, footerFormat,
                        true, null, null, interactive);
                message = "Printing " + (complete ? "complete" : "canceled");
            } catch (PrinterException ex) {
                message = "Sorry, a printer error occurred";
            } catch (SecurityException ex) {
                message =
                    "Sorry, cannot access the printer due to security reasons";
            }
            return null;
        }

        @Override
        protected void done() {
            message(!complete, message);
        }
    }
The code example below shows how the print method obtains the set of selected options from the GUI components, then creates an instance of the PrintingTask class, and performs printing.
private void print(java.awt.event.ActionEvent evt) {
        MessageFormat header = createFormat(headerField);
        MessageFormat footer = createFormat(footerField);
        boolean interactive = interactiveCheck.isSelected();
        boolean background = backgroundCheck.isSelected();

        PrintingTask task = new PrintingTask(header, footer, interactive);
    if (background) {
            task.execute();
        } else {
            task.run()
        }
    }
The code in bold illustrates how PrintingTask's methods are invoked depending on the background parameter's value. Whenever the user prefers to print on a background thread, the execute method is called, which schedules the printing task for the execution on a background thread. Otherwise the run method performs the printing task on EDT.

Since printing large documents is a time-consuming task, it is recommended to perform printing on a background thread.

Text Batch Printing Example

The TextBatchPrintingDemo example illustrates printing non-visible HTML text documents on background threads. When launched, this demo displays a page with a list of URLs. You can visit an HTML page, add the displayed page to the print list, and once you select all pages that you need, you can print them all at once on background threads. The entire code for this program can be found in TextBatchPrintingDemo.java. Here is a picture of the TextBatchPrintingDemo application.

A screenshot of TextBatchPrintingDemo

Try this:
  1. Click the Launch button to run TextBatchPrintingDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TextBatchPrintingDemo Application

  2. Click on any link to view the corresponding HTML page.
  3. Press ALT+A or choose File > Add Page menu item to add the displayed page to a print list shown on the right.
  4. Press ALT+H or choose File > Home Page menu item to return to the demo's home page.
  5. Add as many pages to the print list as you need.
  6. Press ALT+C or choose File > Clear Selected menu item if you need to clear the print list and build at again.
  7. Press ALT+P or choose File > Print Selected menu item to print the selected pages.
  8. Press ALT+Q or choose File > Quit menu item to quit the application.
You can find the printing code in the printSelectedPages method. When called, this method first obtains the amount of pages selected for printing. The code example below shows how the printSelectedPages method creates a Runnable object for each page and then prints the current page on a separate thread.
for (int i = 0; i < n; i++) {
    final PageItem item = (PageItem) pages.getElementAt(i);
    // This method is called from EDT.  Printing is a time-consuming
    // task, so it should be done outside EDT, in a separate thread.
    Runnable printTask = new Runnable() {
        public void run() {
            try {
                item.print(
                        // Two "false" args mean "no print dialog" and
                        // "non-interactive" (ie, batch-mode printing).
                                null, null, false, printService, null, false);
            } catch (PrinterException pe) {
                JOptionPane.showMessageDialog(null,
                        "Error printing " + item.getPage() + "\n" + pe,
                        "Print Error", JOptionPane.WARNING_MESSAGE);
            }
        }
    };
    new Thread(printTask).start();

Text Printing API

This section lists methods defined in the JTextComponent class that allow you to print text documents.

Method | Purpose
boolean print()
boolean print(MessageFormat, MessageFormat)
boolean print(MessageFormat, MessageFormat, boolean, PrintRequestAttributeSet, boolean, PrintService) 		When called without arguments, displays a print dialog, and then prints this text component interactively without a header or a footer text. Returns true if the user continued printing and false if the user cancelled printing.
When called with the two MessageFormat arguments, displays a print dialog, and then prints this text component interactively with the specified header and footer text.
When called with a full set of arguments, prints this text component according to the specified arguments. The two MessageFormat arguments specify header and footer text. The first boolean argument defines whether to show a print dialog or not. Another boolean argument specifies whether to print interactively or not. With two other arguments you can specify printing attributes and a print service.
Whenever a PrintService argument is omitted, the default printer will be used.
Printable getPrintable(MessageFormat, MessageFormat) | Returns a Printable object for printing your text component. Override this method to get a customized Printable object. You can wrap one Printable object into another in order to obtain complex reports and documents.

Examples That Use Text Printing

This table lists examples that use text printing and points to where those examples are described.

Example | Where Described | Notes
TextAreaPrintingDemo | This page | Demonstrates the basics of text printing and provides a rich GUI. Allows the user to specify header or footer text, turn the print dialog on or off, select printing interactively or non-interactively, and then print according to the selected options.
TextBatchPrintingDemo | This page | This demo displays a text component with a list of URLs, allows the user to view HTML pages, add them to the print list, and print all selected pages at once on background threads.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Print Tables
Next page: How to Create a Splash Screen


How to Create a Splash Screen (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Other Swing Features)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Other Swing Features
Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Home Page > Creating a GUI with JFC/Swing > Using Other Swing Features
« Previous • Trail • Next »
How to Create a Splash Screen

Almost all modern applications have a splash screen. Typically splash screens are used for the following purposes:

  • Advertising a product
  • Indicating to the user that the application is launching during long startup times
  • Providing information that is only needed once per visit

Java Foundation Classes, both Swing and Abstract Windowing Toolkit (AWT), enable a developer to create splash screens in Java technology applications. However, because the main purpose of a splash screen is to provide the user with feedback about the application's startup, the delay between the application's startup and the moment when the splash screen pops up should be minimal. Before the splash screen can pop up, the application has to load and initialize the Java™ Virtual Machine (JVM), AWT, Swing, and sometimes application-dependent libraries as well. The resulting delay of several seconds has made the use of a Java™ technology-based splash screen less than desirable.

Fortunately, Java™ SE 6 provides a solution that allows the application to display the splash screen much earlier, even before the virtual machine starts. A Java application launcher is able to decode an image and display it in a simple non-decorated window.

The splash screen can display any gif, png, or jpeg image, with transparency, translucency, and animation. The figure below represents an example of the Java application splash screen developed as an animated gif file.

Splash Screen for Java Application

The SplashScreen class is used to close the splash screen, change the splash-screen image, obtain the image position or size, and paint in the splash screen. An application cannot create an instance of this class. Only a single instance created within this class can exist, and this instance can be obtained using the getSplashScreen() static method. If the application has not created the splash screen at startup through the command-line or manifest-file option, the getSplashScreen method returns null.

Typically, a developer wants to keep the splash-screen image on the screen and display something over the image. The splash-screen window has an overlay surface with an alpha channel, and this surface can be accessed with a traditional Graphics2D interface.

The following code snippet shows how to obtain a SplashScreen object, then how to create a graphics context with the createGraphics() method:

...
        final SplashScreen splash = SplashScreen.getSplashScreen();
        if (splash == null) {
            System.out.println("SplashScreen.getSplashScreen() returned null");
            return;
        }
        Graphics2D g = splash.createGraphics();
        if (g == null) {
            System.out.println("g is null");
            return;
        }
...

Find the demo's complete code in the SplashDemo.java file.

Note: The SplashDemo application uses fixed coordinates to display overlay information. These coordinates are image-dependent and calculated individually for each splash screen.

The native splash screen can be displayed in the following ways:

  • Command-line argument
  • Java™ Archive (JAR) file with the specified manifest option

How to Use the Command-Line Argument to Display a Splash Screen

To display a splash screen from the command line use the -splash: command-line argument. This argument is a Java application launcher option that displays a splash screen:

java -splash:<file name> <class name>

Try this:
  1. Compile the SplashDemo.java file.
  2. Save the splash.gif image in the images directory.
  3. Run the application from the command line with the following arguments:
    java -splash:images/splash.gif SplashDemo
  4. Wait until the splash screen has been completely displayed.
  5. The application window appears. To close the window choose File|Exit from the pop-up menu or click the X.
  6. Change the splash screen name to a non-existent image, for example, nnn.gif. Run the application as follows:
    java -splash:images/nnn.gif SplashDemo
  7. You will see the following output string:
    SplashScreen.getSplashScreen() returned null

How to Use a JAR File to Display Splash Screen

If your application is packaged in a JAR file, you can use the SplashScreen-Image option in a manifest file to show a splash screen. Place the image in the JAR file and specify the path in the option as follows:

Manifest-Version: 1.0
Main-Class: <class name>
SplashScreen-Image: <image name>

Try this:
  1. Compile the SplashDemo.java file.
  2. Save the splash.gif image in the images directory.
  3. Prepare the splashmanifest.mf file as follows:
    Manifest-Version: 1.0
Main-Class: SplashDemo
SplashScreen-Image: images/splash.gif
  4. Create a JAR file using the following command:
    jar cmf splashmanifest.mf splashDemo.jar SplashDemo*.class images/splash.gif
    For more information about JAR files, see Using JAR Files in the Packaging Programs in JAR Files page.
  5. Run the application:
    java -jar splashDemo.jar
  6. Wait until the splash screen has been completly displayed.
  7. The application window appears. To close the window choose File|Exit from the pop-up menu or click the X.

The Splash Screen API

The SplashScreen class cannot be used to create the splash screen. Only a single instance created within this class can exist.
Method | Purpose
getSplashScreen() | Returns the SplashScreen object used for Java startup splash screen control.
createGraphics() | Creates a graphics context (as a Graphics2D object) for the splash screen overlay image, which allows you to draw over the splash screen.
getBounds() | Returns the bounds of the splash screen window as a Rectangle.
close() | Closes the splash screen and releases all associated resources.

Example That Uses the SplashScreen API
The following table lists the example that uses splash screen.

Example | Where Described | Notes
SplashDemo | This section | Shows a splash screen before opening the application window.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Print Text
Next page: How to Use the System Tray


How to Use the System Tray (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Other Swing Features)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Other Swing Features
Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Home Page > Creating a GUI with JFC/Swing > Using Other Swing Features
« Previous • Trail • Next »
How to Use the System Tray

The system tray is a specialized area of the desktop where users can access currently running programs. This area may be referred to differently on various operating systems. On Microsoft Windows, the system tray is referred to as the Taskbar Status Area, while on the GNU Network Object Model Environment (GNOME) Desktop it is referred to as the Notification Area. On K Desktop Environment (KDE) this area is referred to as the System Tray. However, on each system the tray area is shared by all applications running on the desktop.

The java.awt.SystemTray class introduced in Java™ SE version 6 represents the system tray for a desktop. The system tray can be accessed by calling the static SystemTray.getSystemTray() method. Before calling this method, use the static method isSupported() to check that the system tray is supported. If the system tray is not supported on this platform, the isSupported() method returns false. If the application attempts to call the getSystemTray() method in such a case, the method will throw a java.lang.UnsupportedOperationException.

An application cannot create an instance of the SystemTray class. Only a single instance created within this class can exist, and this instance can be obtained using the getSystemTray() method.

The system tray contains one or more tray icons which are added to the tray using the add(java.awt.TrayIcon) method. They can be removed when they are no longer needed with the remove(java.awt.TrayIcon) method.

Note: The add() method can throw an AWTException if the operating system or the Java runtime determines that the icon cannot be added to the system tray. For example, an AWTException will be thrown by X-Window desktops if the system tray does not exist on the desktop.

The TrayIcon class functionality goes beyond the icon that is displayed in the tray. It also includes a text tooltip, a pop-up menu, ballon messages, and a set of listeners associated with it. A TrayIcon object generates various mouse events and supports the addition of corresponding listeners to receive notification of these events. The TrayIcon class processes some of the events itself. For example, by default, when a right-click is performed on the tray icon, it displays the specified pop-up menu. When a double-click is performed, the TrayIcon object generates an ActionEvent to launch an application. When the mouse pointer hovers over the tray icon, the tooltip is displayed. The icon image is automatically resized to fit the space allocated for the image on the tray.

The following demo, developed using the AWT package, demonstrates the features of SystemTray and TrayIcon classes.

System Tray with opened pop-up menu

Unfortunately, the current implementation of the TrayIcon class provides limited support of the Swing pop-up menu (the JPopupMenu class) and does not enable an application to use all of the capabilities of the javax.swing package. The workaround proposal for this issue is described in the Bug Database, see Bug ID 6285881.

Try this:
  1. Place the bulb.gif image file in the image directory. Compile and run the example, consult the example index.
  2. The tray icon will appear in the system tray.

    Tray icon image

  3. Double-click the tray icon to launch the corresponding application. The dialog box will be displayed.
  4. Hover the mouse pointer over the tray icon and click the right mouse button. The pop-up menu appears.
  5. Select the Set auto size checkbox menu item. Notice that the icon appearance is changed as follows.

    Tray icon image is resized

  6. Select the Set tooltip checkbox menu item. Hover the mouse pointer over the tray icon. The tooltip appears.
  7. Choose the About menu item. The dialog box appears. Close the dialog box.
  8. Choose any of the Display submenu items. Each of these items displays a message dialog box of a particular type: error, warning, info, or standard.
  9. Use the Exit menu item to quit the application.

The following code snippet shows how to add a tray icon to the system tray and apply a pop-up menu:

...
        //Check the SystemTray is supported
        if (!SystemTray.isSupported()) {
            System.out.println("SystemTray is not supported");
            return;
        }
        final PopupMenu pop-up = new PopupMenu();
        final TrayIcon trayIcon =
                new TrayIcon(createImage("images/bulb.gif", "tray icon"));
        final SystemTray tray = SystemTray.getSystemTray();

        // Create a pop-up menu components
        MenuItem aboutItem = new MenuItem("About");
        CheckboxMenuItem cb1 = new CheckboxMenuItem("Set auto size");
        CheckboxMenuItem cb2 = new CheckboxMenuItem("Set tooltip");
        Menu displayMenu = new Menu("Display");
        MenuItem errorItem = new MenuItem("Error");
        MenuItem warningItem = new MenuItem("Warning");
        MenuItem infoItem = new MenuItem("Info");
        MenuItem noneItem = new MenuItem("None");
        MenuItem exitItem = new MenuItem("Exit");

        //Add components to pop-up menu
        pop-up.add(aboutItem);
        pop-up.addSeparator();
        pop-up.add(cb1);
        pop-up.add(cb2);
        pop-up.addSeparator();
        pop-up.add(displayMenu);
        displayMenu.add(errorItem);
        displayMenu.add(warningItem);
        displayMenu.add(infoItem);
        displayMenu.add(noneItem);
        pop-up.add(exitItem);

        trayIcon.setPopupMenu(pop-up);

        try {
            tray.add(trayIcon);
        } catch (AWTException e) {
            System.out.println("TrayIcon could not be added.");
        }
...

The complete code for this demo is available in the TrayIconDemo.java file. This demo also uses the bulb.gif image file.

Removing the current limitations on applying Swing components will enable developers to add such components as JMenuItem (with image), JRadioButtonMenuItem, and JCheckBoxMenuItem.

The SystemTray API

Only a single instance created within SystemTray class can exist.

Method | Purpose
add | Adds a tray icon to the system tray. The tray icon becomes visible in the system tray once it is added. The order in which icons are displayed in a tray is not specified — it is platform- and implementation-dependent.
getSystemTray | Gets the SystemTray instance that represents the desktop's tray area. This method always returns the same instance per application. On some platforms the system tray may not be supported. Use the isSupported() method to check if the system tray is supported.
isSupported | Returns information as to whether the system tray is supported on the current platform. In addition to displaying the tray icon, minimal system tray support includes either a pop-up menu (see the TrayIcon.setPopupMenu(PopupMenu) method) or an action event (see the TrayIcon.addActionListener(ActionListener)).

The TrayIcon API

A TrayIcon object represents a tray icon that can be added to the system tray. A TrayIcon object can have a tooltip (text), an image, a pop-up menu, and a set of listeners associated with it.

Method | Purpose
setImageAutoSize | Sets the auto-size property. Auto-size determines whether the tray image is automatically sized to fit the space allocated for the image on the tray. By default, the auto-size property is set to false.
setPopupMenu | Sets the pop-up menu for this TrayIcon object. If pop-up is null, no pop-up menu will be associated with this TrayIcon object.
setToolTip | Sets the tooltip string for this TrayIcon object. The tooltip is displayed automatically when the mouse hovers over the icon. Setting the tooltip to null removes any tooltip text. When displayed, the tooltip string may be truncated on some platforms; the number of characters that may be displayed is platform-dependent.

Examples That Use the SystemTray API
The following table lists the example that uses tray icons added to the system tray.

Example | Where Described | Notes
TrayIconDemo | This section | Creates the tray icon in the system tray, adds a pop-up menu to the tray icon.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Create a Splash Screen
Next page: Solving Common Problems Using Other Swing Features


Solving Common Problems Using Other Swing Features (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Other Swing Features)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Other Swing Features
Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Home Page > Creating a GUI with JFC/Swing > Using Other Swing Features
« Previous • Trail • Next »
Solving Common Problems Using Other Swing Features
Problem: My application is not showing the look and feel I have requested via UIManager.setLookAndFeel.

You probably either set the look and feel to an invalid look and feel or set it after the UI manager loaded the default look and feel. If you are sure that the look and feel you specified is valid and setting the look and feel is the first thing your program does (at the top of its main method, for example), check whether you have a static field that references a Swing class. This reference can cause the default look and feel to be loaded if none has been specified. For more information, including how to set a look and feel after the GUI has been created, see the look and feel section.

Problem: Why is not my component getting the focus?

  • Is it a custom component (for example, a direct subclass of JComponent) that you created? If so, you may need to give your component an input map and mouse listener. See How to Make a Custom Component Focusable for more information and a demo.

  • Is the component inside of a JWindow object? The focus system requires a JWindow's owning frame to be visible for any components in the JWindow object to get the focus. By default, if you do not specify an owning frame for a JWindow object, an invisible owning frame is created for it. The solution is to either specify a visible and focusable owning frame when creating the JWindow object or to use JDialog or JFrame objects instead.

Problem: Why cannot my dialog receive the event generated when the user hits the Escape key? This worked until I ported to release 1.4.

If your dialog contains a text field, it may be consuming the event. (Prior to release 1.4.0, the text field did not get the focus.)

  • If you want to get the Escape event regardless of whether a component consumes it, you should use a KeyEventDispatcher.

  • If you want to get the Escape event only if a component has not consumed it, then register a key binding on any JComponent component in the JDialog object, using the WHEN_IN_FOCUSED_WINDOW input map. For more information, see the How to Use Key Bindings page.

Problem: Why I cannot apply Swing components to a tray icon?

Current implementation of the TrayIcon class supports the PopupMenu component, but not its Swing counterpart JPopupMenu. This limitation narrows capabilities to employ additional Swing features, for example, menu icons. See the Bug ID 6285881.
  • A new JTrayIcon class will be created to eliminate this inconvenience. Until then, use AWT components to add a menu item, checkbox menu item, or submenu.

If you do not find your problem in this section, consult Solving Common Component Problems.

If there is a problem you would like to see mentioned on this page, please send us feedback.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use the System Tray
Next page: Laying Out Components Within a Container


Lesson: Laying Out Components Within a Container (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Lesson: Laying Out Components Within a Container
Examples Index

This lesson tells you how to use the layout managers provided by the Java platform. It also tells you how to use absolute positioning (no layout manager) and gives an example of writing a custom layout manager. For each layout manager (or lack thereof), this lesson points to an example that you can run using JavaTM Web Start. By resizing an example's window, you can see how size changes affect the layout.

Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.

A Visual Guide to Layout Managers

This section shows examples of the standard layout managers and points to the how-to section for each one.

Using Layout Managers

This section gives general rules on using the standard layout managers. It includes how to set the layout manager, add components to a container, provide size and alignment hints, put space between components, and set the orientation of the container's layout so that it is appropriate for the locale in which the program is running. It also has some tips for choosing the right layout manager.

How Layout Management Works

This section goes through a typical layout sequence and then describes what happens when a component's size changes.

How to Use ...

This series of sections tells you how to use each of the general-purpose layout managers that the Java platform provides.

Creating a Custom Layout Manager

Instead of using one of the Java platform's layout managers, you can write your own. Layout managers must implement the LayoutManager interface, which specifies the five methods every layout manager must define. Optionally, layout managers can implement LayoutManager2, which is a subinterface of LayoutManager.

Doing Without a Layout Manager (Absolute Positioning)

If necessary, you can position components without using a layout manager. Generally, this solution is used to specify absolute sizes and positions for components.

Solving Common Layout Problems

Some of the most common layout problems involve components that are displayed too small — or not at all. This section tells you how to fix these and other common layout problems.

Questions and Exercises

Try these questions and exercises to test what you have learned in this lesson.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: A Visual Guide to Layout Managers


A Visual Guide to Layout Managers (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
A Visual Guide to Layout Managers

Several AWT and Swing classes provide layout managers for general use:

  • BorderLayout
  • BoxLayout
  • CardLayout
  • FlowLayout
  • GridBagLayout
  • GridLayout
  • GroupLayout
  • SpringLayout

This section shows example GUIs that use these layout managers, and tells you where to find the how-to page for each layout manager. You can find links for running the examples in the how-to pages and in the example index.

Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.

BorderLayout

A picture of a GUI that uses BorderLayout

Every content pane is initialized to use a BorderLayout. (As Using Top-Level Containers explains, the content pane is the main container in all frames, applets, and dialogs.) A BorderLayout places components in up to five areas: top, bottom, left, right, and center. All extra space is placed in the center area. Tool bars that are created using JToolBar must be created within a BorderLayout container, if you want to be able to drag and drop the bars away from their starting positions. For further details, see How to Use BorderLayout.

BoxLayout

A picture of a GUI that uses BoxLayout

The BoxLayout class puts components in a single row or column. It respects the components' requested maximum sizes and also lets you align components. For further details, see How to Use BoxLayout.

CardLayout

A picture of a GUI that uses CardLayout Another picture of the same layout

The CardLayout class lets you implement an area that contains different components at different times. A CardLayout is often controlled by a combo box, with the state of the combo box determining which panel (group of components) the CardLayout displays. An alternative to using CardLayout is using a tabbed pane, which provides similar functionality but with a pre-defined GUI. For further details, see How to Use CardLayout.

FlowLayout

A picture of a GUI that uses FlowLayout

FlowLayout is the default layout manager for every JPanel. It simply lays out components in a single row, starting a new row if its container is not sufficiently wide. Both panels in CardLayoutDemo, shown previously, use FlowLayout. For further details, see How to Use FlowLayout.

GridBagLayout

A picture of a GUI that uses GridBagLayout

GridBagLayout is a sophisticated, flexible layout manager. It aligns components by placing them within a grid of cells, allowing components to span more than one cell. The rows in the grid can have different heights, and grid columns can have different widths. For further details, see How to Use GridBagLayout.

GridLayout

A picture of a GUI that uses GridLayout

GridLayout simply makes a bunch of components equal in size and displays them in the requested number of rows and columns. For further details, see How to Use GridLayout.

GroupLayout

A picture of a GUI that uses GroupLayout

GroupLayout is a layout manager that was developed for use by GUI builder tools, but it can also be used manually. GroupLayout works with the horizontal and vertical layouts separately. The layout is defined for each dimension independently. Consequently, however, each component needs to be defined twice in the layout. The Find window shown above is an example of a GroupLayout. For further details, see How to Use GroupLayout.

SpringLayout

A picture of a GUI that uses SpringLayout

Another GUI that uses SpringLayout

SpringLayout is a flexible layout manager designed for use by GUI builders. It lets you specify precise relationships between the edges of components under its control. For example, you might define that the left edge of one component is a certain distance (which can be dynamically calculated) from the right edge of a second component. SpringLayout lays out the children of its associated container according to a set of constraints, as shall be seen in How to Use SpringLayout.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Laying Out Components Within a Container
Next page: Using Layout Managers


Using Layout Managers (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
Using Layout Managers
A layout manager is an object that implements the LayoutManager interface* and determines the size and position of the components within a container. Although components can provide size and alignment hints, a container's layout manager has the final say on the size and position of the components within the container.
Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.

This section discusses some of the common tasks related to using layout managers:

  • Setting the Layout Manager
  • Adding Components to a Container
  • Providing Size and Alignment Hints
  • Putting Space Between Components
  • Setting the Container's Orientation
  • Tips on Choosing a Layout Manager
  • Third-Party Layout Managers

Setting the Layout Manager

As a rule, the only containers whose layout managers you need to worry about are JPanels and content panes. Each JPanel object is initialized to use a FlowLayout, unless you specify differently when creating the JPanel. Content panes use BorderLayout by default. If you do not like the default layout manager that a panel or content pane uses, you are free to change it to a different one. However, unless you are using JToolBar, the FlowLayout and BorderLayout managers are only useful for prototyping. Any real application will need to reset the layout manager. Again, you should use an appropriate tool to do this, rather than coding the manager by hand.

You can set a panel's layout manager using the JPanel constructor. For example:

JPanel panel = new JPanel(new BorderLayout());
After a container has been created, you can set its layout manager using the setLayout method. For example:
Container contentPane = frame.getContentPane();
contentPane.setLayout(new FlowLayout());

Although we strongly recommend that you use layout managers, you can perform layout without them. By setting a container's layout property to null, you make the container use no layout manager. With this strategy, called absolute positioning, you must specify the size and position of every component within that container. One drawback of absolute positioning is that it does not adjust well when the top-level container is resized. It also does not adjust well to differences between users and systems, such as different font sizes and locales.

Adding Components to a Container

When you add components to a panel or content pane, the arguments you specify to the add method depend on the layout manager that the panel or content pane is using. In fact, some layout managers do not even require you to add the component explicitly; for example, GroupLayout. For example, BorderLayout requires that you specify the area to which the component should be added (using one of the constants defined in BorderLayout) using code like this:
pane.add(aComponent, BorderLayout.PAGE_START);

The how-to section for each layout manager has details on what, if any, arguments you need to specify to the add method. Some layout managers, such as GridBagLayout and SpringLayout, require elaborate setup procedures. Many layout managers, however, simply place components based on the order they were added to their container.

Swing containers other than JPanel and content panes generally provide API that you should use instead of the add method. For example, instead of adding a component directly to a scroll pane (or, actually, to its viewport), you either specify the component in the JScrollPane constructor or use setViewportView. Because of specialized API like this, you do not need to know which layout manager (if any) many Swing containers use. (For the curious: scroll panes happen to use a layout manager named ScrollPaneLayout.)

For information about how to add components to a specific container, see the how-to page for the container. You can find the component how-to pages using How to Use Various Components.

Providing Size and Alignment Hints

Sometimes you need to customize the size hints that a component provides to its container's layout manager, so that the component will be laid out well. You can do this by specifying one or more of the minimum, preferred, and maximum sizes of the component. You can invoke the component's methods for setting size hints — setMinimumSize, setPreferredSize, and setMaximumSize. Or you can create a subclass of the component that overrides the appropriate getter methods — getMinimumSize, getPreferredSize, and getMaximumSize. Here is an example of making a component's maximum size unlimited:
component.setMaximumSize(new Dimension(Integer.MAX_VALUE,
                                       Integer.MAX_VALUE));

Many layout managers do not pay attention to a component's requested maximum size. However, BoxLayout and SpringLayout do. Furthermore, GroupLayout provides the ability to set the minimum, preferred or maximum size explicitly, without touching the component.

Besides providing size hints, you can also provide alignment hints. For example, you can specify that the top edges of two components should be aligned. You set alignment hints either by invoking the component's setAlignmentX and setAlignmentY methods, or by overriding the component's getAlignmentX and getAlignmentY methods. Although most layout managers ignore alignment hints, BoxLayout honors them. You can find examples of setting the alignment in How to Use BoxLayout.

Putting Space Between Components

Three factors influence the amount of space between visible components in a container:
The layout manager
Some layout managers automatically put space between components; others do not. Some let you specify the amount of space between components. See the how-to page for each layout manager for information about spacing support.
Invisible components
You can create lightweight components that perform no painting, but that can take up space in the GUI. Often, you use invisible components in containers controlled by BoxLayout. See How to Use BoxLayout for examples of using invisible components.
Empty borders
No matter what the layout manager, you can affect the apparent amount of space between components by adding empty borders to components. The best candidates for empty borders are components that typically have no default border, such as panels and labels. Some other components might not work well with borders in some look-and-feel implementations, because of the way their painting code is implemented. For information about borders, see How to Use Borders.

Setting the Container's Orientation

This website is written in English, with text that runs from left to right, and then top to bottom. However, many other languages have different orientations. The componentOrientation property provides a way of indicating that a particular component should use something different from the default left-to-right, top-to-bottom orientation. In a component such as a radio button, the orientation might be used as a hint that the look and feel should switch the locations of the icon and text in the button. In a container, the orientation is used as a hint to the layout manager.

To set a container's orientation, you can use either the Component-defined method setComponentOrientation or, to set the orientation on the container's children as well, applyComponentOrientation. The argument to either method can be a constant such as ComponentOrientation.RIGHT_TO_LEFT, or it can be a call to the ComponentOrientation method getOrientation(Locale). For example, the following code causes all JComponents to be initialized with an Arabic-language locale, and then sets the orientation of the content pane and all components inside it accordingly:

JComponent.setDefaultLocale(new Locale("ar"));
JFrame frame = new JFrame();
...
Container contentPane = frame.getContentPane();
contentPane.applyComponentOrientation(
    ComponentOrientation.getOrientation(
        contentPane.getLocale()));
Here are two pictures showing how FlowLayout lays out components in containers that are exactly the same, except for their orientation.

FlowLayoutDemo with default, left-to-right orientation
Default orientation (left-to-right)

FlowLayoutDemo with right-to-left orientation
Right-to-left orientation

The standard layout managers that support component orientation are FlowLayout, BorderLayout, BoxLayout, GridBagLayout, and GridLayout.
Note: Care must be taken that the component orientation is applied to renderers, editors and any other components unreachable through normal traversal of the containment hierarchy.

Tips on Choosing a Layout Manager

Layout managers have different strengths and weaknesses. This section discusses some common layout scenarios and which layout managers might work for each scenario. However, once again, it is strongly recommended that you use a builder tool to create your layout managers, such as the NetBeans IDE 5.5 Matisse GUI builder, rather than coding managers by hand. The scenarios listed below are given for information purposes, in case you are curious about which type of manager is used in different situations, or in case you absolutely must code your manager manually.

If none of the layout managers we discuss is right for your situation and you cannot use a builder tool, feel free to use other layout managers that you may write or find. Also keep in mind that flexible layout managers such as GridBagLayout and SpringLayout can fulfill many layout needs.

Scenario: You need to display a component in as much space as it can get.
If it is the only component in its container, use GridLayout or BorderLayout. Otherwise, BorderLayout or GridBagLayout might be a good match.

If you use BorderLayout, you will need to put the space-hungry component in the center. With GridBagLayout, you will need to set the constraints for the component so that fill=GridBagConstraints.BOTH. Another possibility is to use BoxLayout, making the space-hungry component specify very large preferred and maximum sizes.

Scenario: You need to display a few components in a compact row at their natural size.
Consider using a JPanel to group the components and using either the JPanel's default FlowLayout manager or the BoxLayout manager. SpringLayout is also good for this.

Scenario: You need to display a few components of the same size in rows and columns.
GridLayout is perfect for this.

Scenario: You need to display a few components in a row or column, possibly with varying amounts of space between them, custom alignment, or custom component sizes.
BoxLayout is perfect for this.

Scenario: You need to display aligned columns, as in a form-like interface where a column of labels is used to describe text fields in an adjacent column.
SpringLayout is a natural choice for this. The SpringUtilities class used by several Tutorial examples defines a makeCompactGrid method that lets you easily align multiple rows and columns of components.

Scenario: You have a complex layout with many components.
Consider either using a very flexible layout manager such as GridBagLayout or SpringLayout, or grouping the components into one or more JPanels to simplify layout. If you take the latter approach, each JPanel might use a different layout manager.

Third Party Layout Managers

Other third party layout managers have been created by the Swing community, to complement those provided by the Java platform. The following list is by no means definitive, but the layout managers listed below are the most popular:
  • TableLayout
  • MiGLayout
  • Karsten Lentzsch's FormLayout
*Way back in JDK 1.1 a second interface, LayoutManager2, was introduced. LayoutManager2 extends LayoutManager, providing support for maximum size and alignment. LayoutManager2 also adds the methods addLayoutComponent, that takes an Object, and invalidateLayout. Layout managers also need the notifications provided by LayoutManager2, so any modern layout manager will need to implement it.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: A Visual Guide to Layout Managers
Next page: How Layout Management Works


How Layout Management Works (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
How Layout Management Works
Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.

Here is an example of a layout management sequence for a container using LayoutManager2.

  1. Layout managers basically do two things:
    • Calculate the minimum/preferred/maximum sizes for a container.
    • Lay out the container's children.

    Layout managers do this based on the provided constraints, the container's properties (such as insets) and on the children's minimum/preferred/maximum sizes. If a child is itself a container then its own layout manger is used to get its minimum/preferred/maximum sizes and to lay it out.

  2. A container can be valid (namely, isValid() returns true) or invalid. For a container to be valid, all the container's children must be laid out already and must all be valid also. The Container.validate method can be used to validate an invalid container. This method triggers the layout for the container and all the child containers down the component hierarchy and marks this container as valid.

  3. After a component is created it is in the invalid state by default. The Window.pack method validates the window and lays out the window's component hierarchy for the first time.

The end result is that to determine the best size for the container, the system determines the sizes of the containers at the bottom of the containment hierarchy. These sizes then percolate up the containment hierarchy, eventually determining the container's total size.

If the size of a component changes, for example following a change of font, the component must be resized and repainted by calling the revalidate and repaint methods on that component. Both revalidate and repaint are thread-safe — you need not invoke them from the event-dispatching thread.

When you invoke revalidate on a component, a request is passed up the containment hierarchy until it encounters a container, such as a scroll pane or top-level container, that should not be affected by the component's resizing. (This is determined by calling the container's isValidateRoot method.) The container is then laid out, which has the effect of adjusting the revalidated component's size and the size of all affected components.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Layout Managers
Next page: How to Use Various Layout Managers


How to Use Various Layout Managers (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
How to Use Various Layout Managers
Each of the following pages describes how to use a particular kind of layout manager. Another way to get to these pages is through A Visual Guide to Layout Managers.
Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.
  • How to Use BorderLayout
  • How to Use BoxLayout
  • How to Use CardLayout
  • How to Use FlowLayout
  • How to Use GridBagLayout
  • How to Use GridLayout
  • How to Use GroupLayout
  • How to Use SpringLayout
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How Layout Management Works
Next page: How to Use BorderLayout


How to Use BorderLayout (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
How to Use BorderLayout
Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.
The following figure represents a snapshot of an application that uses the BorderLayout class.

A snapshot of BorderLayoutDemo

Click the Launch button to run BorderLayoutDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the BorderLayoutDemo application

The complete code of this demo is in the BorderLayoutDemo.java file.

As the preceding picture shows, a BorderLayout object has five areas. These areas are specified by the BorderLayout constants:

  • PAGE_START
  • PAGE_END
  • LINE_START
  • LINE_END
  • CENTER
Version note: Before JDK release 1.4, the preferred names for the various areas were different, ranging from points of the compass (for example, BorderLayout.NORTH for the top area) to wordier versions of the constants we use in our examples. The constants our examples use are preferred because they are standard and enable programs to adjust to languages that have different orientations.

If the window is enlarged, the center area gets as much of the available space as possible. The other areas expand only as much as necessary to fill all available space. Often a container uses only one or two of the areas of the BorderLayout object — just the center, or the center and the bottom.

The following code adds components to a frame's content pane. Because content panes use the BorderLayout class by default, the code does not need to set the layout manager. The complete program is in the BorderLayoutDemo.java file.

...//Container pane = aFrame.getContentPane()...
JButton button = new JButton("Button 1 (PAGE_START)");
pane.add(button, BorderLayout.PAGE_START);

//Make the center component big, since that's the
//typical usage of BorderLayout.
button = new JButton("Button 2 (CENTER)");
button.setPreferredSize(new Dimension(200, 100));
pane.add(button, BorderLayout.CENTER);

button = new JButton("Button 3 (LINE_START)");
pane.add(button, BorderLayout.LINE_START);

button = new JButton("Long-Named Button 4 (PAGE_END)");
pane.add(button, BorderLayout.PAGE_END);

button = new JButton("5 (LINE_END)");
pane.add(button, BorderLayout.LINE_END);

Specify the component's location (for example, BorderLayout.LINE_END) as one of the arguments to the add method. If this component is missing from a container controlled by a BorderLayout object, make sure that the component's location was specified and no another component was placed in the same location.

All tutorial examples that use the BorderLayout class specify the component as the first argument to the add method. For example:

add(component, BorderLayout.CENTER)  //preferred
However, the code in other programs specifies the component as the second argument. For example, here are alternate ways of writing the preceding code:
add(BorderLayout.CENTER, component)  //valid but old fashioned
    or
add("Center", component)             //valid but error prone

The BorderLayout API

The following table lists constructors and methods to specify gaps (in pixels).
Specifying gaps
Constructor or Method | Purpose
BorderLayout(int horizontalGap, int verticalGap) | Defines a border layout with specified gaps between components.
setHgap(int) | Sets the horizontal gap between components.
setVgap(int) | Sets the vertical gap between components.

Examples that Use BorderLayout

The following table lists code examples that use the BorderLayout class and provides links to related sections.

Example | Where Described | Notes
BorderLayoutDemo | This page | Puts a component in each of the five possible locations.
TabbedPaneDemo | How to Use Tabbed Panes | One of many examples that puts a single component in the center of a content pane, so that the component is as large as possible.
CheckBoxDemo | How to Use Check Boxes | Creates a JPanel object that uses the BorderLayout class. Puts components into the left (actually, LINE_START) and center locations.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use Various Layout Managers
Next page: How to Use BoxLayout


How to Use BoxLayout (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
How to Use BoxLayout
Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.
The Swing packages include a general purpose layout manager named BoxLayout. BoxLayout either stacks its components on top of each other or places them in a row — your choice. You might think of it as a version of FlowLayout, but with greater functionality. Here is a picture of an application that demonstrates using BoxLayout to display a centered column of components:

A snapshot of BoxLayoutDemo

Click the Launch button to run BoxLayoutDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the BoxLayoutDemo example

You can see the code in BoxLayoutDemo.java.

The following figure shows a GUI that uses two instances of BoxLayout. In the top part of the GUI, a top-to-bottom box layout places a label above a scroll pane. In the bottom part of the GUI, a left-to-right box layout places two buttons next to each other. A BorderLayout combines the two parts of the GUI and ensures that any excess space is given to the scroll pane.

Uses both left-to-right and top-to-bottom box layouts

You can find links for running ListDialog and for its source files in the example index for Using Swing Components.

The following code, taken from ListDialog.java, lays out the GUI. This code is in the constructor for the dialog, which is implemented as a JDialog subclass. The bold lines of code set up the box layouts and add components to them.

JScrollPane listScroller = new JScrollPane(list);
listScroller.setPreferredSize(new Dimension(250, 80));
listScroller.setAlignmentX(LEFT_ALIGNMENT);
...
//Lay out the label and scroll pane from top to bottom.
JPanel listPane = new JPanel();
listPane.setLayout(new BoxLayout(listPane, BoxLayout.PAGE_AXIS));
JLabel label = new JLabel(labelText);
...
listPane.add(label);
listPane.add(Box.createRigidArea(new Dimension(0,5)));
listPane.add(listScroller);
listPane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10));

//Lay out the buttons from left to right.
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
buttonPane.setBorder(BorderFactory.createEmptyBorder(0, 10, 10, 10));
buttonPane.add(Box.createHorizontalGlue());
buttonPane.add(cancelButton);
buttonPane.add(Box.createRigidArea(new Dimension(10, 0)));
buttonPane.add(setButton);

//Put everything together, using the content pane's BorderLayout.
Container contentPane = getContentPane();
contentPane.add(listPane, BorderLayout.CENTER);
contentPane.add(buttonPane, BorderLayout.PAGE_END);

The first bold line creates a top-to-bottom box layout and sets it up as the layout manager for listPane. The two arguments to the BoxLayout constructor are the container that it manages and the axis along which the components will be laid out. The PAGE_AXIS constant specifies that components should be laid out in the direction that lines flow across a page as determined by the target container's ComponentOrientation property. The LINE_AXIS constant specifies that components should be laid out in the direction of a line of text as determined by the target container's ComponentOrientation property. These constants allow for internationalization, by laying out components in their container with the correct left-to-right, right-to-left or top-to-bottom orientation for the language being used.

The next three bold lines add the label and scroll pane to the container, separating them with a rigid area — an invisible component used to add space between components. In this case, the rigid area has no width and puts exactly 5 pixels between the label and scroll pane. Rigid areas are discussed later, in Using Invisible Components as Filler.

The next chunk of bold code creates a left-to-right box layout and sets it up for the buttonPane container. Then the code adds two buttons to the container, using a rigid area to put 10 pixels between the buttons. To place the buttons at the right side of their container, the first component added to the container is glue. This glue is an invisible component that grows as necessary to absorb any extra space in its container. Glue is discussed in Using Invisible Components as Filler.

As an alternative to using invisible components, you can sometimes use empty borders to create space around components, most particularly panels. For example, the preceding code snippet uses empty borders to put 10 pixels between all sides of the dialog and its contents, and between the two parts of the contents. Borders are completely independent of layout managers. They are simply how Swing components draw their edges and provide padding between the content of the component and the edge. See How to Use Borders for more information.

The following sections discuss BoxLayout in more detail:

  • Box layout features
  • Using invisible components as filler
  • Fixing alignment problems
  • Specifying component sizes
  • The box layout API
  • Examples that use box layouts
Do not let the length of the BoxLayout discussion scare you! You can probably use BoxLayout with the information you already have. If you run into trouble or you want to take advantage of BoxLayout's power, read on.

Box Layout Features

As said before, BoxLayout arranges components either on top of each other or in a row. As the box layout arranges components, it takes the components' alignments and minimum, preferred, and maximum sizes into account. In this section, we will talk about top-to-bottom layout. The same concepts apply to left-to-right or right-to-left layout. You simply substitute X for Y, height for width, and so on.
Version note: Before JDK version 1.4, no constants existed for specifying the box layout's axis in a localizable way. Instead, you specified X_AXIS (left to right) or Y_AXIS (top to bottom) when creating the BoxLayout. Our examples now use the constants LINE_AXIS and PAGE_AXIS, which are preferred because they enable programs to adjust to languages that have different orientations. In the default, left-to-right orientation, LINE_AXIS specifies left-to-right layout and PAGE_AXIS specifies top-to-bottom layout.

When a BoxLayout lays out components from top to bottom, it tries to size each component at the component's preferred height. If the vertical space of the layout does not match the sum of the preferred heights, then BoxLayout tries to resize the components to fill the space. The components either grow or shrink to fill the space, with BoxLayout honoring the minimum and maximum sizes of each of the components. Any extra space appears at the bottom of the container.

For a top-to-bottom box layout, the preferred width of the container is that of the maximum preferred width of the children. If the container is forced to be wider than that, BoxLayout attempts to size the width of each component to that of the container's width (minus insets). If the maximum size of a component is smaller than the width of the container, then X alignment comes into play.

The X alignments affect not only the components' positions relative to each other, but also the location of the components (as a group) within their container. The following figures illustrate alignment of components that have restricted maximum widths.

Three left-aligned components Three center-aligned components Three right-aligned components

In the first figure, all three components have an X alignment of 0.0 (Component.LEFT_ALIGNMENT). This means that the components' left sides should be aligned. Furthermore, it means that all three components are positioned as far left in their container as possible.

In the second figure, all three components have an X alignment of 0.5 (Component.CENTER_ALIGNMENT). This means that the components' centers should be aligned, and that the components should be positioned in the horizontal center of their container.

In the third figure, the components have an X alignment of 1.0 (Component.RIGHT_ALIGNMENT). You can guess what that means for the components' alignment and position relative to their container.

You might be wondering what happens when the components have both restricted maximum sizes and different X alignments. The next figure shows an example of this:

Three components with mixed X alignments

As you can see, the left side of the component with an X alignment of 0.0 (Component.LEFT_ALIGNMENT) is aligned with the center of the component that has the 0.5 X alignment (Component.CENTER_ALIGNMENT), which is aligned with the right side of the component that has an X alignment of 1.0 (Component.RIGHT_ALIGNMENT). Mixed alignments like this are further discussed in Fixing Alignment Problems.

What if none of the components has a maximum width? In this case, if all the components have identical X alignment, then all components are made as wide as their container. If the X alignments are different, then any component with an X alignment of 0.0 (left) or 1.0 (right) will be smaller. All components with an intermediate X alignment (such as center) will be as wide as their container. Here are two examples:

Three components with mixed X alignments and no maximum size Three components with mixed X alignments and no maximum size

To get to know BoxLayout better, you can run your own experiments with BoxLayoutDemo2.
Try this:
  1. Click the Launch button to run BoxLayoutDemo2 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the BoxLayoutDemo2 example

    You can see the code in BoxLayoutDemo2.java.
    You will see a window like the one above that contains three rectangles. Each rectangle is an instance of BLDComponent, which is a JComponent subclass.

  2. Click inside one of the rectangles.
    This is how you change the rectangle's X alignment.
  3. Click the check box at the bottom of the window.
    This turns off restricted sizing for all the rectangles.
  4. Make the window taller.
    This makes the rectangles' container larger than the sum of the rectangles' preferred sizes. The container is a JPanel that has a red outline, so that you can tell where the container's edges are.

Using Invisible Components as Filler

Each component controlled by a box layout butts up against its neighboring components. If you want to have space between components, you can either add an empty border to one or both components, or insert invisible components to provide the space. You can create invisible components with the help of the Box class.

The Box class defines a nested class, Box.Filler, that is a transparent component that paints nothing, and is used to provide space between other components. However, Filler is not actually invisible, because setVisible(false) is not invoked. The Box class provides convenience methods to help you create common kinds of filler. The following table gives details about creating invisible components with Box and Box.Filler.

Type Size Constraints How to Create
rigid area
Three components with mixed X alignments and no maximum size
Box.createRigidArea(size)
glue horizontal
Three components with mixed X alignments and no maximum size
Box.createHorizontalGlue()
vertical
Three components with mixed X alignments and no maximum size
Box.createVerticalGlue()
custom Box.Filler (as specified)
new Box.Filler(minSize, prefSize,
               maxSize)

Here is how you generally use each type of filler:

Rigid area
Use this when you want a fixed-size space between two components. For example, to put 5 pixels between two components in a left-to-right box, you can use this code:
container.add(firstComponent);
container.add(Box.createRigidArea(new Dimension(5,0)));
container.add(secondComponent);
Without rigid area With rigid area

Note: The Box class provides another kind of filler for putting fixed space between components: a vertical or horizontal strut. Unfortunately, struts have unlimited maximum heights or widths (for horizontal and vertical struts, respectively). This means that if you use a horizontal box within a vertical box, for example, the horizontal box can sometimes become too tall. For this reason, we recommend that you use rigid areas instead of struts.

Glue
Use this to specify where excess space in a layout should go. Think of it as a kind of elastic glue — stretchy and expandable, yet taking up no space unless you pull apart the components that it is sticking to. For example, by putting horizontal glue between two components in a left-to-right box, you make any extra space go between those components, instead of to the right of all the components. Here is an example of making the space in a left-to-right box go between two components, instead of to the right of the components:
container.add(firstComponent);
container.add(Box.createHorizontalGlue());
container.add(secondComponent);
Without horizontal glue With glue

Custom Box.Filler
Use this to specify a component with whatever minimum, preferred, and maximum sizes you want. For example, to create some filler in a left-to-right layout that puts at least 5 pixels between two components and ensures that the container has a minimum height of 100 pixels, you could use this code:
container.add(firstComponent);
Dimension minSize = new Dimension(5, 100);
Dimension prefSize = new Dimension(5, 100);
Dimension maxSize = new Dimension(Short.MAX_VALUE, 100);
container.add(new Box.Filler(minSize, prefSize, maxSize));
container.add(secondComponent);
Without custom filler With custom filler

Fixing Alignment Problems

Two types of alignment problems sometimes occur with BoxLayout:
  • A group of components all have the same alignment, but you want to change their alignment to make them look better. For example, instead of having the centers of a group of left-to-right buttons all in a line, you might want the bottoms of the buttons to be aligned. Here is an example:

  • Two or more components controlled by a BoxLayout have different default alignments, which causes them to be mis-aligned. For example, as the following shows, if a label and a panel are in a top-to-bottom box layout, the label's left edge is, by default, aligned with the center of the panel.

    X alignment mismatch

In general, all the components controlled by a top-to-bottom BoxLayout object should have the same X alignment. Similarly, all the components controlled by a left-to-right Boxlayout should generally have the same Y alignment. You can set a JComponent's X alignment by invoking its setAlignmentX method. An alternative available to all components is to override the getAlignmentX method in a custom subclass of the component class. Similarly, you set the Y alignment of a component by invoking the setAlignmentY method or by overriding getAlignmentY.

Here is an example, taken from an application called BoxAlignmentDemo, of changing the Y alignments of two buttons so that the bottoms of the buttons are aligned:

button1.setAlignmentY(Component.BOTTOM_ALIGNMENT);
button2.setAlignmentY(Component.BOTTOM_ALIGNMENT);

Click the Launch button to run BoxAlignmentDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the BoxAlignmentDemo example

By default, most components have center X and Y alignment. However, buttons, combo boxes, labels, and menu items have a different default X alignment value: LEFT_ALIGNMENT. The previous picture shows what happens if you put a left-aligned component such as a label together with a center-aligned component in a container controlled by a top-to-bottom BoxLayout.

The BoxAlignmentDemo program gives examples of fixing mismatched alignment problems. Usually, it is as simple as making an offending button or label be center aligned. For example:

label.setAlignmentX(Component.CENTER_ALIGNMENT);

Specifying Component Sizes

As mentioned before, BoxLayout pays attention to a component's requested minimum, preferred, and maximum sizes. While you are fine-tuning the layout, you might need to adjust these sizes.

Sometimes the need to adjust the size is obvious. For example, a button's maximum size is generally the same as its preferred size. If you want the button to be drawn wider when additional space is available, then you need to change its maximum size.

Sometimes, however, the need to adjust size is not so obvious. You might be getting unexpected results with a box layout, and you might not know why. In this case, it is usually best to treat the problem as an alignment problem first. If adjusting the alignments does not help, then you might have a size problem. We'll discuss this further a bit later.

Note: Although BoxLayout pays attention to a component's maximum size, many layout managers do not. For example, if you put a button in the bottom part of a BorderLayout, the button will probably be wider than its preferred width, no matter what the button's maximum size is. BoxLayout, on the other hand, never makes a button wider than its maximum size.

You can change the minimum, preferred, and maximum sizes in two ways:

  • By invoking the appropriate setXxxSize method (which is defined by the JComponent class). For example:
    comp.setMinimumSize(new Dimension(50, 25));
comp.setPreferredSize(new Dimension(50, 25));
comp.setMaximumSize(new Dimension(Short.MAX_VALUE,
                                  Short.MAX_VALUE));
  • By overriding the appropriate getXxxSize method. For example:
    ...//in a subclass of a component class:
public Dimension getMaximumSize() {
    size = getPreferredSize();
    size.width = Short.MAX_VALUE;
    return size;
}

If you are running into trouble with a box layout and you have ruled out alignment problems, then the trouble might well be size-related. For example, if the container controlled by the box layout is taking up too much space, then one or more of the components in the container probably needs to have its maximum size restricted.

You can use two techniques to track down size trouble in a box layout:

  • Add a garish line border to the outside of the Swing components in question. This lets you see what size they really are. For example:
    comp.setBorder(BorderFactory.createCompoundBorder(
                   BorderFactory.createLineBorder(Color.red),
                   comp.getBorder()));
  • Use System.out.println to print the components' minimum, preferred, and maximum sizes, and perhaps their bounds.

The Box Layout API

The following tables list the commonly used BoxLayout and Box constructors and methods. The API for using box layouts falls into these categories:

  • Creating BoxLayout objects
  • Creating space fillers
  • Other useful methods

Creating BoxLayout Objects
Constructor or Method | Purpose
BoxLayout(Container, int) | Creates a BoxLayout instance that controls the specified Container. The integer argument specifies the axis along which the container's components should be laid out. When the container has the default component orientation, BoxLayout.LINE_AXIS specifies that the components be laid out from left to right, and BoxLayout.PAGE_AXIS specifies that the components be laid out from top to bottom.
Box(int) | Creates a Box — a container that uses a BoxLayout with the specified axis. As of release 1.3, Box extends JComponent. Before that, it was implemented as a subclass of Container.
static Box createHorizontalBox()
(in Box) 		Creates a Box that lays out its components from left to right.
static Box createVerticalBox()
(in Box) 		Creates a Box that lays out its components from top to bottom.

Creating Space Fillers
These methods are defined in the Box class.
Constructor or Method | Purpose
Component createRigidArea(Dimension) | Create a rigid component.
Component createHorizontalGlue()
Component createVerticalGlue()
Component createGlue() 		Create a glue component. Horizontal glue and vertical glue can be very useful.
Component createHorizontalStrut()
Component createVerticalStrut() 		Create a "strut" component. We recommend using rigid areas instead of struts.
Box.Filler(Dimension, Dimension, Dimension) | Creates a component with the specified minimum, preferred, and maximum sizes (with the arguments specified in that order). See the custom Box.Filler discussion, earlier in this section, for details.

Other Useful Methods
Method | Purpose
void changeShape(Dimension, Dimension, Dimension) (in Box.Filler) | Change the minimum, preferred, and maximum sizes of the recipient Box.Filler object. The layout changes accordingly.

Examples that Use Box Layouts

The following table lists some of the many examples that use box layouts.

Example | Where Described | Notes
BoxLayoutDemo2 | This page | Uses a box layout to create a centered column of components.
BoxAlignmentDemo | This page | Demonstrates how to fix common alignment problems.
BoxLayoutDemo | This page | Lets you play with alignments and maximum sizes.
ListDialog | This page | A simple yet realistic example of using both a top-to-bottom box layout and a left-to-right one. Uses horizontal glue, rigid areas, and empty borders. Also sets the X alignment of a component.
InternalFrameEventDemo | How to Write an Internal Frame Listener | Uses a top-to-bottom layout to center buttons and a scroll pane in an internal frame.
MenuGlueDemo | Customizing Menu Layout | Shows how to right-align a menu in the menu bar, using a glue component.
MenuLayoutDemo | Customizing Menu Layout | Shows how to customize menu layout by changing the menu bar to use a top-to-bottom box layout, and the popup menu to use a left-to-right box layout.
ConversionPanel.java in the Converter demo | How to Use Panels | Aligns two components in different box-layout-controlled containers by setting the components' widths to be the same, and their containers' widths to be the same.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use BorderLayout
Next page: How to Use CardLayout


How to Use CardLayout (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
How to Use CardLayout
Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.

The following figure represents a snapshot of an application that uses the CardLayout class to switch between two panels.

A snapshot of CardLayoutDemo Another snapshot of CardLayoutDemo

Click the Launch button to run CardLayoutDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the CardLayoutDemo application

The complete code of this demo is in the CardLayoutDemo.java file.

The CardLayout class manages two or more components (usually JPanel instances) that share the same display space. When using the CardLayout class, let the user choose between the components by using a combo box. The CardLayoutDemo application is an example to illustrate this feature.

Another way to accomplish the same task is to use a tabbed pane. The following picture shows a tabbed pane version of the preceding example:

A snapshot of TabDemo

Because a tabbed pane provides its own GUI, using a tabbed pane is simpler than using the CardLayout class. For example, implementing the preceding example using a tabbed pane results in a program with fewer lines of code.

Click the Launch button to run TabDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the TabDemo application

The complete code of this demo is in the TabDemo.java file.

Conceptually, each component that a CardLayout manages is like a playing card or trading card in a stack, where only the top card is visible at any time. You can choose the card that is showing in any of the following ways:

  • By asking for either the first or last card, in the order it was added to the container
  • By flipping through the deck backwards or forwards
  • By specifying a card with a specific name
The CardLayoutDemo class uses the last scheme.

The following code snippet from the CardLayoutDemo.java application creates the CardLayout object and the components it manages.

//Where instance variables are declared:
JPanel cards;
final static String BUTTONPANEL = "Card with JButtons";
final static String TEXTPANEL = "Card with JTextField";

//Where the components controlled by the CardLayout are initialized:
//Create the "cards".
JPanel card1 = new JPanel();
...
JPanel card2 = new JPanel();
...

//Create the panel that contains the "cards".
cards = new JPanel(new CardLayout());
cards.add(card1, BUTTONPANEL);
cards.add(card2, TEXTPANEL);
To add a component to a container that a CardLayout object manages, specify a string that identifies the component being added. For example, in this demo, the first panel has the string "Card with JButtons", and the second panel has the string "Card with JTextField". In this demo those strings are also used in the combo box.

To choose which component a CardLayout object shows, put additional code in your code example:

//Where the GUI is assembled:
//Put the JComboBox in a JPanel to get a nicer look.
JPanel comboBoxPane = new JPanel(); //use FlowLayout
String comboBoxItems[] = { BUTTONPANEL, TEXTPANEL };
JComboBox cb = new JComboBox(comboBoxItems);
cb.setEditable(false);
cb.addItemListener(this);
comboBoxPane.add(cb);
...
pane.add(comboBoxPane, BorderLayout.PAGE_START);
pane.add(cards, BorderLayout.CENTER);
...

//Method came from the ItemListener class implementation,
//contains functionality to process the combo box item selecting
public void itemStateChanged(ItemEvent evt) {
    CardLayout cl = (CardLayout)(cards.getLayout());
    cl.show(cards, (String)evt.getItem());
}
This example shows that to use the show method of the CardLayout class, you must set the currently visible component. The first argument in the show method is the container the CardLayout controls — that is, the container of the components the CardLayout manages. The second argument is the string that identifies the component to show. This string is the same string that was used when adding the component to the container.

The CardLayout API

The following table lists the CardLayout class methods that are used to choose a component. For each method, the first argument is the container for which the CardLayout is the layout manager (the container of the cards the CardLayout controls).

Method | Purpose
first (Container parent) | Flips to the first card of the container.
next (Container parent) | Flips to the next card of the container. If the currently visible card is the last one, this method flips to the first card in the layout.
previous (Container parent) | Flips to the previous card of the container. If the currently visible card is the first one, this method flips to the last card in the layout.
last (Container parent) | Flips to the last card of the container.
show (Container parent, String name) | Flips to the component that was added to this layout with the specified name, using the addLayoutComponent method.

Examples that Use CardLayout

Only one example in this trail uses CardLayout, and this is the CardLayoutDemo. Generally, our examples use tabbed panes instead of CardLayout, since a tabbed pane provides its own GUI.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use BoxLayout
Next page: How to Use FlowLayout


How to Use FlowLayout (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
How to Use FlowLayout
Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.
The FlowLayout class provides a very simple layout manager that is used, by default, by the JPanel objects. The following figure represents a snapshot of an application that uses the flow layout:

A snapshot of FlowLayoutDemo

Click the Launch button to run FlowLayoutDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the FlowLayoutDemo application

The complete code of this demo is in the FlowLayoutDemo.java file.

The FlowLayout class puts components in a row, sized at their preferred size. If the horizontal space in the container is too small to put all the components in one row, the FlowLayout class uses multiple rows. If the container is wider than necessary for a row of components, the row is, by default, centered horizontally within the container. To specify that the row is to aligned either to the left or right, use a FlowLayout constructor that takes an alignment argument. Another constructor of the FlowLayout class specifies how much vertical or horizontal padding is put around the components.

The code snippet below creates a FlowLayout object and the components it manages.

FlowLayout experimentLayout = new FlowLayout();

...

    compsToExperiment.setLayout(experimentLayout);

    compsToExperiment.add(new JButton("Button 1"));
    compsToExperiment.add(new JButton("Button 2"));
    compsToExperiment.add(new JButton("Button 3"));
    compsToExperiment.add(new JButton("Long-Named Button 4"));
    compsToExperiment.add(new JButton("5"));

Select either the Left to Right or Right to Left option and click the Apply orientation button to set up the component's orientation. The following code snippet applies the Left to Right components orientation to the experimentLayout.

    compsToExperiment.setComponentOrientation(
        ComponentOrientation.LEFT_TO_RIGHT);

The FlowLayout API

The following table lists constructors of the FlowLayout class.
Constructor | Purpose
FlowLayout() | Constructs a new FlowLayout object with a centered alignment and horizontal and vertical gaps with the default size of 5 pixels.
FlowLayout(int align) | Creates a new flow layout manager with the indicated alignment and horizontal and vertical gaps with the default size of 5 pixels. The alignment argument can be FlowLayout.LEADING, FlowLayout.CENTER, or FlowLayout.TRAILING. When the FlowLayout object controls a container with a left-to right component orientation (the default), the LEADING value specifies the components to be left-aligned and the TRAILING value specifies the components to be right-aligned.
FlowLayout (int align, int hgap, int vgap) | Creates a new flow layout manager with the indicated alignment and the indicated horizontal and vertical gaps. The hgap and vgap arguments specify the number of pixels to put between components.

Examples that Use FlowLayout

The following table lists code examples that use the FlowLayout class and provides links to related sections.

Example | Where Described | Notes
FlowLayoutDemo | This page | Sets up a content pane to use FlowLayout. If you set the RIGHT_TO_LEFT constant to true and recompile, you can see how FlowLayout handles a container that has a right-to-left component orientation.
CardLayoutDemo | How to Use CardLayout | Centers a component nicely in the top part of a BorderLayout, and puts the component in a JPanel that uses a FlowLayout.
ButtonDemo | How to Use Buttons, Check Boxes, and Radio Buttons | Uses the default FlowLayout of a JPanel.
TextInputDemo | How to Use Formatted Text Fields | Uses a panel with a right-aligned FlowLayout presenting two buttons.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use CardLayout
Next page: How to Use GridBagLayout


How to Use GridBagLayout (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
How to Use GridBagLayout
Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.
Here is a picture of an example that uses GridBagLayout.

A snapshot of GridBagLayoutDemo

Click the Launch button to run GridBagLayoutDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the GridBagLayoutDemo example

The code for GridBagDemo is in GridBagLayoutDemo.java.

GridBagLayout is one of the most flexible — and complex — layout managers the Java platform provides. A GridBagLayout places components in a grid of rows and columns, allowing specified components to span multiple rows or columns. Not all rows necessarily have the same height. Similarly, not all columns necessarily have the same width. Essentially, GridBagLayout places components in rectangles (cells) in a grid, and then uses the components' preferred sizes to determine how big the cells should be.

The following figure shows the grid for the preceding applet. As you can see, the grid has three rows and three columns. The button in the second row spans all the columns; the button in the third row spans the two right columns.

A snapshot of GridBagLayoutDemo with its grid

If you enlarge the window as shown in the following figure, you will notice that the bottom row, which contains Button 5, gets all the new vertical space. The new horizontal space is split evenly among all the columns. This resizing behavior is based on weights the program assigns to individual components in the GridBagLayout. You will also notice that each component takes up all the available horizontal space — but not (as you can see with button 5) all the available vertical space. This behavior is also specified by the program.

GridBagLayout shown after the user enlarged it.

The way the program specifies the size and position characteristics of its components is by specifying constraints for each component. The preferred approach to set constraints on a component is to use the Container.add variant, passing it a GridBagConstraints object, as demonstrated in the next sections.

The following sections explain the constraints you can set and provide examples.

Specifying Constraints

The following code is typical of what goes in a container that uses a GridBagLayout. You will see a more detailed example in the next section.
JPanel pane = new JPanel(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();

//For each component to be added to this container:
//...Create the component...
//...Set instance variables in the GridBagConstraints instance...
pane.add(theComponent, c);
As you might have guessed from the above example, it is possible to reuse the same GridBagConstraints instance for multiple components, even if the components have different constraints. However, it is recommended that you do not reuse GridBagConstraints, as this can very easily lead to you introducing subtle bugs if you forget to reset the fields for each new instance.
Note: The following discussion assumes that the GridBagLayout controls a container that has a left-to-right component orientation.

You can set the following GridBagConstraints instance variables:

gridx, gridy
Specify the row and column at the upper left of the component. The leftmost column has address gridx=0 and the top row has address gridy=0. Use GridBagConstraints.RELATIVE (the default value) to specify that the component be placed just to the right of (for gridx) or just below (for gridy) the component that was added to the container just before this component was added. We recommend specifying the gridx and gridy values for each component rather than just using GridBagConstraints.RELATIVE; this tends to result in more predictable layouts.

gridwidth, gridheight
Specify the number of columns (for gridwidth) or rows (for gridheight) in the component's display area. These constraints specify the number of cells the component uses, not the number of pixels it uses. The default value is 1. Use GridBagConstraints.REMAINDER to specify that the component be the last one in its row (for gridwidth) or column (for gridheight). Use GridBagConstraints.RELATIVE to specify that the component be the next to last one in its row (for gridwidth) or column (for gridheight). We recommend specifying the gridwidth and gridheight values for each component rather than just using GridBagConstraints.RELATIVE and GridBagConstraints.REMAINDER; this tends to result in more predictable layouts.

Note: GridBagLayout does not allow components to span multiple rows unless the component is in the leftmost column or you have specified positive gridx and gridy values for the component.

fill
Used when the component's display area is larger than the component's requested size to determine whether and how to resize the component. Valid values (defined as GridBagConstraints constants) include NONE (the default), HORIZONTAL (make the component wide enough to fill its display area horizontally, but do not change its height), VERTICAL (make the component tall enough to fill its display area vertically, but do not change its width), and BOTH (make the component fill its display area entirely).

ipadx, ipady
Specifies the internal padding: how much to add to the size of the component. The default value is zero. The width of the component will be at least its minimum width plus ipadx*2 pixels, since the padding applies to both sides of the component. Similarly, the height of the component will be at least its minimum height plus ipady*2 pixels.

insets
Specifies the external padding of the component -- the minimum amount of space between the component and the edges of its display area. The value is specified as an Insets object. By default, each component has no external padding.

anchor
Used when the component is smaller than its display area to determine where (within the area) to place the component. Valid values (defined as GridBagConstraints constants) are CENTER (the default), PAGE_START, PAGE_END, LINE_START, LINE_END, FIRST_LINE_START, FIRST_LINE_END, LAST_LINE_END, and LAST_LINE_START.

Here is a picture of how these values are interpreted in a container that has the default, left-to-right component orientation.

-------------------------------------------------
|FIRST_LINE_START   PAGE_START     FIRST_LINE_END|
|                                                |
|                                                |
|LINE_START           CENTER             LINE_END|
|                                                |
|                                                |
|LAST_LINE_START     PAGE_END       LAST_LINE_END|
-------------------------------------------------
Version note: The PAGE_* and *LINE_* constants were introduced in 1.4. Previous releases require values named after points of the compass. For example, NORTHEAST indicates the top-right part of the display area. We recommend that you use the new constants, instead, since they enable easier localization.

weightx, weighty
Specifying weights is an art that can have a significant impact on the appearance of the components a GridBagLayout controls. Weights are used to determine how to distribute space among columns (weightx) and among rows (weighty); this is important for specifying resizing behavior.

Unless you specify at least one non-zero value for weightx or weighty, all the components clump together in the center of their container. This is because when the weight is 0.0 (the default), the GridBagLayout puts any extra space between its grid of cells and the edges of the container.

Generally weights are specified with 0.0 and 1.0 as the extremes: the numbers in between are used as necessary. Larger numbers indicate that the component's row or column should get more space. For each column, the weight is related to the highest weightx specified for a component within that column, with each multicolumn component's weight being split somehow between the columns the component is in. Similarly, each row's weight is related to the highest weighty specified for a component within that row. Extra space tends to go toward the rightmost column and bottom row.

The next section discusses constraints in depth, in the context of explaining how the example program works.

The Example Explained

Here, again, is a picture of the GridBagLayoutDemo application.

A snapshot of GridBagLayoutDemo

Click the Launch button to run GridBagLayoutDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the GridBagLayoutDemo example

The following code creates the GridBagLayout and the components it manages. You can find the entire source file in GridBagLayoutDemo.java.

JButton button;
pane.setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints();
if (shouldFill) {
        //natural height, maximum width
        c.fill = GridBagConstraints.HORIZONTAL;
}

button = new JButton("Button 1");
if (shouldWeightX) {
           c.weightx = 0.5;
}
c.fill = GridBagConstraints.HORIZONTAL;
c.gridx = 0;
c.gridy = 0;
pane.add(button, c);

button = new JButton("Button 2");
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0.5;
c.gridx = 1;
c.gridy = 0;
pane.add(button, c);

button = new JButton("Button 3");
c.fill = GridBagConstraints.HORIZONTAL;
c.weightx = 0.5;
c.gridx = 2;
c.gridy = 0;
pane.add(button, c);

button = new JButton("Long-Named Button 4");
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 40;      //make this component tall
c.weightx = 0.0;
c.gridwidth = 3;
c.gridx = 0;
c.gridy = 1;
pane.add(button, c);

button = new JButton("5");
c.fill = GridBagConstraints.HORIZONTAL;
c.ipady = 0;       //reset to default
c.weighty = 1.0;   //request any extra vertical space
c.anchor = GridBagConstraints.PAGE_END; //bottom of space
c.insets = new Insets(10,0,0,0);  //top padding
c.gridx = 1;       //aligned with button 2
c.gridwidth = 2;   //2 columns wide
c.gridy = 2;       //third row
pane.add(button, c);

This example uses one GridBagConstraints instance for all the components the GridBagLayout manages, however in real-life situations it is recommended that you do not reuse GridBagConstraints, as this can very easily lead to you introducing subtle bugs if you forget to reset the fields for each new instance. Just before each component is added to the container, the code sets (or resets to default values) the appropriate instance variables in the GridBagConstraints object. It then adds the component to its container, specifying the GridBagConstraints object as the second argument to the add method.

For example, to make button 4 be extra tall, the example has this code:

c.ipady = 40;
And before setting the constraints of the next component, the code resets the value of ipady to the default:
c.ipady = 0;

If a component's display area is larger than the component itself, then you can specify whereabouts in the display area the component will be displayed by using the GridBagConstraints.anchor constraint. The anchor constraint's values can be absolute (north, south, east, west, and so on), or orientation-relative (at start of page, at end of line, at the start of the first line, and so on), or relative to the component's baseline. For a full list of the possible values of the anchor constraint, including baseline-relative values,see the API documentation for GridBagConstraints.anchor. You can see in the code extract above that Button 5 specifies that it should be displayed at the end of the display area by setting an anchor at GridBagConstraints.PAGE_END.

Note: The Tutorial's examples used to specify the constraints object a different way, which you might see in other programs as well. Rather than specifying the constraints with the add method, our examples used to invoke the setConstraints method on the GridBagLayout object. For example:
GridBagLayout gridbag = new GridBagLayout();
pane.setLayout(gridbag);
...
gridbag.setConstraints(button, c);
pane.add(button);
However, we recommend you use the Container.add method since it makes for cleaner code than if you were to use setConstraints.
Here is a table that shows all the constraints for each component in GridBagLayoutDemo's content pane. Values that are not the default are marked in boldface. Values that are different from those in the previous table entry are marked in italics.

Component Constraints
All components
ipadx = 0
fill = GridBagConstraints.HORIZONTAL
Button 1
ipady = 0
weightx = 0.5
weighty = 0.0
gridwidth = 1
anchor = GridBagConstraints.CENTER
insets = new Insets(0,0,0,0)
gridx = 0
gridy = 0
Button 2
weightx = 0.5
gridx = 1
gridy = 0
Button 3
weightx = 0.5
gridx = 2
gridy = 0
Button 4
ipady = 40
weightx = 0.0
gridwidth = 3
gridx = 0
gridy = 1
Button 5
ipady = 0
weightx = 0.0
weighty = 1.0
anchor = GridBagConstraints.PAGE_END
insets = new Insets(10,0,0,0)
gridwidth = 2
gridx = 1
gridy = 2

GridBagLayoutDemo has two components that span multiple columns (buttons 4 and 5). To make button 4 tall, we added internal padding (ipady) to it. To put space between buttons 4 and 5, we used insets to add a minimum of 10 pixels above button 5, and we made button 5 hug the bottom edge of its cell.

All the components in the pane container are as wide as possible, given the cells that they occupy. The program accomplishes this by setting the GridBagConstraints fill instance variable to GridBagConstraints.HORIZONTAL, leaving it at that setting for all the components. If the program did not specify the fill, the buttons would be at their natural width, like this:

GridBagLayoutDemo with default fill values.

When you enlarge GridBagLayoutDemo's window, the columns grow proportionately. This is because each component in the first row, where each component is one column wide, has weightx = 1.0. The actual value of these components' weightx is unimportant. What matters is that all the components, and consequently, all the columns, have an equal weight that is greater than 0. If no component managed by the GridBagLayout had weightx set, then when the components' container was made wider, the components would stay clumped together in the center of the container, like this:

GridBagLayoutDemo with default weightx values and enlarged by the user.

If the container is given a size that is smaller or bigger than the prefered size, then any space is distributed according to the GridBagContainer weights.

Note that if you enlarge the window, the last row is the only one that gets taller. This is because only button 5 has weighty greater than zero.

The GridBagLayout API

The GridBagLayout and GridBagConstraints classes each have only one constructor, with no arguments. Instead of invoking methods on a GridBagConstraints object, you manipulate its instance variables, as described in Specifying Constraints. Generally, the only method you invoke on a GridBagLayout object is setConstraints, as demonstrated in The Example Explained.

Examples that Use GridBagLayout

You can find examples of using GridBagLayout throughout this tutorial. The following table lists a few.

Example | Where Described | Notes
GridBagLayoutDemo | This section | Uses many features — weights, insets, internal padding, horizontal fill, exact cell positioning, multi-column cells, and anchoring (component positioning within a cell).
TextSamplerDemo | Using Text Components | Aligns two pairs of labels and text fields, plus adds a label across the full width of the container.
ContainerEventDemo | How to Write a Container Listener | Positions five components within a container, using weights, fill, and relative positioning.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use FlowLayout
Next page: How to Use GridLayout


How to Use GridLayout (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
How to Use GridLayout
Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.
The following figure represents a snapshot of an application that uses the GridLayout class.

A snapshot of GridLayoutDemo

Click the Launch button to run GridLayoutDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the GridLayoutDemo application

The complete code of this demo is in the GridLayoutDemo.java file.

A GridLayout object places components in a grid of cells. Each component takes all the available space within its cell, and each cell is exactly the same size. If the GridLayoutDemo window is resized, the GridLayout object changes the cell size so that the cells are as large as possible, given the space available to the container.

The code snippet below creates the GridLayout object and the components it manages.

GridLayout experimentLayout = new GridLayout(0,2);

...

    compsToExperiment.setLayout(experimentLayout);

    compsToExperiment.add(new JButton("Button 1"));
    compsToExperiment.add(new JButton("Button 2"));
    compsToExperiment.add(new JButton("Button 3"));
    compsToExperiment.add(new JButton("Long-Named Button 4"));
    compsToExperiment.add(new JButton("5"));
The constructor of the GridLayout class creates an instance that has two columns and as many rows as necessary.

Use combo boxes to set up how much vertical or horizontal padding is put around the components. Then click the Apply gaps button. The following code snippet shows how your selection is processed by using the setVgap and setHgap methods of the GridLayout class:

applyButton.addActionListener(new ActionListener(){
            public void actionPerformed(ActionEvent e){
                //Get the horizontal gap value
                String horGap = (String)horGapComboBox.getSelectedItem();
                //Get the vertical gap value
                String verGap = (String)verGapComboBox.getSelectedItem();
                //Set up the horizontal gap value
                experimentLayout.setHgap(Integer.parseInt(horGap));
                //Set up the vertical gap value
                experimentLayout.setVgap(Integer.parseInt(verGap));
                //Set up the layout of the buttons
                experimentLayout.layoutContainer(compsToExperiment);
            }
        });

The GridLayout API

The following table lists constructors of the GridLayout class that specify the number of rows and columns.

The GridLayout class constructors
Constructor | Purpose
GridLayout(int rows, int cols) | Creates a grid layout with the specified number of rows and columns. All components in the layout are given equal size. One, but not both, of rows and cols can be zero, which means that any number of objects can be placed in a row or in a column.
GridLayout(int rows, int cols, int hgap, int vgap) | Creates a grid layout with the specified number of rows and columns. In addition, the horizontal and vertical gaps are set to the specified values. Horizontal gaps are places between each of columns. Vertical gaps are placed between each of the rows.

The GridLayout class has two constructors:

Examples that Use GridLayout

The following table lists code examples that use the GridLayout class and provides links to related sections.

Example | Where Described | Notes
GridLayoutDemo | This page | Uses a 2-column grid.
ComboBoxDemo2 | How to Use Combo Boxes | One of many examples that use a 1x1 grid to make a component as large as possible.
LabelDemo | How to Use Labels | Uses a 3-row grid.
DragPictureDemo | Introduction to DnD | Uses a 4-row grid to present 12 components that display photographs.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use GridBagLayout
Next page: How to Use GroupLayout


How to Use GroupLayout (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
How to Use GroupLayout

GroupLayout is a layout manager that was developed for GUI builders such as Matisse, the GUI builder provided with the NetBeans IDE. Although the layout manager was originally designed to suit the GUI builder needs, it also works well for manual coding. This discussion will teach you how GroupLayout works and show you how you can use GroupLayout to build GUIs, whether you choose to use a GUI builder like Matisse or write your own code.

Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.

Design Principle: Independent Dimensions

GroupLayout works with the horizontal and vertical layouts separately. The layout is defined for each dimension independently. You do not need to worry about the vertical dimension when defining the horizontal layout, and vice versa, as the layout along each axis is totally independent of the layout along the other axis.

When focusing on just one dimension, you only have to solve half the problem at one time. This is easier than handling both dimensions at once. This means, of course, that each component needs to be defined twice in the layout. If you forget to do this, GroupLayout will generate an exception.

Layout Organization: Hierarchical Groups

GroupLayout uses two types of arrangements -- sequential and parallel, combined with hierarchical composition.

  1. With sequential arrangement, the components are simply placed one after another, just like BoxLayout or FlowLayout would do along one axis. The position of each component is defined as being relative to the preceding component.

  2. The second way places the components in parallel—on top of each other in the same space. They can be baseline-, top-, or bottom-aligned along the vertical axis. Along the horizontal axis, they can be left-, right-, or center-aligned if the components are not all the same size.

Usually, components placed in parallel in one dimension are in a sequence in the other, so that they do not overlap.

What makes these two arrangements powerful is that they can be nested hierarchically. For this purpose GroupLayout defines layout groups. A group is either sequential or parallel and may contain components, other groups, and gaps (discussed below).

The size of a sequential group is the sum of the sizes of the contained elements, and the size of a parallel group corresponds to the size of the largest element (although, depending on the elements and where the baseline lands, the size of a baseline-aligned group may be a bit larger than the largest element).

Defining a layout means defining how the components should be grouped by combining the sequential and parallel arrangements.

Let us use a simple example to see how it works in practice.

An Example

Let us start with something simple, just three components in a row:

Three components in a row.

We will express this layout using groups. Starting with the horizontal axis it is easy to see there is a sequential group of 3 components arranged from left to right. Along the vertical axis there is a parallel group of the same 3 components with the same location, size, and baseline:

In pseudo code, the layout specification might look like this (the real code is in the Writing Code section below):

horizontal layout = sequential group { c1, c2, c3 }
vertical layout = parallel group (BASELINE) { c1, c2, c3 }

This illustrates a principle mentioned earlier: components grouped sequentially in one dimension usually form a parallel group in the other dimension.

Now let us add one more component, C4, left-aligned with C3:

Along the horizontal axis the new component occupies the same horizontal space as C3 so that it forms a parallel group with C3. Along the vertical axis C4 forms a sequential group with the original parallel group of the three components.

In pseudo code, the layout specification now looks like this:

horizontal layout = sequential group { c1, c2, parallel group (LEFT) { c3, c4 } }
vertical layout = sequential group { parallel group (BASELINE) { c1, c2, c3 }, c4 }

Now you understand the most important aspects of designing layouts with GroupLayout. There are just a few more details to explain: how to add gaps, how to define size and resize behavior, how to define justified layout, and how to write real code.

Gaps

A gap can be thought of as an invisible component of a certain size. Gaps of arbitrary size can be added to groups just like components or other groups. Using gaps you can precisely control the distance between components or from the container border.

GroupLayout also defines automatic gaps that correspond to preferred distances between neighboring components (or between a component and container border). The size of such a gap is computed dynamically based on the look and feel the application is using (the LayoutStyle class is used for this). There are two advantages to using automatic (preferred) gaps: you do not have to specify the pixel sizes of the gaps, and they automatically adjust to the look and feel the UI runs with, reflecting the actual look and feel guidelines.

GroupLayout distinguishes between (a) the preferred gap between two components and (b) the preferred gap between a component and the container border. There are corresponding methods in the GroupLayout API for adding these gaps (addPreferredGap and addContainerGap). There are three types of component gaps: related, unrelated and indented. The LayoutStyle.ComponentPlacement enum defines corresponding constants to be used as parameters of the addPreferredGap method: RELATED, UNRELATED and INDENT. The difference between related and unrelated gaps is just in size—the distance between unrelated components is a bit bigger. Indented represents a preferred horizontal distance of two components when one of them is positioned underneath the second with an indent.

As mentioned above, GroupLayout can insert gaps automatically—if you do not add your own gaps explicitly, it adds the related preferred gaps for you. This is not the default behavior, however. You have to turn this feature on by invoking setAutoCreateGaps(true) and setAutoCreateContainerGaps(true) on the GroupLayout. Then you will get correct spacing automatically.

Writing Code

Now, let us take a look at the actual code to create the layout described above.

Let us assume we have a container named panel and the same four components already presented (c1, c2, c3, and c4). First, we create a new GroupLayout object and associate it with the panel:

GroupLayout layout = new GroupLayout(panel);
 panel.setLayout(layout);

We specify automatic gap insertion:

layout.setAutoCreateGaps(true);
layout.setAutoCreateContainerGaps(true);

Then, we define the groups and add the components. We establish a root group for each dimension using the setHorizontalGroup and setVerticalGroup methods. Groups are created via createSequentialGroup and createParallelGroup methods. Components are added to groups by using the addComponent method.

layout.setHorizontalGroup(
   layout.createSequentialGroup()
      .addComponent(c1)
      .addComponent(c2)
      .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
           .addComponent(c3)
           .addComponent(c4))
);
layout.setVerticalGroup(
   layout.createSequentialGroup()
      .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
           .addComponent(c1)
           .addComponent(c2)
           .addComponent(c3))
      .addComponent(c4)
);

You can specify the alignment for parallel groups. It can be one of the following constants defined in the GroupLayout.Alignment enum: LEADING, TRAILING, CENTER, and BASELINE. These constants are used for both dimensions and depend on whether the component orientation is left-to-right or right-to-left (top-to-bottom or bottom-to-top). For example, if the horizontal (vertical) component orientation is left-to-right (top-to-bottom) LEADING means left (top) while TRAILING means right (bottom). CENTER means "centered" in both dimensions. If you do not specify the alignment, LEADING will be used. The BASELINE alignment is valid only in the vertical dimension.

Note: Alignment in the layout of a group only has meaning for components of different sizes. Components of the same size will be automatically aligned for each of the GroupLayout.Alignment constants.

Some comments about the code:

  • You do not need to add the component directly to the container—that is done for you implicitly when using one of the addComponent methods.

  • Note the chained calls of the addComponent methods used to fill the groups. The addComponent method always returns the group on which it is called. Thanks to this you do not need to use local variables to hold the groups.

  • It is a good idea to indent the code so it is easy to see the hierarchical structure of the groups. Give each component a new line, add one level of indent for each new group in the hierarchy. A good source editor will help you with pairing the parenthesis to close the createXXXGroup methods. By following these simple rules, it is easier to add a new component or remove an existing one.

Component Size and Resizability

There is no limit on the number of resizable components in a layout.

The size of each component in a GroupLayout is constrained by three values; minimum size, preferred size and maximum size. These sizes control how the component resizes within the layout. The GroupLayout.addComponent(...) method allows the size constraints to be specified.

If not specified explicitly, the layout asks the component for its default sizes (by using the component's getMinimumSize(), getPreferredSize() and getMaximumSize() methods). You do not need to specify anything for most of the components, like making JTextField resizable or JButton fixed, because the components themselves have the desired resizing behavior as default. On the other hand you can override the default behavior. For example you can make a JTextField fixed or JButton resizable.

GroupLayout defines constants that provide precise control over resize behavior. They can be used as parameters in the addComponent(Component comp, int min, int pref, int max) method. Here are two examples:

  1. To force a component to be resizable (allow shrinking and growing):

    group.addComponent(component, 0, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) ...

    This allows the component to resize between zero size (minimum) to any size (Short.MAX_VALUE as maximum size means "infinite"). If we wanted the component not to shrink below its default minimum size, we would use GroupLayout.DEFAULT_SIZE instead of 0 in the second parameter.

  2. To make a component fixed size (suppress resizing):
    group.addComponent(component, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE,
          GroupLayout.PREFERRED_SIZE) ...

In these examples the initial size of the component is not altered, its default size is the component's preferred size. If we wanted a specific size for the component, we would specify it in the second parameter instead of using GroupLayout.DEFAULT_SIZE.

Resizable gaps

Specifying size and resizability applies to gaps as well, including the preferred ones. For example, you can specify a preferred gap between two components that acts like a spring pushing the components away from each other (to the opposite sides of the container). The preferred distance of the two components is only used as the minimum size of the gap. See the following snippet:

layout.createSequentialGroup()
    .addComponent(c1)
    .addPreferredGap(LayoutStyle.ComponentPlacement.RELATED,
                     GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    .addComponent(c2);

Sizing in Parallel Groups

Resizable elements placed in a parallel group are stretched to fill the space of the group determined by the largest element in the group, so they end up aligned with the same size. GroupLayout also provides control over whether the enclosing parallel group itself should resize. If group resizing is suppressed, it prevents the contained elements from growing over the preferred size of the group. This way you can make a block of components align on both sides, or constrain individual components to have the same size.

Let us try to achieve the same size for two components from our example (c3 and c4 in the horizontal dimension):

layout.createParallelGroup(GroupLayout.Alignment.LEADING, false)
  .addComponent(c3, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
  .addComponent(c4, GroupLayout.DEFAULT_SIZE, GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE);

The underlying mechanism works as follows:

  1. The size of the parallel group is set to the preferred size of the largest element; so to the preferred size of c4 in our example.

  2. Resizable elements are stretched to the size of the group. In our example, only c3 is effectively stretched, the size of c4 already corresponds to the size of the group.

As a result, c3 and c4 would have the same width. The components would not resize further because the parallel group itself is not resizable (the second parameter of the createParallelGroup method, above, is false).

Question for attentive readers: Why do we define both components in the parallel group as resizable in this example? It seems enough to have just c3 resizable since c4 is not stretched anyway...

The answer is: because of platform and localization independence. Otherwise we would have to rely on that c4 component always being bigger than c3. But this may change when the application runs on different platform or is translated to another language. By having both components resizeable they adjust to each other, no matter which one is bigger at a given moment.

Making Components the Same Size

The previous case is special because the components are in the same parallel group. But what if we wanted unrelated components to have the same size? Clearly, the same size cannot always be ensured by grouping. The OK and Cancel buttons in a row at the bottom of a dialog are a good example. For this purpose GroupLayout provides a linkSize method. This method allows the size of arbitrary components to be linked regardless of where they are placed. The resulting size of the linked components is set according to the largest component. For example:

layout.linkSize(SwingConstants.HORIZONTAL, c3, c4);

In this example, the size is linked selectively for the horizontal dimension.

Runtime Changes to Your GUI

There are two important methods that you can use to make changes to your GUI at runtime, replace() and setHonorsVisibility(). Using these two methods, you can exchange components or change the visibility of components at runtime and have the GUI rearrange itself accordingly.

replace(Component existingComponent, Component newComponent) replaces an existing component with a new one. One of the common operations needed for dynamic layouts is the ability to replace components like this. For example, perhaps a check box toggles between a component displaying a graph or a tree. GroupLayout makes this scenario simple with the replace() method. You can swap components without recreating all the groups.

Another common operation in user interfaces is to dynamically change the visibility of components. Perhaps components are shown only as a user completes earlier portions of a form. To avoid components shuffling around in such a scenario, space should be taken up regardless of the visibility of the components. GroupLayout offers two ways to configure how invisible components are treated. The setHonorsVisibility(boolean) method globally sets how invisible components are handled. A value of true, the default, indicates invisible components are treated as if they are not there. On the other hand, a value of false provides space for invisible components, treating them as though they were visible. The setHonorsVisibility(Component,Boolean) method can be used to configure the behavior at the level of a specific component. To determine how visibility is handled, GroupLayout first checks if a value has been specified for the Component, if not, it checks the setting of the global property.

Some history: GroupLayout in the Java Standard Edition 6 consists of three distinct bodies of work: the ability to get the baseline for a component, the ability to get the preferred gap between components (LayoutStyle), and GroupLayout. This work was originally done as an open source project at http://swing-layout.dev.java.net

NetBeans 5.0 supports GroupLayout by way of the swing-layout project. Because of the success of this work, all three portions have been rolled into GroupLayout in Java Standard Edition version 6. The main difference between the GroupLayout in Java SE 6 and swing-layout is in the package name and method names. NetBeans 5.5 provides the ability to target either the GroupLayout in Java SE 6, or the GroupLayout in swing-layout. Which version NetBeans targets is determined by the version of the Java platform your project targets. A project targeting Java SE 6 uses the GroupLayout in Java SE, otherwise GroupLayout in swing-layout is used.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use GridLayout
Next page: A GroupLayout Example


A GroupLayout Example (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Section: How to Use GroupLayout
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
A GroupLayout Example
Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.
As an example of GUI creation with GroupLayout, let us create a layout for this "Find" dialog box:

Horizontal layout

Examining the horizontal dimension from left to right, we can see there are 3 groups in a sequence. The first one is actually not a group, just a component -- the label. The second one is a group containing the text field and the check boxes (we will decompose it later). And the third is a group of the two buttons. As illustrated here:

Let us sketch out the sequential group in code. Note that GroupLayout.Alignment.LEADING corresponds to left alignment in the horizontal dimension. Also note we do not specify gaps, assuming the gap auto-insertion feature is turned on.

layout.setHorizontalGroup(layout.createSequentialGroup()
    .addComponent(label)
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
);

Now let us decompose the group in the middle. This is the hardest one. There is a text field in parallel with a sequence of two parallel groups each containing two check boxes. See the following illustration:

Let us add the corresponding code:

layout.setHorizontalGroup(layout.createSequentialGroup()
    .addComponent(label)
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
         .addComponent(textField)
         .addGroup(layout.createSequentialGroup()
              .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                  .addComponent(caseCheckBox)
                  .addComponent(wholeCheckBox))
              .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                  .addComponent(wrapCheckBox)
                  .addComponent(backCheckBox))))
     .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
);

We want the text field to be resizable, but that happens automatically since JTextField returns the right maximum size by default.

The remaining group on the right is trivial: it contains just two buttons. Here is the code:

layout.setHorizontalGroup(layout.createSequentialGroup()
    .addComponent(label)
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addComponent(textField)
        .addGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addComponent(caseCheckBox)
                .addComponent(wholeCheckBox))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addComponent(wrapCheckBox)
                .addComponent(backCheckBox))))
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addComponent(findButton)
        .addComponent(cancelButton))
);

And finally, we would like the buttons to be always the same size, so let us link them:

layout.linkSize(SwingConstants.HORIZONTAL, findButton, cancelButton);

Now we are done with the horizontal dimension. Let us switch to the vertical dimension. From now, we will only need to think about the y axis.

Vertical layout

In the vertical dimension, we examine the layout from top to bottom. We definitely want all the components on the first line aligned on the baseline. So along the vertical axis there is a sequence of the baseline group, followed by a group of the remaining components. See the following picture.

Let us sketch out the code. First, we need to define two parallel groups. Note that GroupLayout.Alignment.LEADING corresponds to the top alignment in the vertical dimension.

layout.setVerticalGroup(layout.createSequentialGroup()
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE))
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
);

We can fill the baseline group right away:

layout.setVerticalGroup(layout.createSequentialGroup()
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
        .addComponent(label)
        .addComponent(textField)
        .addComponent(findButton))
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING))
);

Now let us look at the bottom group. Note the Cancel button is not on a shared baseline with the check boxes; it is aligned at the top. So the second parallel group comprises the button and a sequential group of two baseline groups with check boxes:

The corresponding code looks as follows:

layout.setVerticalGroup(layout.createSequentialGroup()
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
        .addComponent(label)
        .addComponent(textField)
        .addComponent(findButton))
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(caseCheckBox)
                .addComponent(wrapCheckBox))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(wholeCheckBox)
                .addComponent(backCheckBox)))
        .addComponent(cancelButton))
);

So, we have created a complete layout, including resize behavior, without specifying a single number in pixels—a true cross platform layout. Note that we do not need to specify gaps between components, we get correct spacing automatically and according to the look and feel guidelines. Here is the complete code for the Find dialog's layout:

GroupLayout layout = new GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setAutocreateGaps(true);
layout.setAutocreateContainerGaps(true);

layout.setHorizontalGroup(layout.createSequentialGroup()
    .addComponent(label)
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addComponent(textField)
        .addGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addComponent(caseCheckBox)
                .addComponent(wholeCheckBox))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
                .addComponent(wrapCheckBox)
                .addComponent(backCheckBox))))
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addComponent(findButton)
        .addComponent(cancelButton))
);
layout.linkSize(SwingConstants.HORIZONTAL, findButton, cancelButton);

layout.setVerticalGroup(layout.createSequentialGroup()
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
        .addComponent(label)
        .addComponent(textField)
        .addComponent(findButton))
    .addGroup(layout.createParallelGroup(GroupLayout.Alignment.LEADING)
        .addGroup(layout.createSequentialGroup()
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(caseCheckBox)
                .addComponent(wrapCheckBox))
            .addGroup(layout.createParallelGroup(GroupLayout.Alignment.BASELINE)
                .addComponent(wholeCheckBox)
                .addComponent(backCheckBox)))
        .addComponent(cancelButton))
);

Here is the complete Find.java file. You can compile and run it. Try resizing the dialog horizontally to see how the layout automatically adjusts to the new size.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use GroupLayout
Next page: How to Use SpringLayout


How to Use SpringLayout (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
How to Use SpringLayout
Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.
The SpringLayout class was added in JDK version 1.4 to support layout in GUI builders. SpringLayout is a very flexible layout manager that can emulate many of the features of other layout managers. SpringLayout is, however, very low-level and as such you really should only use it with a GUI builder, rather than attempting to code a spring layout manager by hand.

This section begins with a simple example showing all the things you need to remember to create your first spring layout — and what happens when you forget them! Later it presents utility methods that let you lay out components in a couple of different types of grids.

Here are pictures of some of the layouts we will cover:

The SpringBox application uses a SpringLayout to produce something similar to what a BoxLayout would produce.

The SpringForm application has 5 rows of label-textfield pairs.

The SpringCompactGrid application presents components in a grid without forcing all components to be the same size..

How Spring Layouts Work

Spring layouts do their job by defining directional relationships, or constraints, between the edges of components. For example, you might define that the left edge of one component is a fixed distance (5 pixels, say) from the right edge of another component.

In a SpringLayout, the position of each edge is dependent on the position of just one other edge. If a constraint is subsequently added to create a new binding for an edge, the previous binding is discarded and the edge remains dependent on a single edge.

Unlike many layout managers, SpringLayout does not automatically set the location of the components it manages. If you hand-code a GUI that uses SpringLayout, remember to initialize component locations by constraining the west/east and north/south locations. Depending on the constraints you use, you may also need to set the size of the container explicitly.

Components define edge properties, which are connected by Spring instances. Each spring has four properties — its minimum, preferred, and maximum values, and its actual (current) value. The springs associated with each component are collected into a SpringLayout.Constraints object.

An instance of the Spring class holds three properties that characterize its behavior: the minimum, preferred, and maximum values. Each of these properties may be involved in defining its fourth, value, property based on a series of rules.

An instance of the Spring class can be visualized as a mechanical spring that provides a corrective force as the spring is compressed or stretched away from its preferred value. This force is modelled as linear function of the distance from the preferred value, but with two different constants -- one for the compressional force and one for the tensional one. Those constants are specified by the minimum and maximum values of the spring such that a spring at its minimum value produces an equal and opposite force to that which is created when it is at its maximum value. The difference between the preferred and minimum values, therefore, represents the ease with which the spring can be compressed. The difference between its maximum and preferred values indicates the ease with which the Spring can be extended.

Based on this, a SpringLayout can be visualized as a set of objects that are connected by a set of springs on their edges.

Example: SpringDemo

This section takes you through the typical steps of specifying the constraints for a container that uses SpringLayout. The first example, SpringDemo1.java, is an extremely simple application that features a label and a text field in a content pane controlled by a spring layout. Here is the relevant code:

public class SpringDemo1 {
    public static void main(String[] args) {
        ...
        Container contentPane = frame.getContentPane();
        SpringLayout layout = new SpringLayout();
        contentPane.setLayout(layout);
        contentPane.add(new JLabel("Label: "));
        contentPane.add(new JTextField("Text field", 15));
        ...
        frame.pack();
        frame.setVisible(true);
    }
}

Click the Launch button to run SpringDemo1 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SpringDemo1 example

Here is what the GUI looks like when it first comes up:

SpringDemo1 -- the parent has no initial size!

Here is what it looks like when it is resized to be bigger:

SpringDemo1 -- all the components are at (0, 0)!

Obviously, we have some problems. Not only does the frame come up way too small, but even when it is resized the components are all located at (0,0). This happens because we have set no springs specifying the components' positions and the width of the container. One small consolation is that at least the components are at their preferred sizes — we get that for free from the default springs created by SpringLayout for each component.

Our next example, SpringDemo2.java, improves the situation a bit by specifying locations for each component.Click the Launch button to run SpringDemo2 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SpringDemo2 example

In this example, we will specify that the components should appear in a single row, with 5 pixels between them. The following code specifies the location of the label:

//Adjust constraints for the label so it's at (5,5).
layout.putConstraint(SpringLayout.WEST, label,
                     5,
                     SpringLayout.WEST, contentPane);
layout.putConstraint(SpringLayout.NORTH, label,
                     5,
                     SpringLayout.NORTH, contentPane);
The first putConstraint call specifies that the label's left (west) edge should be 5 pixels from its container's left edge. This translates to an x coordinate of 5. The second putConstraint call sets up a similar relationship between the top (north) edges of the label and its container, resulting in a y coordinate of 5.

Here is the code that sets up the location of the text field:

//Adjust constraints for the text field so it's at
//(<label's right edge> + 5, 5).
layout.putConstraint(SpringLayout.WEST, textField,
                     5,
                     SpringLayout.EAST, label);
layout.putConstraint(SpringLayout.NORTH, textField,
                     5,
                     SpringLayout.NORTH, contentPane);

The first putConstraint call makes the text field's left (west) edge be 5 pixels away from the label's right (east) edge. The second putConstraint call is just like the second call in the first snippet, and has the same effect of setting the component's y coordinate to 5.

The previous example still has the problem of the container coming up too small. But when we resize the window, the components are in the right place:

SpringDemo2 -- at least now all the components are in the right position!

To make the container initially appear at the right size, we need to set the springs that define the right (east) and bottom (south) edges of the container itself. No constraints for the right and bottom container edges are set by default. The size of the container is defined by setting these constraints. SpringDemo3.java shows how to do this. Click the Launch button to run SpringDemo3 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SpringDemo3 example

Here is the code that sets the container's springs:

layout.putConstraint(SpringLayout.EAST, contentPane,
                     5,
                     SpringLayout.EAST, textField);
layout.putConstraint(SpringLayout.SOUTH, contentPane,
                     5,
                     SpringLayout.SOUTH, textField);

The first putConstraint call makes the container's right edge be 5 pixels to the right of the text field's right edge. The second one makes its bottom edge be 5 pixels beyond the bottom edge of the tallest component (which, for simplicity's sake, we've assumed is the text field).

Finally, the window comes up at the right size:

SpringDemo3 -- the parent now HAS a correct initial size!

When we make the window larger we can see the spring layout in action, distributing the extra space between the available components.

In this case the spring layout has chosen to give all the extra space to the text field. Although it seems like the spring layout treats labels and text fields differently, spring layout has no special knowledge of any Swing or AWT components. It relies on the values of a component's minimum, preferred, and maximum size properties. The next section discusses how spring layout uses these properties, and why they can cause uneven space distribution.

Springs and Component Size

A SpringLayout object automatically installs Springs for the height and width of each component that the SpringLayout controls. These springs are essentially covers for the component’s getMinimumSize, getPreferredSize, and getMaximumSize methods. By "covers" we mean that not only are the springs initialized with the appropriate values from these methods, but also that the springs track those values. For example, the Spring object that represents the width of a component is a special kind of spring that simply delegates its implementation to the relevant size methods of the component. That way the spring stays in sync with the size methods as the characteristics of the component change.

When a component's getMaximumSize and getPreferredSize methods return the same value, SpringLayout interprets this as meaning that the component should not be stretched. JLabel and JButton are examples of components implemented this way. For this reason, the label in the SpringDemo3 example does not stretch.

The getMaximumSize method of some components, such as JTextField, returns the value Integer.MAX_VALUE for the width and height of its maximum size, indicating that the component can grow to any size. For this reason, when the SpringDemo3 window is enlarged, SpringLayout distributes all the extra space to the only springs that can grow — those determining the size of the text field.

More About the SpringLayout API

The SpringDemo examples used the SpringLayout method putConstraint to set the springs associated with each component. The putConstraint method is a convenience method that lets you modify a component's constraints without needing to use the full spring layout API. Here, again, is the code from SpringDemo3 that sets the location of the label:
layout.putConstraint(SpringLayout.WEST, label,
                     5,
                     SpringLayout.WEST, contentPane);
layout.putConstraint(SpringLayout.NORTH, label,
                     5,
                     SpringLayout.NORTH, contentPane);
Here is equivalent code that uses the SpringLayout.Constraints and Spring classes directly:
SpringLayout.Constraints  contentPaneCons =
    layout.getConstraints(contentPane);
contentPaneCons.setX(Spring.sum(Spring.constant(5),
                          contentPaneCons
                          .getConstraint(SpringLayout.WEST)));
contentPaneCons.setY(Spring.sum(Spring.constant(5),
                          contentPaneCons
                          .getConstraint(SpringLayout.NORTH)));
To see the entire demo converted to use this API, look at SpringDemo4.java. That file also includes a more polished (and much longer) version of the code that sets the container's size. Click the Launch button to run SpringDemo4 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SpringDemo4 example

As the preceding snippets imply, SpringLayout and SpringLayout.Constraints tend to use different conventions for describing springs. The SpringLayout API uses edges to define its constraints. Springs connect edges to establish linear relations between them. Edges are defined by components, using the following constants:

  • SpringLayout.NORTH specifies the top edge of a component's bounding rectangle.
  • SpringLayout.SOUTH specifies the bottom edge of a component's bounding rectangle.
  • SpringLayout.EAST specifies the right edge of a component's bounding rectangle.
  • SpringLayout.WEST specifies the left edge of a component's bounding rectangle.
  • SpringLayout.BASELINE specifies the baseline of a component.
  • SpringLayout.HORIZONTAL_CENTER specifies the horizontal center of a component's bounding rectangle.
  • SpringLayout.VERTICAL_CENTER specifies the vertical center of a component's bounding rectangle.
Edges differ from Spring objects The SpringLayout.Constraints class knows about edges, but only has Spring objects for the following properties:
  • x
  • y
  • width
  • height
Each Constraints object maintains the following relationships between its springs and the edges they represent:
 west = x
north = y
 east = x + width
south = y + height

If you are confused, do not worry. The next section presents utility methods you can use to accomplish some common layout tasks without knowing anything about the spring layout API.

Utility Methods for Grids

Because the SpringLayout class was created for GUI builders, setting up individual springs for a layout can be cumbersome to code by hand. This section presents a couple of methods you can use to install all the springs needed to lay out a group of components in a grid. These methods emulate some of the features of the GridLayout, GridBagLayout, and BoxLayout classes.

The two methods, called makeGrid and makeCompactGrid, are defined in SpringUtilities.java. Both methods work by grouping the components together into rows and columns and using the Spring.max method to make a width or height spring that makes a row or column big enough for all the components in it. In the makeCompactGrid method the same width or height spring is used for all components in a particular column or row, respectively. In the makeGrid method, by contrast, the width and height springs are shared by every component in the container, forcing them all to be the same size. Furthermore, factory methods are provided by Spring for creating different kinds of springs, including springs that depend on other springs.

Let us see these methods in action. Our first example, implemented in the source file SpringGrid.java, displays a bunch of numbers in text fields. The center text field is much wider than the others. Just as with GridLayout, having one large cell forces all the cells to be equally large. Click the Launch button to run SpringGrid using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SpringGrid example

Here is the code that creates and lays out the text fields in SpringGrid:

JPanel panel = new JPanel(new SpringLayout());
for (int i = 0; i < 9; i++) {
    JTextField textField = new JTextField(Integer.toString(i));
    ...//when i==4, put long text in the text field...
    panel.add(textField);
}
...
SpringUtilities.makeGrid(panel,
                         3, 3, //rows, cols
                         5, 5, //initialX, initialY
                         5, 5);//xPad, yPad

Now let us look at an example, in the source file SpringCompactGrid.java, that uses the makeCompactGrid method instead of makeGrid. This example displays lots of numbers to show off spring layout's ability to minimize the space required. Click the Launch button to run SpringCompactGrid using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SpringCompactGrid example

Here is what the SpringCompactGrid GUI looks like:

Here is the code that creates and lays out the text fields in SpringCompactGrid:

JPanel panel = new JPanel(new SpringLayout());

int rows = 10;
int cols = 10;
for (int r = 0; r < rows; r++) {
    for (int c = 0; c < cols; c++) {
        int anInt = (int) Math.pow(r, c);
        JTextField textField =
                new JTextField(Integer.toString(anInt));
        panel.add(textField);
    }
}

//Lay out the panel.
SpringUtilities.makeCompactGrid(panel, //parent
                                rows, cols,
                                3, 3,  //initX, initY
                                3, 3); //xPad, yPad

One of the handiest uses for the makeCompactGrid method is associating labels with components, where the labels are in one column and the components in another. The file SpringForm.java uses makeCompactGrid in this way, as the following figure demonstrates.

Click the Launch button to run SpringForm using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SpringForm example

Here is the code that creates and lays out the label-text field pairs in SpringForm:

String[] labels = {"Name: ", "Fax: ", "Email: ", "Address: "};
int numPairs = labels.length;

//Create and populate the panel.
JPanel p = new JPanel(new SpringLayout());
for (int i = 0; i < numPairs; i++) {
    JLabel l = new JLabel(labels[i], JLabel.TRAILING);
    p.add(l);
    JTextField textField = new JTextField(10);
    l.setLabelFor(textField);
    p.add(textField);
}

//Lay out the panel.
SpringUtilities.makeCompactGrid(p,
                                numPairs, 2, //rows, cols
                                6, 6,        //initX, initY
                                6, 6);       //xPad, yPad

Because we are using a real layout manager instead of absolute positioning, the layout manager responds dynamically to changes in components involved. For example, if the names of the labels are localized, the spring layout produces a configuration that gives the first column more or less room, as needed. And as the following figure shows, when the window is resized, the flexibly sized components — the text fields — take all the excess space, while the labels stick to what they need.

Our last example of the makeCompactGrid method, in SpringBox.java, shows some buttons configured to be laid out in a single row. Click the Launch button to run SpringBox using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SpringBox example

Note that the behavior is almost identical to that of BoxLayout in the case of a single row. Not only are the components laid out as BoxLayout would arrange them but the minimum, preferred, and maximum sizes of the container that uses the SpringLayout return the same results that BoxLayout would. Here is the call to makeCompactGrid that produces this layout:

//Lay out the buttons in one row and as many columns
//as necessary, with 6 pixels of padding all around.
SpringUtilities.makeCompactGrid(contentPane, 1,
                                contentPane.getComponentCount(),
                                6, 6, 6, 6);

Let us look at what happens when we resize this window. This is an odd special case that is worth taking note of as you may run into it by accident in your first layouts.

Nothing moved! That is because none of the components (buttons) or the spacing between them was defined to be stretchable. In this case the spring layout calculates a maximum size for the parent container that is equal to its preferred size, meaning the parent container itself is not stretchable. It would perhaps be less confusing if the AWT refused to resize a window that was not stretchable, but it does not. The layout manager cannot do anything sensible here as none of the components will take up the required space. Instead of crashing, it just does nothing, leaving all the components as they were.

The SpringLayout API

The API for using SpringLayout is spread across three classes:
  • SpringLayout
  • SpringLayout.Constraints
  • Spring

SpringLayout
Constructor or Method | Purpose
SpringLayout() | Create a SpringLayout instance.
SpringLayout.Constraints getConstraints(Component) | Get the constraints (set of springs) associated with the specified component.
Spring getConstraint(String, Component) | Get the spring for an edge of a component. The first argument specifies the edge and must be one of the following SpringLayout constants: NORTH, SOUTH, EAST, or WEST.
void putConstraint(String, Component, int, String, Component)
void putConstraint(String, Component, Spring, String, Component) 		Convenience methods for defining relationships between the edges of two components. The first two arguments specify the first component and its affected edge. The last two arguments specify the second component and its affected edge. The third argument specifies the spring that determines the distance between the two. When the third argument is an integer, a constant spring is created to provide a fixed distance between the component edges.

SpringLayout.Constraints
Constructor or Method Purpose
SpringLayout.Constraints()
SpringLayout.Constraints(Spring, Spring)
SpringLayout.Constraints(Spring, Spring, Spring, Spring) 		Create a SpringLayout.Constraints instance. The first two arguments, if present, specify the X and Y springs, respectively. The second two arguments, if present, specify the height and width springs, respectively. Omitting an argument causes the corresponding spring to be null, which SpringLayout generally replaces with suitable defaults.
Spring getConstraint(String)
Spring getHeight()
Spring getWidth()
Spring getX()
Spring getY()
void setConstraint(String, Spring)
void setHeight(Spring)
void setWidth(Spring)
void setX(Spring)
void setY(Spring) 		Get or set the specified spring. The string argument to the getConstraint and setConstraint methods specifies an edge name, and must be one of the SpringLayout constants NORTH, SOUTH, EAST, or WEST.

Spring
Method Purpose
static Spring constant(int)
static Spring constant(int, int, int) 		Create a spring that does not track a component's sizes. The three-argument version creates a spring with its minimum, preferred, and maximum values set to the specified values, in that order. The one-argument version creates a spring with its minimum, preferred, and maximum values all set to the specified integer.

Despite the name, springs returned by constant are mutable. To make a layout work out, SpringLayout might be forced to adjust a "constant" spring. For this reason, you should avoid reusing constant springs unless (1) you truly want the springs to always be precisely alike and (2) other springs provide some flexibility in the layout.

static Spring sum(Spring, Spring)
static Spring max(Spring, Spring)
static Spring minus(Spring) 		Create a spring that is the result of some mathematical manipulation. The sum method adds two springs. The max method returns a spring whose value is always greater than or equal to the values of the two arguments. The minus method returns a spring running in the opposite direction of the argument. The minus method can be used to create an argument for the sum method, allowing you to get the difference between two springs.
int getMinimumValue()
int getPreferredValue()
int getMaximumValue() 		Get the corresponding value from the spring. For a SpringLayout-created spring that automatically tracks a component, these methods result in calls to the component's corresponding getXxxSize method.
int getValue()
setValue(int) 		Get or set the spring's current value.

Examples that Use SpringLayout

The following table lists some examples that use spring layout.

Example | Where Described | Notes
SpringDemo3 | This page | Uses SpringLayout to create a row of evenly spaced, natural-size components.
SpringDemo4 | This page | Reimplements SpringDemo3 to use SpringLayout.Constraints and Spring directly.
SpringGrid | This page | Uses SpringLayout and the makeGrid utility method to create a layout where all the components are the same size.
SpringCompactGrid | This page | Uses SpringLayout and the makeCompactGrid utility method to create a layout where all the components in a row have the same height, and all components in a column have the same width.
SpringForm | This page | Uses SpringLayout and makeCompactGrid to align label-text field pairs.
SpringBox | This page | Uses SpringLayout and makeCompactGrid to demonstrate laying out a single row of components, and what happens when no springs can grow.
SpinnerDemo | How to Use Spinners | Uses SpringLayout and makeCompactGrid to lay out rows of label-spinner pairs.
TextInputDemo | How to Use Formatted Text Fields | Uses SpringLayout and makeCompactGrid to lay out rows of labeled components. The components are a mix of text fields, formatted text fields, and spinners.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: A GroupLayout Example
Next page: Creating a Custom Layout Manager


Creating a Custom Layout Manager (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
Creating a Custom Layout Manager
Before you start creating a custom layout manager, make sure that no existing layout manager will meet your requirements. In particular, layout managers such as GridBagLayout, SpringLayout, and BoxLayout are flexible enough to work in many cases. You can also find layout managers from other sources, such as from the Internet. Finally, you can simplify layout by grouping components into containers such as panels.
Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.

To create a custom layout manager, you must create a class that implements the LayoutManager interface. You can either implement it directly, or implement its subinterface, LayoutManager2.

Every layout manager must implement at least the following five methods, which are required by the LayoutManager interface:

void addLayoutComponent(String, Component)
Called by the Container class's add methods. Layout managers that do not associate strings with their components generally do nothing in this method.

void removeLayoutComponent(Component)
Called by the Container methods remove and removeAll. Layout managers override this method to clear an internal state they may have associated with the Component.

Dimension preferredLayoutSize(Container)
Called by the Container class's getPreferredSize method, which is itself called under a variety of circumstances. This method should calculate and return the ideal size of the container, assuming that the components it contains will be at or above their preferred sizes. This method must take into account the container's internal borders, which are returned by the getInsets method.

Dimension minimumLayoutSize(Container)
Called by the Container getMinimumSize method, which is itself called under a variety of circumstances. This method should calculate and return the minimum size of the container, assuming that the components it contains will be at or above their minimum sizes. This method must take into account the container's internal borders, which are returned by the getInsets method.

void layoutContainer(Container)
Called to position and size each of the components in the container. A layout manager's layoutContainer method does not actually draw components. It simply invokes one or more of each component's setSize, setLocation, and setBounds methods to set the component's size and position.

This method must take into account the container's internal borders, which are returned by the getInsets method. If appropriate, it should also take the container's orientation (returned by the getComponentOrientation method) into account. You cannot assume that the preferredLayoutSize or minimumLayoutSize methods will be called before layoutContainer is called.

Besides implementing the preceding five methods, layout managers generally implement at least one public constructor and the toString method.

If you wish to support component constraints, maximum sizes, or alignment, then your layout manager should implement the LayoutManager2 interface. In fact, for these reasons among many others, nearly all modern layout managers will need to implement LayoutManager2. That interface adds five methods to those required by LayoutManager:

  • addLayoutComponent(Component, Object)
  • getLayoutAlignmentX(Container)
  • getLayoutAlignmentY(Container)
  • invalidateLayout(Container)
  • maximumLayoutSize(Container)

Of these methods, the most important are addLayoutComponent(Component, Object) and invalidateLayout(Container). The addLayoutComponent method is used to add components to the layout, using the specified constraint object. The invalidateLayout method is used to invalidate the layout, so that if the layout manager has cached information, this should be discarded. For more information about LayoutManager2, see the LayoutManager2 API documentation.

Finally, whenever you create custom layout managers, you should be careful of keeping references to Component instances that are no longer children of the Container. Namely, layout managers should override removeLayoutComponent to clear any cached state related to the Component.

Example of a Custom Layout

The example CustomLayoutDemo uses a custom layout manager called DiagonalLayout. You can find the layout manager's source code in DiagonalLayout.java. DialogLayout lays out components diagonally, from left to right, with one component per row. Here is a picture of CustomLayoutDemo using DialogLayout to lay out five buttons.

A snapshot of CustomLayoutDemo

Click the Launch button to run CustomLayoutDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the CustomLayoutDemo example
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Use SpringLayout
Next page: Doing Without a Layout Manager (Absolute Positioning)


Doing Without a Layout Manager (Absolute Positioning) (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
Doing Without a Layout Manager (Absolute Positioning)
Although it is possible to do without a layout manager, you should use a layout manager if at all possible. A layout manager makes it easier to adjust to look-and-feel-dependent component appearances, to different font sizes, to a container's changing size, and to different locales. Layout managers also can be reused easily by other containers, as well as other programs.
Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.

If a container holds components whose size is not affected by the container's size or by font, look-and-feel, or language changes, then absolute positioning might make sense. Desktop panes, which contain internal frames, are in this category. The size and position of internal frames does not depend directly on the desktop pane's size. The programmer determines the initial size and placement of internal frames within the desktop pane, and then the user can move or resize the frames. A layout manager is unnecessary in this situation.

Another situation in which absolute positioning might make sense is that of a custom container that performs size and position calculations that are particular to the container, and perhaps require knowledge of the container's specialized state. This is the situation with split panes.

Creating a container without a layout manager involves the following steps.

  1. Set the container's layout manager to null by calling setLayout(null).
  2. Call the Component class's setbounds method for each of the container's children.
  3. Call the Component class's repaint method.

However, creating containers with absolutely positioned containers can cause problems if the window containing the container is resized.

Here is a snapshot of a frame whose content pane uses absolute positioning.

A snapshot of AbsoluteLayoutDemo

Click the Launch button to run AbsoluteLayoutDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the AbsoluteLayoutDemo example

Its code is in AbsoluteLayoutDemo.java. The following code snippet shows how the components in the content pane are created and laid out.

pane.setLayout(null);

JButton b1 = new JButton("one");
JButton b2 = new JButton("two");
JButton b3 = new JButton("three");

pane.add(b1);
pane.add(b2);
pane.add(b3);

Insets insets = pane.getInsets();
Dimension size = b1.getPreferredSize();
b1.setBounds(25 + insets.left, 5 + insets.top,
             size.width, size.height);
size = b2.getPreferredSize();
b2.setBounds(55 + insets.left, 40 + insets.top,
             size.width, size.height);
size = b3.getPreferredSize();
b3.setBounds(150 + insets.left, 15 + insets.top,
             size.width + 50, size.height + 20);

...//In the main method:
Insets insets = frame.getInsets();
frame.setSize(300 + insets.left + insets.right,
              125 + insets.top + insets.bottom);
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating a Custom Layout Manager
Next page: Solving Common Layout Problems


Solving Common Layout Problems (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
Solving Common Layout Problems
Note: This lesson covers writing layout code by hand, which can be challenging. If you are not interested in learning all the details of layout management, you might prefer to use the GroupLayout layout manager combined with a builder tool to lay out your GUI. One such builder tool is the NetBeans IDE. Otherwise, if you want to code by hand and do not want to use GroupLayout, then GridBagLayout is recommended as the next most flexible and powerful layout manager.
Problem: How do I specify a component's exact size?
  • A handful of the more modern layout managers provide ways to override the size set by the component. Check whether the layout manager you are using allows you to specify component sizes.

  • Make sure that you really need to set the component's exact size. Each Swing component has a different preferred size, depending on the font it uses and the look and feel. For this reason, it often does not make sense to specify a Swing component's exact size.

  • If the component is not controlled by a layout manager, you can set its size by invoking the setSize or setBounds method on it. Otherwise, you need to provide size hints and then make sure you are using a layout manager that respects the size hints.

  • If you extend a Swing component class, you can give size hints by overriding the component's getMinimumSize, getPreferredSize, and getMaximumSize methods. What is nice about this approach is that each getXxxxSize method can get the component's default size hints by invoking super.getXxxxSize(). Then it can adjust the size, if necessary, before returning it. This is particularly handy for text components, where you might want to fix the width, but have the height determined from the content. However, sometimes problems can be encountered with GridBagLayout and text fields, wherein if the size of the container is smaller than the preferred size, the minimum size gets used, which can cause text fields to shrink quite substantially.

  • Another way to give size hints is to invoke the component's setMinimumSize, setPreferredSize, and setMaximumSize methods.

  • If you specify new size hints for a component that is already visible, you then need to invoke the revalidate method on it, to make sure that its containment hierarchy is laid out again. Then invoke the repaint method.
Note: No matter how you specify your component's size, be sure that your component's container uses a layout manager that respects the requested size of the component. The FlowLayout and GridBagLayout managers use the component's preferred size (the latter depending on the constraints that you set), but BorderLayout and GridLayout usually do not. The BoxLayout manager generally uses a component's preferred size (although components can be larger), and is one of the few layout managers that respects the component's maximum size.

Problem: My component does not appear after I have added it to the container.

  • You need to invoke revalidate and repaint after adding a component before it will show up in your container.

Problem: My custom component is being sized too small.

  • Does the component implement the getPreferredSize and getMinimumSize methods? If so, do they return the right values?
  • Are you using a layout manager that can use as much space as is available? See Tips on Choosing a Layout Manager for some tips on choosing a layout manager and specifying that it use the maximum available space for a particular component.

If you do not see your problem in this list, see Solving Common Component Problems.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Doing Without a Layout Manager (Absolute Positioning)
Next page: Questions and Exercises: Laying Out Components within a Container


Questions and Exercises: Laying Out Components within a Container (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Questions and Exercises: Laying Out Components within a Container

Questions

In each of the following questions, choose the layout manager(s) most naturally suited for the described layout. Assume that the container controlled by the layout manager is a JPanel. [Hint: Two sections that might help are A Visual Index to Swing Components and Tips on Choosing a Layout Manager.]

1. The container has one component that should take up as much space as possible

a. BorderLayout
b. GridLayout
c. GridBagLayout
d. a and b
e. b and c

2. The container has a row of components that should all be displayed at the same size, filling the container’s entire area.

a. FlowLayout
b. GridLayout
c. BoxLayout
d. a and b

3. The container displays a number of components in a column, with any extra space going between the first two components.

a. FlowLayout
b. BoxLayout
c. GridLayout
d. BorderLayout

4. The container can display three completely different components at different times, depending perhaps on user input or program state. Even if the components’ sizes differ, switching from one component to the next shouldn’t change the amount of space devoted to the component.

a. SpringLayout
b. BoxLayout
c. CardLayout
d. GridBagLayout

Exercises

1. Implement the layout described and shown in question 1.

2. Implement the layout described and shown in question 2.

3. Implement the layout described and shown in question 3.

4. Implement the layout described and shown in question 4.

5. By adding a single line of code, make the program you wrote for Exercise 2 display the components from right-to-left, instead of from left-to-right.

Check your answers.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Solving Common Layout Problems
Next page: Modifying the Look and Feel


Lesson: Modifying the Look and Feel (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Modifying the Look and Feel
How to Set the Look and Feel
The Synth Look and Feel
A Synth Example
Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Lesson: Modifying the Look and Feel
Examples Index

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: How to Set the Look and Feel


How to Set the Look and Feel (The Java™ Tutorials > Creating a GUI with JFC/Swing > Modifying the Look and Feel)

Trail: Creating a GUI with JFC/Swing
Lesson: Modifying the Look and Feel
Modifying the Look and Feel
How to Set the Look and Feel
The Synth Look and Feel
A Synth Example
Home Page > Creating a GUI with JFC/Swing > Modifying the Look and Feel
« Previous • Trail • Next »
How to Set the Look and Feel
The architecture of Swing is designed so that you may change the "look and feel" (L&F) of your application's GUI (see A Swing Architecture Overview). "Look" refers to the appearance of GUI widgets (more formally, JComponents) and "feel" refers to the way the widgets behave.

Swing's architecture enables multiple L&Fs by separating every JComponent into two distinct classes: a JComponent subclass and a corresponding ComponentUI subclass. For example, every JList instance has a concrete implementation of ListUI (ListUI extends ComponentUI). The ComponentUI subclass is referred to by various names in Swing's documentation—"the UI," "component UI," "UI delegate," and "look and feel delegate" are all used to identify the ComponentUI subclass.

Most developers never need to interact with the UI delegate directly. For the most part, the UI delegate is used internally by the JComponent subclass for crucial functionality, with cover methods provided by the JComponent subclass for all access to the UI delegate. For example, all painting in JComponent subclasses is delegated to the UI delegate. By delegating painting, the 'look' can vary depending upon the L&F.

It is the responsibility of each L&F to provide a concrete implementation for each of the ComponentUI subclasses defined by Swing. For example, the Java Look and Feel creates an instance of MetalTabbedPaneUI to provide the L&F for JTabbedPane. The actual creation of the UI delegate is handled by Swing for you—for the most part you never need to interact directly with the UI delegate.

The rest of this section discusses the following subjects:

  • Available Look and Feels
  • Programatically Setting the Look and Feel
  • Specifying the Look and Feel: Command Line
  • Specifying the Look and Feel: swing.properties
  • How the UI Manager Chooses the Look and Feel
  • Changing the Look and Feel After Startup
  • An Example
  • Themes
  • The SwingSet2 Demonstration Program

Available Look and Feels

Sun's JRE provides the following L&Fs:
  1. CrossPlatformLookAndFeel—this is the "Java L&F" (also called "Metal") that looks the same on all platforms. It is part of the Java API (javax.swing.plaf.metal) and is the default that will be used if you do nothing in your code to set a different L&F.

  2. SystemLookAndFeel—here, the application uses the L&F that is native to the system it is running on. The System L&F is determined at runtime, where the application asks the system to return the name of the appropriate L&F.

  3. Synth—the basis for creating your own look and feel with an XML file.

  4. Multiplexing— a way to have the UI methods delegate to a number of different look and feels at the same time.

For Linux and Solaris, the System L&Fs are "GTK+" if GTK+ 2.2 or later is installed, "Motif" otherwise. For Windows, the System L&F is "Windows," which mimics the L&F of the particular Windows OS that is running—classic Windows, XP, or Vista. The GTK+, Motif, and Windows L&Fs are provided by Sun and shipped with the Java SDK and JRE, although they are not part of the Java API.

Apple provides its own JVM which includes their proprietary L&F.

In summary, when you use the SystemLookAndFeel, this is what you will see:

System Look and Feel
Platform | Look and Feel
Solaris, Linux with GTK+ 2.2 or later | GTK+
Other Solaris, Linux | Motif
IBM UNIX | IBM*
HP UX | HP*
Classic Windows | Windows
Windows XP | Windows XP
Windows Vista | Windows Vista
Macintosh | Macintosh*
* Supplied by the system vendor.

You don't see the System L&F in the API. The GTK+, Motif, and Windows packages that it requires are shipped with the Java SDK as:

com.sun.java.swing.plaf.gtk.GTKLookAndFeel
com.sun.java.swing.plaf.motif.MotifLookAndFeel
com.sun.java.swing.plaf.windows.WindowsLookAndFeel
Note that the path includes java, and not javax.

Note: The GTK+ L&F will only run on UNIX or Linux systems with GTK+ 2.2 or later installed, while the Windows L&F runs only on Windows systems. Like the Java (Metal) L&F, the Motif L&F will run on any platform.

All of Sun's L&Fs have a great deal of commonality. This commonality is defined in the Basic look and feel in the API (javax.swing.plaf.basic). The Motif and Windows L&Fs are each built by extending the UI delegate classes in javax.swing.plaf.basic (a custom L&F can be built by doing the same thing). The "Basic" L&F is not used without being extended.

In the API you will see four L&F packages:

  • javax.swing.plaf.basic—basic UI Delegates to be extended when creating a custom L&F

  • javax.swing.plaf.metal—the Java L&F, also known as the CrossPlatform L&F ("Metal" was the Sun project name for this L&F) The current default "theme" (discussed below) for this L&F is "Ocean, so this is often referred to as the Ocean L&F.

  • javax.swing.plaf.multi—a multiplexing L&F that allows the UI methods to delegate to a number of look and feels at the same time. It can be used to augment the behavior of a particular L&F, for example with a L&F that provides audio cues on top of the Windows L&F. This is a way of creating a handicapped-accessible L&F.

  • javax.swing.plaf.synth—an easily configured L&F using XML files (discussed in the next section of this lesson)

You aren't limited to the L&Fs supplied with the Java platform. You can use any L&F that is in your program's class path. External L&Fs are usually provided in one or more JAR files that you add to your program's class path at runtime. For example:

java -classpath .;C:\java\lafdir\customlaf.jar YourSwingApplication

Once an external L&F is in your program's class path, your program can use it just like any of the L&Fs shipped with the Java platform.

Programatically Setting the Look and Feel

Note: If you are going to set the L&F, you should do it as the very first step in your application. Otherwise you run the risk of initializing the Java L&F regardless of what L&F you've requested. This can happen inadvertently when a static field references a Swing class, which causes the L&F to be loaded. If no L&F has yet been specified, the default L&F for the JRE is loaded. For Sun's JRE the default is the Java L&F, for Apple's JRE the Apple L&F, and so forth.

The L&F that Swing components use is specified by way of the UIManager class in the javax.swing package. Whenever a Swing component is created,the component asks the UI manager for the UI delegate that implements the component's L&F. For example, each JLabel constructor queries the UI manager for the UI delegate object appropriate for the label. It then uses that UI delegate object to implement all of its drawing and event handling.

To programatically specify a L&F, use the UIManager.setLookAndFeel() method with the fully qualified name of the appropriate subclass of LookAndFeel as its argument. For example, the bold code in the following snippet makes the program use the cross-platform Java L&F:

public static void main(String[] args) {
    try {
        // Set cross-platform Java L&F (also called "Metal")
        UIManager.setLookAndFeel(
            UIManager.getCrossPlatformLookAndFeelClassName());
    }
    catch (UnsupportedLookAndFeelException e) {
       // handle exception
    }
    catch (ClassNotFoundException e) {
       // handle exception
    }
    catch (InstantiationException e) {
       // handle exception
    }
    catch (IllegalAccessException e) {
       // handle exception
    }

    new SwingApplication(); //Create and show the GUI.
}

Alternatively, this code makes the program use the System L&F:

public static void main(String[] args) {
    try {
        // Set System L&F
        UIManager.setLookAndFeel(
            UIManager.getSystemLookAndFeelClassName());
    }
    catch (UnsupportedLookAndFeelException e) {
       // handle exception
    }
    catch (ClassNotFoundException e) {
       // handle exception
    }
    catch (InstantiationException e) {
       // handle exception
    }
    catch (IllegalAccessException e) {
       // handle exception
    }

    new SwingApplication(); //Create and show the GUI.
}

You can also use the actual class name of a Look and Feel as the argument to UIManager.setLookAndFeel(). For example,

// Set cross-platform Java L&F (also called "Metal")
UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel");
or
// Set Motif L&F on any platform
UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel");

You aren't limited to the preceding arguments. You can specify the name for any L&F that is in your program's class path.

Specifying the Look and Feel: Command Line

You can specify the L&F at the command line by using the -D flag to set the swing.defaultlaf property. For example:
java -Dswing.defaultlaf=com.sun.java.swing.plaf.gtk.GTKLookAndFeel MyApp

java -Dswing.defaultlaf=com.sun.java.swing.plaf.windows.WindowsLookAndFeel MyApp

Specifying the Look and Feel: swing.properties File

Yet another way to specify the current L&F is to use the swing.properties file to set the swing.defaultlaf property. This file, which you may need to create, is located in the lib directory of Sun's Java release (other vendors of Java may use a different location). For example, if you're using the Java interpreter in javaHomeDirectory\bin, then the swing.properties file (if it exists) is in javaHomeDirectory\lib. Here is an example of the contents of a swing.properties file:
# Swing properties
swing.defaultlaf=com.sun.java.swing.plaf.windows.WindowsLookAndFeel

How the UI Manager Chooses the Look and Feel

Here are the look-and-feel determination steps that occur when the UI manager needs to set a L&F:
  1. If the program sets the L&F before a look and feel is needed, the UI manager tries to create an instance of the specified look-and-feel class. If successful, all components use that L&F.

  2. If the program hasn't successfully specified a L&F, then the UI manager uses the L&F specified by the swing.defaultlaf property. If the property is specified in both the swing.properties file and on the command line, the command-line definition takes precedence.

  3. If none of these steps has resulted in a valid L&F, Sun's JRE uses the Java L&F. Other vendors, such as Apple, will use their default L&F.

Changing the Look and Feel After Startup

You can change the L&F with setLookAndFeel even after the program's GUI is visible. To make existing components reflect the new L&F, invoke the SwingUtilities updateComponentTreeUI method once per top-level container. Then you might wish to resize each top-level container to reflect the new sizes of its contained components. For example:
UIManager.setLookAndFeel(lnfName);
SwingUtilities.updateComponentTreeUI(frame);
frame.pack();

An Example

In the following example, LookAndFeelDemo.java, you can experiment with different Look and Feels. The program creates a simple GUI with a button and a label. Every time you click the button, the label increments.

You can change the L&F by changing the LOOKANDFEEL constant on line 18. The comments on the preceding lines tell you what values are acceptable:

    // Specify the look and feel to use by defining the LOOKANDFEEL constant
    // Valid values are: null (use the default), "Metal", "System", "Motif",
    // and "GTK"
    final static String LOOKANDFEEL = "Motif";
Here the constant is set to "Motif", which is a L&F that will run on any platform (as will the default, "Metal"). "GTK+" will not run on Windows, and "Windows" will run only on Windows. If you choose a L&F that will not run, you will get the Java, or Metal, L&F.

In the section of the code where the L&F is actually set, you will see several different ways to set it, as discussed above:

if (LOOKANDFEEL.equals("Metal")) {
   lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName();
   //  an alternative way to set the Metal L&F is to replace the
   // previous line with:
   // lookAndFeel = "javax.swing.plaf.metal.MetalLookAndFeel";

You can verify that both arguments work by commenting/un-commenting the two alternatives.

Here is a listing of the LookAndFeelDemo source file:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package lookandfeel;

/*
 * LookAndFeelDemo.java is a Java SE 6 example that requires
 * one other file (TestTheme.java).
 */
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.plaf.metal.*;

public class LookAndFeelDemo implements ActionListener {
    private static String labelPrefix = "Number of button clicks: ";
    private int numClicks = 0;
    final JLabel label = new JLabel(labelPrefix + "0    ");

    // Specify the look and feel to use by defining the LOOKANDFEEL constant
    // Valid values are: null (use the default), "Metal", "System", "Motif",
    // and "GTK"
    final static String LOOKANDFEEL = "Metal";

    // If you choose the Metal L&F, you can also choose a theme.
    // Specify the theme to use by defining the THEME constant
    // Valid values are: "DefaultMetal", "Ocean",  and "Test"
    final static String THEME = "Test";

    public Component createComponents() {
        JButton button = new JButton("I'm a Swing button!");
        button.setMnemonic(KeyEvent.VK_I);
        button.addActionListener(this);
        label.setLabelFor(button);

        /*
         * An easy way to put space between a top-level container
         * and its contents is to put the contents in a JPanel
         * that has an "empty" border.
         */
        JPanel pane = new JPanel(new GridLayout(0, 1));
        pane.add(button);
        pane.add(label);
        pane.setBorder(BorderFactory.createEmptyBorder(
                                        30, //top
                                        30, //left
                                        10, //bottom
                                        30) //right
                                        );

        return pane;
    }

    public void actionPerformed(ActionEvent e) {
        numClicks++;
        label.setText(labelPrefix + numClicks);
    }

    private static void initLookAndFeel() {
        String lookAndFeel = null;

        if (LOOKANDFEEL != null) {
            if (LOOKANDFEEL.equals("Metal")) {
                lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName();
              //  an alternative way to set the Metal L&F is to replace the
              // previous line with:
              // lookAndFeel = "javax.swing.plaf.metal.MetalLookAndFeel";

            }

            else if (LOOKANDFEEL.equals("System")) {
                lookAndFeel = UIManager.getSystemLookAndFeelClassName();
            }

            else if (LOOKANDFEEL.equals("Motif")) {
                lookAndFeel = "com.sun.java.swing.plaf.motif.MotifLookAndFeel";
            }

            else if (LOOKANDFEEL.equals("GTK")) {
                lookAndFeel = "com.sun.java.swing.plaf.gtk.GTKLookAndFeel";
            }

            else {
                System.err.println("Unexpected value of LOOKANDFEEL specified: "
                                   + LOOKANDFEEL);
                lookAndFeel = UIManager.getCrossPlatformLookAndFeelClassName();
            }

            try {

                UIManager.setLookAndFeel(lookAndFeel);

                // If L&F = "Metal", set the theme

                if (LOOKANDFEEL.equals("Metal")) {
                  if (THEME.equals("DefaultMetal"))
                     MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme());
                  else if (THEME.equals("Ocean"))
                     MetalLookAndFeel.setCurrentTheme(new OceanTheme());
                  else
                     MetalLookAndFeel.setCurrentTheme(new TestTheme());

                  UIManager.setLookAndFeel(new MetalLookAndFeel());
                }

            }

            catch (ClassNotFoundException e) {
                System.err.println("Couldn't find class for specified look and feel:"
                                   + lookAndFeel);
                System.err.println("Did you include the L&F library in the class path?");
                System.err.println("Using the default look and feel.");
            }

            catch (UnsupportedLookAndFeelException e) {
                System.err.println("Can't use the specified look and feel ("
                                   + lookAndFeel
                                   + ") on this platform.");
                System.err.println("Using the default look and feel.");
            }

            catch (Exception e) {
                System.err.println("Couldn't get specified look and feel ("
                                   + lookAndFeel
                                   + "), for some reason.");
                System.err.println("Using the default look and feel.");
                e.printStackTrace();
            }
        }
    }

    /**
     * Create the GUI and show it.  For thread safety,
     * this method should be invoked from the
     * event dispatch thread.
     */
    private static void createAndShowGUI() {
        //Set the look and feel.
        initLookAndFeel();

        //Make sure we have nice window decorations.
        JFrame.setDefaultLookAndFeelDecorated(true);

        //Create and set up the window.
        JFrame frame = new JFrame("SwingApplication");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        LookAndFeelDemo app = new LookAndFeelDemo();
        Component contents = app.createComponents();
        frame.getContentPane().add(contents, BorderLayout.CENTER);

        //Display the window.
        frame.pack();
        frame.setVisible(true);
    }

    public static void main(String[] args) {
        //Schedule a job for the event dispatch thread:
        //creating and showing this application's GUI.
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }
}

Themes

Themes were introduced as a way of easily changing the colors and fonts of the cross-platform Java (Metal) Look and Feel. In the sample program, LookAndfeelDemo.java, listed above, you can change the theme of the Metal L&F by setting the THEME constant on line 23 to one of three values:
  • DefaultMetal
  • Ocean
  • Test
Ocean, which is a bit softer than the pure Metal look, has been the default theme for the Metal (Java) L&F since Java SE 5. Despite its name, DefaultMetal is not the default theme for Metal (it was before Java SE 5, which explains its name). The Test theme is a theme defined in TestTheme.java, which you must compile with LookAndfeelDemo.java. As it is written, TestTheme.java sets the three primary colors (with somewhat bizarre results). You can modify TestTheme.java to test any colors you like.

The section of code where the theme is set is found beginning on line 92 of LookAndfeelDemo.java. Note that you must be using the Metal L&F to set a theme.

 if (LOOKANDFEEL.equals("Metal")) {
    if (THEME.equals("DefaultMetal"))
       MetalLookAndFeel.setCurrentTheme(new DefaultMetalTheme());
    else if (THEME.equals("Ocean"))
       MetalLookAndFeel.setCurrentTheme(new OceanTheme());
    else
       MetalLookAndFeel.setCurrentTheme(new TestTheme());

    UIManager.setLookAndFeel(new MetalLookAndFeel());
 }

The SwingSet2 Demonstration Program

In your JDK 6 installation, there is a demo\jfc folder that contains a demonstration program called SwingSet2. This program has a graphically rich GUI and allows you to change the Look and Feel from the menu. Further, if you are using the Java (Metal) Look and Feel, you can choose a variety of different themes. The files for the various themes (for example, RubyTheme.java) are found in the SwingSet2\src folder.

This is the "Ocean" theme, which is the default for the cross-platform Java (Metal) Look and Feel:

This is the "Steel" theme, which was the original theme for the cross-platform Java (Metal) Look and Feel:

To run the SwingSet2 demo program on a system that has the JDK installed, use this command:

java -jar SwingSet2.jar
This will give you the default theme of Ocean.

To get the metal L&F, run this:

java -Dswing.metalTheme=steel -jar SwingSet2.jar

It is also possible to run the SwingSet2 demo program with Java Web Start:

http://java.sun.com/products/jfc/jws/SwingSet2.jnlp
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Modifying the Look and Feel
Next page: The Synth Look and Feel


The Synth Look and Feel (The Java™ Tutorials > Creating a GUI with JFC/Swing > Modifying the Look and Feel)

Trail: Creating a GUI with JFC/Swing
Lesson: Modifying the Look and Feel
Modifying the Look and Feel
How to Set the Look and Feel
The Synth Look and Feel
A Synth Example
Home Page > Creating a GUI with JFC/Swing > Modifying the Look and Feel
« Previous • Trail • Next »
The Synth Look and Feel
Creating a custom look and feel, or modifying an existing one, can be a daunting task. The javax.swing.plaf.synth package can be used to create a custom look and feel with much less effort. You can create a Synth look and feel either programatically or through the use of an external XML file. The discussion below is devoted to the creation of a Synth look and feel using an external XML file. Creating a Synth L&F programatically is discussed in the API documentation.

With the Synth look and feel, you provide the "look." Synth itself provides the "feel." Thus, you can think of the Synth L&F as a "skin."

The Synth Architecture

Recall from the previous topic that it is the responsibility of each L&F to provide a concrete implementation for each of the many ComponentUI subclasses defined by Swing. The Synth L&F takes care of this for you. To use Synth, you need not create any ComponentUIs—rather you need only specify how each component is painted, along with various properties that effect the layout and size.

Synth operates at a more granular level than a component—this granular level is called a "region." Each component has one or more regions. Many components have only one region, such as JButton. Others have multiple regions, such as JScrollBar. Each of the ComponentUIs provided by Synth associates a SynthStyle with each of the regions defined by the ComponentUI. For example, Synth defines three regions for JScrollBar: the track, the thumb and the scroll bar itself. The ScrollBarUI (the ComponentUI subclass defined for JScrollBar) implementation for Synth associates a SynthStyle with each of these regions.

Synth Architecture Drawing.

SynthStyle provides style information used by the Synth ComponentUI implementation. For example, SynthStyle defines the foreground and background color, font information, and so forth. In addition, each SynthStyle has a SynthPainter that is used to paint the region. For example, SynthPainter defines the two methods paintScrollBarThumbBackground and paintScrollBarThumbBorder, which are used to paint the scroll bar thumb regions.

Each of the ComponentUIs in Synth obtain SynthStyles using a SynthStyleFactory. There are two ways to define a SynthStyleFactory: through a Synth XML file, or programatically. The following code shows how to load an XML file dictating the look of Synth—beneath the covers this creates a SynthStyleFactory implementation populated with SynthStyles from the XML file:

  SynthLookAndFeel laf = new SynthLookAndFeel();
  laf.load(MyClass.class.getResourceAsStream("laf.xml"), MyClass.class);
  UIManager.setLookAndFeel(laf);

The programmatic route involves creating an implementation of SynthStyleFactory that returns SynthStyles. The following code creates a custom SynthStyleFactory that returns distinct SynthStyles for buttons and trees:

 class MyStyleFactory extends SynthStyleFactory {
     public SynthStyle getStyle(JComponent c, Region id) {
         if (id == Region.BUTTON) {
             return buttonStyle;
         }
         else if (id == Region.TREE) {
             return treeStyle;
         }
         return defaultStyle;
     }
 }
 SynthLookAndFeel laf = new SynthLookAndFeel();
 UIManager.setLookAndFeel(laf);
 SynthLookAndFeel.setStyleFactory(new MyStyleFactory());

The XML File

An explanation of the DTD for the Synth XML file can be found at javax.swing.plaf.synth/doc-files/synthFileFormat.html.

When you load a Synth look and feel, only those GUI components (or regions) for which there is a definition (a "style" bound to the region, as discussed below) are rendered. There is no default behavior for any components—without style definitions in the Synth XML file, the GUI is a blank canvas.

To specify the rendering of a component (or region), your XML file must contain a <style> element, which is then bound to the region using the <bind> element. As an example, let's define a style that includes the font, foreground color, and background color, and then bind that style to all components. It is a good idea to include such an element in your Synth XML file while you are developing it—then, any components you haven't yet defined will at least have colors and a font:

<synth>
  <style id="basicStyle">
    <font name="Verdana" size="16"/>
    <state>
      <color value="WHITE" type="BACKGROUND"/>
      <color value="BLACK" type="FOREGROUND"/>
    </state>
  </style>
  <bind style="basicStyle" type="region" key=".*"/>
</synth>

Let's analyse this style definition:

  1. The <style> element is the basic building block of the Synth XML file. It contains all the information needed to describe a region's rendering. A <style> element can describe more than one region, as is done here. In general, though, it is best to create a <style> element for each component or region. Note that the <style> element is given an identifier, the string "basicStyle." This identifier will be used later in the <bind> element.

  2. The <font> element of the <style> element sets the font to Verdana, size 16.

  3. The <state> element of the <style> element will be discussed below. The <state> element of a region can have one, or a mixture, of seven possible values. When the value is not specified, the definition applies to all states, which is the intention here. Therefore, the background and foreground colors "for all states" are defined in this element.

  4. Finally, the <style> element with the identifier "basicStyle" that has just been defined is bound to all regions. The <bind> element binds "basicStyle" to "region" types. Which region type or types the binding applies to is given by the "key" attribute, which is ".*" in this case, the regular expression for "all."

Let's look at the pieces of the Synth XML file before creating some working examples. We'll start with the <bind> element, showing how a given <style> is applied to a component or region.

The <bind> Element

Whenever a <style> element is defined, it must be bound to one or more components or regions before it has an effect. The <bind> element is used for this purpose. It requires three attributes:
  1. style is the unique identifier of a previously defined style.

  2. type is either "name" or "region." If type is a name, obtain the name with the component.getName() method. If type is a region, use the appropriate constant defined in the Region class in the javax.swing.plaf.synth package.

  3. key is a regular expression used to determine which components or regions the style is bound to.

A Region is a way of identifying a component or part of a component. Regions are based on the constants in the Region class, modified by stripping out underscores:

For example, to identify the SPLIT_PANE region you would use SPLITPANE, splitpane, or SplitPane (case insensitive).

When you bind a style to a region, that style will apply to all of the components with that region. You can bind a style to more than one region, and you can bind more than one style to a region. For example,

<style id="styleOne">
   <!-- styleOne definition goes here -->
</style>

<style id="styleTwo">
   <!-- styleTwo definition goes here -->
</style>

<bind style="styleOne" type="region" key="Button"/>
<bind style="styleOne" type="region" key="RadioButton"/>
<bind style="styleOne" type="region" key="ArrowButton"/>

<bind style="styleTwo" type="region" key="ArrowButton"/>

You can bind to individual, named components, whether or not they are also bound as regions. For example, suppose you want to have the "OK" and "Cancel" buttons in your GUI treated differently than all the other buttons. First, you would give the OK and Cancel buttons names, using the component.setName() method. Then, you would define three styles: one for buttons in general (region = "Button"), one for the OK button (name = "OK"), and one for the Cancel button (name = "Cancel"). Finally, you would bind these styles like this:

<bind style="styleButton" type="region" key="Button">
<bind style="styleOK" type="name" key="OK">
<bind style="styleCancel" type="name" key="Cancel">

As a result, the "OK" button is bound to both "styleButton" and "styleOK," while the "Cancel" button is bound to both "styleButton" and "styleCancel."

When a component or region is bound to more than one style, the styles are merged

Note: Just as a style can be bound to multiple regions or names, multiple styles can be bound to a region or name. These multiple styles are merged for the region or name. Precedence is given to styles defined later in the file.

The <state> Element

The <state> element allows you to define a look for a region that depends on its "state." For example, you will usually want a button that has been PRESSED to look different than the button in its ENABLED state. There are seven possible values for <state> that are defined in the Synth XML DTD. They are:

  1. ENABLED
  2. MOUSE_OVER
  3. PRESSED
  4. DISABLED
  5. FOCUSED
  6. SELECTED
  7. DEFAULT

You can also have composite states, separated by 'and'—for example, ENABLED and FOCUSED. If you do not specify a value, the defined look will apply to all states.

As an example, here is a style that specifies painters per state. All buttons are painted a certain way, unless the state is "PRESSED," in which case they are painted differently:

<style id="buttonStyle">
  <property key="Button.textShiftOffset" type="integer" value="1"/>
  <insets top="10" left="10" right="10" bottom="10"/>

  <state>
    <imagePainter method="buttonBackground" path="images/button.png"
                         sourceInsets="10 10 10 10"/>
  </state>
  <state value="PRESSED">
    <color value="#9BC3B1" type="BACKGROUND"/>
    <imagePainter method="buttonBackground" path="images/button2.png"
                        sourceInsets="10 10 10 10"/>
  </state>
</style>
<bind style="buttonStyle" type="region" key="Button"/>

Ignoring the <property> and <insets> elements for the moment, you can see that a pressed button is painted differently than an unpressed button.

The <state> value that is used is the defined state that most closely matches the state of the region. Matching is determined by the number of values that match the state of the region. If none of the state values match, then the state with no value is used. If there are matches, the state with the most individual matches will be chosen. For example, the following code defines three states:

<state id="zero">
  <color value="RED" type="BACKGROUND"/>
</state>
<state value="SELECTED and PRESSED" id="one">
  <color value="RED" type="BACKGROUND"/>
</state>
<state value="SELECTED" id="two">
  <color value="BLUE" type="BACKGROUND"/>
</state>

If the state of the region contains at least SELECTED and PRESSED, state one will be chosen. If the state contains SELECTED, but not does not contain PRESSED, state two will be used. If the state contains neither SELECTED nor PRESSED, state zero will be used.

When the current state matches the same number of values for two state definitions, the one that is used is the first one defined in the style. For example, the MOUSE_OVER state is always true of a PRESSED button (you can't press a button unless the mouse is over it). So, if the MOUSE_OVER state is declared first, it will always be chosen over PRESSED, and any painting defined for PRESSED will not be done.

<state value="PRESSED">
   <imagePainter method="buttonBackground" path="images/button_press.png"
                      sourceInsets="9 10 9 10" />
   <color type="TEXT_FOREGROUND" value="#FFFFFF"/>
</state>

<state value="MOUSE_OVER">
   <imagePainter method="buttonBackground" path="images/button_on.png"
                      sourceInsets="10 10 10 10" />
   <color type="TEXT_FOREGROUND" value="#FFFFFF"/>
</state>
The code above will work properly. However, if you reverse the order of the MOUSE_OVER and PRESSED states in the file, the PRESSED state will never be used. This is because any state that is PRESSED state is also a MOUSE_OVER state. Since the MOUSE_OVER state was defined first, it is the one that will be used.

Colors and Fonts

The <color> element requires two attributes:

  1. value can be any one of the java.awt.Color constants, such as RED, WHITE, BLACK, BLUE, etc. It can also be a hex representation of RGB values, such as #FF00FF or #326A3B.

  2. type describes where the color applies—it can be BACKGROUND, FOREGROUND, FOCUS, TEXT_BACKGROUND, OR TEXT_FOREGROUND.

For example:

  <style id="basicStyle">
    <state>
      <color value="WHITE" type="BACKGROUND"/>
      <color value="BLACK" type="FOREGROUND"/>
    </state>
  </style>

The <font> element has three attributes:

  1. name—the name of the font. For example, Arial or Verdana.

  2. size—the size of the font in pixels.

  3. style (optional)—BOLD, ITALIC, OR BOLD ITALIC. If omitted, you get a normal font.

For example:

  <style id="basicStyle">
    <font name="Verdana" size="16"/>
  </style>

Each of the <color> element and the <font> element has an alternate usage. Each can have an id attribute or an idref attribute. Using the id attribute, you can define a color that you can reuse later by using the idref attribute. For example,

<color id="backColor" value="WHITE" type="BACKGROUND"/>
<font id="textFont" name="Verdana" size="16"/>
...
...
...
<color idref="backColor"/>
<font idref="textFont"/>

Insets

The insets add to the size of a component as it is drawn. For example, without insets, a button with a caption of Cancel will be just large enough to contain the caption in the chosen font. With an <insets> element like this

<insets top="15" left="20" right="20" bottom="15"/>,
the button will be made larger by 15 pixels above and below the caption and 20 pixels to the left and right of the caption.

Painting With Images

Synth's file format allows customizing the painting by way of images. Synth's image painter breaks an image into nine distinct areas: top, top right, right, bottom right, bottom, bottom left, left, top left, and center. Each of the these areas is painted into the destination. The top, left, bottom, and right edges are tiled or stretched, while the corner portions (sourceInsets) remain fixed.

Note: There is no relation between the <insets> element and the sourceInsets attribute. The <insets> element defines the space taken up by a region, while the sourceInsets attributes define how to paint an image. The <insets> and sourceInsets will often be similar, but they need not be.

You can specify whether the center area should be painted with the paintCenter attribute. The following image shows the nine areas:

Nine Image Areas.

Let's create a button as an example. To do this we can use the following image (shown larger than its actual size):

The red box at the upper left corner is 10 pixels square (including the box border)—it shows the corner region that should not be stretched when painting. To achieve this, the top and left sourceInsets should be set to 10. We'll use the following style and binding:
<style id="buttonStyle">
   <insets top="15" left="20" right="20" bottom="15"/>
   <state>
      <imagePainter method="buttonBackground" path="images/button.png"
        sourceInsets="10 10 10 10"/>
   </state>
</style>
<bind style="buttonStyle" type="region" key="button"/>

The lines inside the <state> element specify that the background of buttons should be painted using the image images/button.png. That path is relative to the Class that is passed into SynthLookAndFeel's load method. The sourceInsets attribute specifies the areas of the image that are not to be stretched. In this case the top, left, bottom, and right insets are each 10. This will cause the painter not to stretch a 10 x 10 pixel area at each corner of the image.

The <bind> binds buttonStyle to all buttons.

The <imagePainter> element provides all the information needed to render a portion of a region. It requires only a few attributes:

  • method—this specifies which of the methods in the javax.swing.plaf.synth.SynthPainter class is to be used for painting. The SynthPainter class contains about 100 methods that begin with paint. When you determine which one you need, you remove the paint prefix, change the remaining first letter to lowercase, and use the result as the method attribute. For example, the SynthPainter method paintButtonBackground becomes the attribute buttonBackground.

  • path—the path to the image to be used, relative to the Class that is passed into SynthLookAndFeel's load method.

  • sourceInsets—the insets in pixels, representing the width and height of the corner areas that should not be stretched They map to the top, left, bottom, and right, in that order.

  • paintCenter (optional) : This attribute lets you keep the center of an image or get rid of it (in a text field, for example, so text can be drawn).

The listing below shows the XML code for loading different images depending on the <state> of the button

  <style id="buttonStyle">
    <property key="Button.textShiftOffset" type="integer" value="1"/>
    <insets top="15" left="20" right="20" bottom="15"/>
    <state>
      <imagePainter method="buttonBackground" path="images/button.png"
                    sourceInsets="10 10 10 10"/>
    </state>
    <state value="PRESSED">
      <imagePainter method="buttonBackground" path="images/button2.png"
                    sourceInsets="10 10 10 10"/>
    </state>
  </style>
  <bind style="buttonStyle" type="region" key="button"/>
button2.png shows the depressed version of button.png, shifted one pixel to the right. The line
<property key="Button.textShiftOffset" type="integer" value="1"/>
shifts the button text accordingly, as discussed in the next section.

The <property> Element

<property> elements are used to add key value pairs to a <style> element. Many components use the key value pairs for configuring their visual appearance.

The <property> element has three attributes:

  • key—the name of the property.

  • type—the data type of the property.

  • value—the value of the property.

There is a property table (componentProperties.html) that lists the properties each component supports: javax/swing/plaf/synth/doc-files/componentProperties.html.

Since the button2.png image shifts the visual button one pixel when it is depressed, we should also shift the button text. There is a button property that does this:

<property key="Button.textShiftOffset" type="integer" value="1"/>

An Example

Here is an example, using the button style defined above. The button style, plus a "backing style" with definitions of font and colors that are bound to all regions (similar to the "basicStyle" shown in the section titled "The XML File," above) are combined in buttonSkin.xmlHere is a listing of buttonSkin.xml:

<!-- Synth skin that includes an image for buttons -->
<synth>
  <!-- Style that all regions will use -->
  <style id="backingStyle">
    <!-- Make all the regions that use this skin opaque-->
    <opaque value="TRUE"/>
    <font name="Dialog" size="12"/>
    <state>
      <!-- Provide default colors -->
      <color value="#9BC3B1" type="BACKGROUND"/>
      <color value="RED" type="FOREGROUND"/>
    </state>
  </style>
  <bind style="backingStyle" type="region" key=".*"/>
  <style id="buttonStyle">
    <!-- Shift the text one pixel when pressed -->
    <property key="Button.textShiftOffset" type="integer" value="1"/>
    <insets top="15" left="20" right="20" bottom="15"/>
    <state>
      <imagePainter method="buttonBackground" path="images/button.png"
                    sourceInsets="10 10 10 10"/>
    </state>
    <state value="PRESSED">
      <imagePainter method="buttonBackground" path="images/button2.png"
                    sourceInsets="10 10 10 10"/>
    </state>
  </style>
  <!-- Bind buttonStyle to all JButtons -->
  <bind style="buttonStyle" type="region" key="button"/>
</synth>
We can load this XML file to use the Synth look and feel for a simple application called SynthApplication.java. The GUI for this application includes a button and a label. Every time the button is clicked, the label increments.

Note: The label is painted, even though buttonSkin.xml does not contain a style for it. This is because there is a general "backingStyle" that includes a font and colors.

Here is the listing of the SynthApplication.javafile.

Try this:  Click the Launch button to run the SynthApplication example using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SynthApplication example

Painting With Icons

Radio buttons and check boxes typically render their state by fixed-size icons. For these, you can create an icon and bind it to the appropriate property (refer to the properties table, javax/swing/plaf/synth/doc-files/componentProperties.html). For example, to paint radio buttons that are selected or unselected, use this code:

<style id="radioButton">
   <imageIcon id="radio_off" path="images/radio_button_off.png"/>
   <imageIcon id="radio_on" path="images/radio_button_on.png"/>
   <property key="RadioButton.icon" value="radio_off"/>
   <state value="SELECTED">
      <property key="RadioButton.icon" value="radio_on"/>
   </state>
</style>
<bind style="radioButton" type="region" key="RadioButton"/>

Custom Painters

Synth's file format allows for embedding arbitrary objects by way of the long-term persistence of JavaBeans components . This ability is particularly useful in providing your own painters beyond the image-based ones Synth provides. For example, the following XML code specifies that a gradient should be rendered in the background of text fields:

<synth>
  <object id="gradient" class="GradientPainter"/>
  <style id="textfield">
    <painter method="textFieldBackground" idref="gradient"/>
  </style>
  <bind style="textfield" type="region" key="textfield"/>
</synth>
Where the GradientPainter class looks like this:
public class GradientPainter extends SynthPainter {
   public void paintTextFieldBackground(SynthContext context,
                                        Graphics g, int x, int y,
                                        int w, int h) {
      // For simplicity this always recreates the GradientPaint. In a
      // real app you should cache this to avoid garbage.
      Graphics2D g2 = (Graphics2D)g;
      g2.setPaint(new GradientPaint((float)x, (float)y, Color.WHITE,
                 (float)(x + w), (float)(y + h), Color.RED));
      g2.fillRect(x, y, w, h);
      g2.setPaint(null);
   }
}

Conclusion

In this lesson, we have covered the use of the javax.swing.plaf.synth package to create a custom look and feel. The emphasis of the lesson has been on using an external XML file to define the look and feel. The next lesson presents a sample application that creates a search dialog box using the Synth framework with an XML file.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Set the Look and Feel
Next page: A Synth Example


A Synth Example (The Java™ Tutorials > Creating a GUI with JFC/Swing > Modifying the Look and Feel)

Trail: Creating a GUI with JFC/Swing
Lesson: Modifying the Look and Feel
Section: The Synth Look and Feel
Modifying the Look and Feel
How to Set the Look and Feel
The Synth Look and Feel
A Synth Example
Home Page > Creating a GUI with JFC/Swing > Modifying the Look and Feel
« Previous • Trail • Next »
A Synth Example
In the lesson titled A GroupLayout Example , GroupLayout was used to create a search dialog box called "Find." The program that created the dialog box, Find.java, used the cross platform ("Metal") look and feel with the "Ocean" theme:

This lesson creates the same dialog box with Synth, using an external XML file. Here is the listing of the SynthDialog.javafile.

SynthDialog.java is exactly the same as Find.java except for the initLookAndFeel() method, which has been altered to use the Synth look and feel with an external file called synthDemo.xml. Here is the new initLookAndFeel() method:

private static void initLookAndFeel() {
   SynthLookAndFeel lookAndFeel = new SynthLookAndFeel();

   // SynthLookAndFeel load() method throws a checked exception
   // (java.text.ParseException) so it must be handled
   try {
      lookAndFeel.load(SynthDialog.class.getResourceAsStream("synthDemo.xml"),
                                                               SynthDialog.class);
      UIManager.setLookAndFeel(lookAndFeel);
   }

   catch (ParseException e) {
      System.err.println("Couldn't get specified look and feel ("
                                   + lookAndFeel
                                    + "), for some reason.");
      System.err.println("Using the default look and feel.");
      e.printStackTrace();
   }
}

The XML File

The XML file, synthDemo.xml, begins with a style bound to all regions. It is good practice to do this to ensure that regions without a style bound to them will contain something. This style makes all regions paint their background in an opaque color. It also sets a default font and default colors.

  <!-- Style that all regions will use -->
  <style id="backingStyle">
    <!-- Make all the regions opaque-->
    <opaque value="TRUE"/>
    <font name="Dialog" size="14"/>
    <state>
      <color value="#D8D987" type="BACKGROUND"/>
      <color value="RED" type="FOREGROUND"/>
    </state>
  </style>
  <bind style="backingStyle" type="region" key=".*"/>

Notes:

1. The color definitions must be inside a <state> element. This permits changing colors depending on state. The <state> element in backingStyle has no attributes and is therefore applied to all regions, irrespective of their state. If a region has other states, the states are merged with precedence given to state definitions that appear later in the file.

2. The font definition is not inside a <state> element because the font should not change when there is a change of state (many components are sized depending on their font, and a change in font could cause components to change in size unintentionally).

The next <style> element defined is for the text field, which is painted using an image.

  <style id="textfield">
    <insets top="4" left="6" bottom="4" right="6"/>
    <state>
       <font name="Verdana" size="14"/>
       <color value="#D2DFF2" type="BACKGROUND"/>
       <color value="#000000" type="TEXT_FOREGROUND"/>
    </state>
    <imagePainter method="textFieldBorder" path="images/textfield.png"
                  sourceInsets="4 6 4 6" paintCenter="false"/>
  </style>
  <bind style="textfield" type="region" key="TextField"/>

Notes:

1. The font and color definitions override the definitions in backingStyle.

2. The insets and sourceInsets are given the same values, which is just a coincidence because they are unrelated to each other.

3. The BACKGROUND color, #D2DFF2, is a pale blue—the same color as the background in the image, textfield.png.

4. paintCenter is false so that you can see the background color.

The next <style> element is for buttons that are painted with different images, depending on the button state. When the mouse passes over the button, its appearance changes. When it is clicked (PRESSED) the image changes again.

 <style id="button">
      <!-- Shift the text one pixel when pressed -->
    <property key="Button.textShiftOffset" type="integer" value="1"/>
    <!-- set size of buttons -->
    <insets top="15" left="20" bottom="15" right="20"/>
    <state>
      <imagePainter method="buttonBackground" path="images/button.png"
                           sourceInsets="10 10 10 10" />
      <font name="Dialog" size="16"/>
      <color type="TEXT_FOREGROUND" value="#FFFFFF"/>
    </state>

    <state value="PRESSED">
      <imagePainter method="buttonBackground"
          path="images/button_press.png"
                   sourceInsets="10 10 10 10" />
    </state>

    <state value="MOUSE_OVER">
      <imagePainter method="buttonBackground"
          path="images/button_over.png"
                 sourceInsets="10 10 10 10" />
    </state>
  </style>
  <bind style="button" type="region" key="Button"/>

Notes:

1. The font and color definitions inside the <state> element without attributes apply to all button states. This is because the definitions of all states that apply (and the <state> element without attributes is one of these) will merge and there are no other font and color definitions that might take precedence.

2. The sourceInsets values are large enough that the curved corners of the button image will not be stretched.

3. The order of the PRESSED and MOUSE_OVER states is important. Since the mouse will always be over the button when it is pressed, both states will apply to a pressed button and the first state defined (PRESSED) will apply. When the mouse is over the button but it is not pressed, only the MOUSE_OVER state applies. If the order of the PRESSED and MOUSE_OVER states is reversed, the PRESSED state image will never be used.

The next <style> element is for checkboxes that are painted with different icons, depending on the checkbox state.

  <style id="checkbox">
    <imageIcon id="check_off" path="images/checkbox_off.png"/>
    <imageIcon id="check_on" path="images/checkbox_on.png"/>
    <property key="CheckBox.icon" value="check_off"/>
    <state value="SELECTED">
      <property key="CheckBox.icon" value="check_on"/>
    </state>
  </style>
  <bind style="checkbox" type="region" key="Checkbox"/>
Notes:

1. You must use the <imageIcon> element to define any icons to be used.

2. The <insets> element and the sourceInsets attribute are not used with icons because they are rendered in their fixed size and are not stretched.

3. The icon used to render the checkbox is the icon named in the CheckBox.icon property. (see javax/swing/plaf/synth/doc-files/componentProperties.html), which is the icon with id="check_off" unless the checkbox state is SELECTED.

The synthDemo.xml file is constructed of the styles presented above, wrapped in <synth></synth> tags. You can open the completed file by clicking synthDemo.xml.

Try this: Click the Launch button to run the SynthDialog example using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SynthDialog example
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Synth Look and Feel
Next page: Drag and Drop and Data Transfer


Lesson: Drag and Drop and Data Transfer (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Lesson: Drag and Drop and Data Transfer
Examples Index

This section has been updated to reflect features and conventions of the latest release, JDK 6.0, but it is not yet final. We've published this preliminary version so you can get the most current information now, and so you can tell us (please!) about errors, omissions, or improvements we can make to this tutorial.
Drag and drop, and cut, copy and paste (collectively called data transfer) are essential features of most applications. But what kind of support does Swing provide and how do you take advantage of it?

For many components, when performing a drag and drop or a cut and paste operation, Swing handles all of the work for you. For a handful of components, most of the work is done for you and all that is left for you is to plug in the details of the data import and export.

This lesson provides an introduction to the data transfer mechanism used by Swing and discusses, in particular, the TransferHandler class, the workhorse of the data transfer system.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Introduction to DnD


Introduction to DnD (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Introduction to DnD
If you are writing an application you will want to support the ability to transfer information between components in your application. But you will also want your application to play well with others — this includes supporting the ability to transfer information between your application and other Java applications, and between your application and native applications. The ability to transfer data takes two forms:
  • Drag and drop (DnD) support. The following diagram illustrates dragging from a JList and dropping onto a JTextField component (the arrows show the path of the data):

    Drag and Drop Illustration

  • Clipboard transfer through cut or copy and paste. The following diagrams show cutting (or copying) from a JList and pasting onto a JTextField component:

Drag and Drop — Behind the Scenes

Let us say there is a user named Rollo, who is running a Java application. He wants to drag some text from a list and deposit it into a text field. (Note that the process is the same when dragging from a native application to a Java application.) In a nutshell, the drag and drop process works like this:

  • Rollo has selected a row of text in the source component: the list. While holding the mouse button Rollo begins to drag the text — this initiates the drag gesture.

  • When the drag begins, the list packages up the data for export and declares what source actions it supports, such as COPY, MOVE, or LINK.

  • As Rollo drags the data, Swing continuously calculates the location and handles the rendering.

  • If Rollo simultaneously holds the Shift and/or Control key during the drag, this user action is also part of the drag gesture. Typically, an ordinary drag requests the MOVE action. Holding the Control key while dragging requests the COPY action, and holding both Shift and Control requests the LINK action.

  • Once Rollo drags the text over the bounds of a text field component, the target is continually polled to see if it will accept or reject the potential drop. As he drags, the target provides feedback by showing the drop location, perhaps an insertion cursor or a highlighted selection. In this case, the text field (the current target) allows both replacement of selected text and insertion of new text.

  • When Rollo releases the mouse button, the text component inspects the declared source actions and any user action and then it chooses what it wants out of the available options. In this case, the text field chooses to insert the new text at the point of the drop.

  • Finally, the text field imports the data.

While this might seem like a daunting process, Swing handles most of the work for you. The framework is designed so that you plug in the details specific to your component, and the rest "just works".

More on this in the next section.

Note: We do not recommend that you create your own drag and drop support using the AWT classes. This implementation would require significant complex support internal to each component. Prior to release 1.4 when the dnd system was reworked, developers did occasionally create their own dnd support, but it does not work with sophisticated components, like tree and table, that have subtle selection and drop issues.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Drag and Drop and Data Transfer
Next page: Default DnD Support


Default DnD Support (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Default DnD Support
Technically speaking, the framework for drag and drop supports all Swing components — the data transfer mechanism is built into every JComponent. If you wanted, you could implement drop support for a JSlider so that it could fully participate in data transfer. While JSlider does not support drop by default, the components you would want (and expect) to support drag and drop do provide specialized built-in support.

The following components recognize the drag gesture once the setDragEnabled(true) method is invoked on the component. For example, once you invoke myColorChooser.setDragEnabled(true) you can drag colors from your color chooser:

  • JColorChooser
  • JEditorPane
  • JFileChooser
  • JFormattedTextField
  • JList
  • JTable
  • JTextArea
  • JTextField
  • JTextPane
  • JTree

The following components support drop out of the box. If you are using one of these components, your work is done.

  • JEditorPane
  • JFormattedTextField
  • JPasswordField
  • JTextArea
  • JTextField
  • JTextPane
  • JColorChooser

The framework for drop is in place for the following components, but you need to plug in a small amount of code to customize the support for your needs.

  • JList
  • JTable
  • JTree
For these critical components, Swing performs the drop location calculations and rendering; it allows you to specify a drop mode; and it handles component specific details, such as tree expansions. Your work is fairly minimal.
Note: You can also install drop support on top-level containers, such as JFrame and JDialog. You can learn more about this in Top-Level Drop.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Introduction to DnD
Next page: Demo - BasicDnD


Demo - BasicDnD (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Section: Default DnD Support
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Demo - BasicDnD
Now we will look at a simple demo, called BasicDnD, that shows you what you get for free. As you see from the screen shot, BasicDnD contains a table, a list, a tree, a color chooser, a text area, and a text field.

All of these components are standard out-of-the-box components except for the list. This list has been customized to bring up a dialog showing where the drop would occur, if it accepted drops.

The following areas accept drops:

  • Text field
  • Text area
  • The color chooser accepts drops of type color, but in order to try this, you need to run two copies of the demo (or another demo that contains a color chooser)

By default, none of the objects has default drag and drop enabled. At startup, you can check the "Turn on Drag and Drop" check box to see what drag and drop behavior you get for free.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Try this:
  1. Click the Launch button to run BasicDnD using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the BasicDnD example

  2. Select an item in the list and, while holding down the mouse button, begin to drag. Nothing happens because the drag has not yet been enabled on the list.
  3. Select the "Turn on Drag and Drop" check box.
  4. Press the selected item in the list and begin to drag. Drop the text back onto the list. A dialog shows where the text would appear if the list actually accepted drops. (The default behavior for a list would be to show a "does not accept data" cursor.)
  5. Drag the selected text over a text area. The insertion point for the text is indicated by a blinking caret. Also, the cursor changes to indicate that the text area will accept the text as a copy.
  6. Release the mouse and watch the text appear in the text area.
  7. Select some text in one of the text areas.
  8. Press the mouse button while the cursor is over the selected text and begin to drag.
  9. Note that this time, the cursor for a drag action appears. Successfully dropping this text into another component will cause the text to be removed from the original component.
  10. Hold the Control key down and press again on the selected text. Begin dragging and the copy cursor now appears. Move the cursor over the text area and drop. The text appears in the new location but is not removed from the original location. The Control key can be used to change any Move to a Copy.
  11. Select a color from the color chooser. The selected color appears in the Preview panel. Press and hold the mouse button over the color in the Preview panel and drag it over the other components. Note that none of these components accepts color.
  12. Try dropping text, color, and even files, onto the list. A dialog will report the attempted action. The actual drop can be implemented with an additional six lines of code that have been commented out in the BasicDnD.java source file.

Next we will look at the TransferHandler class, the workhorse of the drag and drop mechanism.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Default DnD Support
Next page: TransferHandler Class


TransferHandler Class (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
TransferHandler Class
At the heart of the data transfer mechanism is the TransferHandler class. As its name suggests, the TransferHandler provides an easy mechanism for transferring data to and from a JComponent — all the details are contained in this class and its supporting classes. Most components are provided with a default transfer handler. You can create and install your own transfer handler on any component.

There are three methods used to engage a TransferHandler on a component:

  • setDragEnabled(boolean) — turns on drag support. (The default is false.) This method is defined on each component that supports the drag gesture; the link takes you to the documentation for JList.

  • setDropMode(DropMode) — configures how drop locations are determined. This method is defined for JList, JTable, and JTree; the link takes you to the documentation for JList.

  • setTransferHandler(TransferHandler) — used to plug in custom data import and export. This method is defined on JComponent, so it is inherited by every Swing component.

As mentioned previously, the default Swing transfer handlers, such as those used by text components and the color chooser, provide the support considered to be most useful for both importing and exporting of data. However list, table, and tree do not support drop by default. The reason for this is that there is no all-purpose way to handle a drop on these components. For example, what does it mean to drop on a particular node of a JTree? Does it replace the node, insert below it, or insert as a child of that node? Also, we do not know what type of model is behind the tree — it might not be mutable.

While Swing cannot provide a default implementation for these components, the framework for drop is there. You need only to provide a custom TransferHandler that manages the actual import of data.

Note: If you install a custom TransferHandler onto a Swing component, the default support is replaced. For example, if you replace JTextField's TransferHandler with one that handles colors only, you will disable its ability to support import and export of text.

If you must replace a default TransferHandler — for example, one that handles text — you will need to re-implement the text import and export ability. This does not need to be as extensive as what Swing provides &mdash it could be as simple as supporting the StringFlavor data flavor, depending on your application's needs.

Next we show what TransferHandler methods are required to implement data export.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Demo - BasicDnD
Next page: Export Methods


Export Methods (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Section: TransferHandler Class
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Export Methods
The first set of methods we will examine are used for exporting data from a component. These methods are invoked for the drag gesture, or the cut/copy action, when the component in question is the source of the operation. The TransferHandler methods for exporting data are:
  • getSourceActions(JComponent) — This method is used to query what actions are supported by the source component, such as COPY, MOVE, or LINK, in any combination. For example, a customer list might not support moving a customer name out of the list, but it would very likely support copying the customer name. Most of our examples support both COPY and MOVE.

  • createTransferable(JComponent) — This method bundles up the data to be exported into a Transferable object in preparation for the transfer.

  • exportDone(JComponent, Transferable, int) — This method is invoked after the export is complete. When the action is a MOVE, the data needs to be removed from the source after the transfer is complete — this method is where any necessary cleanup occurs.

Sample Export Methods

Here are some sample implementations of the export methods:

int getSourceActions(JComponent c) {
    return COPY_OR_MOVE;
}

Transferable createTransferable(JComponent c) {
    return new StringSelection(c.getSelection());
}

void exportDone(JComponent c, Transferable t, int action) {
    if (action == MOVE) {
        c.removeSelection();
    }
}

Next we will look at the TransferHandler methods required for data import.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: TransferHandler Class
Next page: Import Methods


Import Methods (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Section: TransferHandler Class
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Import Methods
Now we will look at the methods used for importing data into a component. These methods are invoked for the drop gesture, or the paste action, when the component is the target of the operation. The TransferHandler methods for importing data are:

  • canImport(TransferHandler.TransferSupport) — This method is called repeatedly during a drag gesture and returns true if the area below the cursor can accept the transfer, or false if the transfer will be rejected. For example, if a user drags a color over a component that accepts only text, the canImport method for that component's TransferHandler should return false.

  • importData(TransferHandler.TransferSupport) — This method is called on a successful drop (or paste) and initiates the transfer of data to the target component. This method returns true if the import was successful and false otherwise.
Version note: These methods replace older versions that do not use the TransferSupport class, introduced in JDK 6. Unlike its replacement method, canImport(JComponent, DataFlavor[]) is not called continuously.

You will notice that these import methods take a TransferHandler.TransferSupport argument. Next we look at the TransferSupport class and then some sample import methods.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Export Methods
Next page: TransferSupport Class


TransferSupport Class (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
TransferSupport Class
The TransferSupport class, one of the inner classes of the TransferHandler class introduced in JDK 6, serves two functions. As the name suggests, its first function is to support the transfer process and for that purpose it provides several utility methods used to access the details of the data transfer. The following list shows the methods that can be used to obtain information from the TransferHandler. Several of these methods are related to drop actions, which will be discussed in Setting the Drop Mode.

  • Component getComponent()— This method returns the target component of the transfer.

  • int getDropAction() — This method returns the chosen action (COPY, MOVE or LINK) when the transfer is a drop. If the transfer is not a drop, this method throws an exception.

  • int getUserDropAction() — This method returns the user's chosen drop action. For example, if the user simultaneously holds Control and Shift during the drag gesture, this indicates an ACTION_LINK action. For more information on user drop actions, see the API for DropTargetDragEvent. If the transfer is not a drop, this method throws an exception.

  • int getSourceDropActions() — This method returns the set of actions supported by the source component. If the transfer is not a drop, this method throws an exception.

  • DataFlavor[] getDataFlavors() — This method returns all the data flavors supported by this component. For example, a component might support files and text, or text and color. If the transfer is not a drop, this method throws an exception.

  • boolean isDataFlavorSupported(DataFlavor) — This method returns true if the specified DataFlavor is supported. The DataFlavor indicates the type of data represented, such as an image (imageFlavor), a string (stringFlavor), a list of files (javaFileListFlavor), and so on.

  • Transferable getTransferable() — This method returns the Transferable data for this transfer. It is more efficient to use one of these methods to query information about the transfer than to fetch the transferable and query it, so this method is not recommended unless you cannot get the information another way.

  • DropLocation getDropLocation() — This method returns the drop location in the component. Components with built-in drop support, such as list, table and tree, override this method to return more useful data. For example, the version of this method for the JList component returns the index in the list where the drop occurred. If the transfer is not a drop, this method throws an exception.

Sample Import Methods

Now that you are familiar with the TransferSupport utility methods, let us look at sample canImport and importData methods:
public boolean canImport(TransferSupport supp) {
    // Check for String flavor
    if (!supp.isDataFlavorSupported(stringFlavor)) {
        return false;
    }

    // Fetch the drop location
    DropLocation loc = supp.getDropLocation();

    // Return whether we accept the location
    return shouldAcceptDropLocation(loc);
}

public boolean importData(TransferSupport supp) {
    if (!canImport(sup)) {
        return false;
    }

    // Fetch the Transferable and its data
    Transferable t = supp.getTransferable();
    String data = t.getTransferData(stringFlavor);

    // Fetch the drop location
    DropLocation loc = supp.getDropLocation();

    // Insert the data at this location
    insertAt(loc, data);

    return true;
}

Next we look at how you can set the drop mode for selected components.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Import Methods
Next page: Setting the Drop Mode


Setting the Drop Mode (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Setting the Drop Mode
When enabling drop on a component, such as a list, you need to decide how you want the drop location to be interpreted. For example, do you want to restrict the user to replacing existing entries? Do you want to only allow adding or inserting new entries? Do you want to allow both? To configure this behavior, the JList class provides the setDropMode method which supports the following drop modes.

  • The default drop mode for JList is DropMode.USE_SELECTION. When dragging in this mode, the selected item in the list moves to echo the potential drop point. On a drop the selected item shifts to the drop location. This mode is provided for backwards compatibility but is otherwise not recommended.

  • In DropMode.ON, the selected item in the list moves to echo the potential drop point, but the selected item is not affected on the drop. This mode can be used to drop on top of existing list items.

  • In DropMode.INSERT, the user is restricted to selecting the space between existing list items, or before the first item or after the last item in the list. Selecting existing list items is not allowed.

  • DropMode.ON_OR_INSERT is a combination of the ON and INSERT modes.

The JTree class provides the same set of drop modes and the JTable class has several more specific to adding rows or columns.

To obtain the location of the drop, the TransferSupport class provides the getDropLocation method that returns the precise point where the drop has occurred. But for a list component, the index of the drop is more useful than a pixel location, so JList provides a special subclass, called JList.DropLocation. This class provides the getIndex and isInsert methods, which handle the math for you.

The table, tree, and text components each provide an implementation of DropLocation with methods that make the most sense for each component. The JTable.setDropMode method has the most choices. The following table shows the methods for all four classes:

DropLocation Methods for JList, JTree, JTable and JTextComponent
JList.DropLocation JTree.DropLocation JTable.DropLocation JTextComponent.DropLocation
isInsert getChildIndex isInsertRow getIndex
getIndex getPath isInsertColumn getBias
getRow
getColumn

Next is a demo that implements a custom transfer handler for a list component so that it fully participates in drag and drop.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: TransferSupport Class
Next page: Demo - DropDemo


Demo - DropDemo (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Section: Setting the Drop Mode
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Demo - DropDemo
Now we will look at a demo that uses a custom transfer handler to implement drop for a list component. Although the default transfer handler for list implements export, because we are creating a custom transfer handler to implement import, we have to re-implement export as well.

As you see from the screen shot, DropDemo contains an editable text area, a list, and a combo box that allows you to select the drop mode for the list.

DropDemo screen shot

Try this:
  1. Click the Launch button to run DropDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the DropDemo example

  2. Select some text in the text area and drop onto the list. The selected list entry is replaced and that item becomes the current selection. This is how USE_SELECTION works and is provided for backwards compatibility but is otherwise not recommended.
  3. Change the List Drop Mode to ON and try the same action. Once again, the selected list item is replaced, but the current selection does not move.
  4. Change the List Drop Mode to INSERT and repeat the same action. The added text is inserted at the drop location. In this mode it is not possible to modify existing list items.
  5. Change the List Drop Mode to ON_OR_INSERT. Depending on the cursor position, you can either insert the new text or you can replace existing text.

Here is the ListTransferHandler implementation for DropDemo.java.

The transfer handler for this list supports copy and move and it reimplements the drag support that list provides by default.

public class ListTransferHandler extends TransferHandler {
    private int[] indices = null;
    private int addIndex = -1; //Location where items were added
    private int addCount = 0;  //Number of items added.

    /**
     * We only support importing strings.
     */
    public boolean canImport(TransferHandler.TransferSupport info) {
        // Check for String flavor
        if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) {
            return false;
        }
        return true;
   }

    /**
     * Bundle up the selected items in a single list for export.
     * Each line is separated by a newline.
     */
    protected Transferable createTransferable(JComponent c) {
        JList list = (JList)c;
        indices = list.getSelectedIndices();
        Object[] values = list.getSelectedValues();

        StringBuffer buff = new StringBuffer();

        for (int i = 0; i < values.length; i++) {
            Object val = values[i];
            buff.append(val == null ? "" : val.toString());
            if (i != values.length - 1) {
                buff.append("\n");
            }
        }

        return new StringSelection(buff.toString());
    }

    /**
     * We support both copy and move actions.
     */
    public int getSourceActions(JComponent c) {
        return TransferHandler.COPY_OR_MOVE;
    }

    /**
     * Perform the actual import.  This demo only supports drag and drop.
     */
    public boolean importData(TransferHandler.TransferSupport info) {
        if (!info.isDrop()) {
            return false;
        }

        JList list = (JList)info.getComponent();
        DefaultListModel listModel = (DefaultListModel)list.getModel();
        JList.DropLocation dl = (JList.DropLocation)info.getDropLocation();
        int index = dl.getIndex();
        boolean insert = dl.isInsert();

        // Get the string that is being dropped.
        Transferable t = info.getTransferable();
        String data;
        try {
            data = (String)t.getTransferData(DataFlavor.stringFlavor);
        }
        catch (Exception e) { return false; }

        // Wherever there is a newline in the incoming data,
        // break it into a separate item in the list.
        String[] values = data.split("\n");

        addIndex = index;
        addCount = values.length;

        // Perform the actual import.
        for (int i = 0; i < values.length; i++) {
            if (insert) {
                listModel.add(index++, values[i]);
            } else {
                // If the items go beyond the end of the current
                // list, add them in.
                if (index < listModel.getSize()) {
                    listModel.set(index++, values[i]);
                } else {
                    listModel.add(index++, values[i]);
                }
            }
        }
        return true;
    }

    /**
     * Remove the items moved from the list.
     */
    protected void exportDone(JComponent c, Transferable data, int action) {
        JList source = (JList)c;
        DefaultListModel listModel  = (DefaultListModel)source.getModel();

        if (action == TransferHandler.MOVE) {
            for (int i = indices.length - 1; i >= 0; i--) {
                listModel.remove(indices[i]);
            }
        }

        indices = null;
        addCount = 0;
        addIndex = -1;
    }
}

Next we look at how the target can choose the drop action.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Setting the Drop Mode
Next page: Choosing the Drop Action


Choosing the Drop Action (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Choosing the Drop Action
Every drag source (Java based or otherwise) advertises the set of actions it supports when exporting data. If it supports data being copied, it advertises the COPY action; if it supports data being moved from it, then it advertises the MOVE action, and so on. For Swing components, the source actions are advertised through the getSourceActions method.

When a drag is initiated, the user has some control over which of the source actions is chosen for the transfer by way of keyboard modifiers used in conjunction with the drag gesture — this is called the user action. For example, the default (where no modifiers are used) generally indicates a move action, holding the Control key indicates a copy action, and holding both Shift and Control indicates a linking action. The user action is available via the getUserDropAction method.

The user action indicates a preference, but ultimately it is the target that decides the drop action. For example, consider a component that will only accept copied data. And consider a drag source that supports both copy and move. The TransferHandler for the copy-only target can be coded to only accept data from the source using the setDropAction method, even if the user has indicated a preference for a move action.

This work happens in the canImport method, where the target's TransferHandler decides whether to accept the incoming data. An implementation that explicitly chooses the COPY action, if it is supported by the source, might look like this:

public boolean canImport(TransferHandler.TransferSupport support) {
    // for the demo, we will only support drops (not clipboard paste)
    if (!support.isDrop()) {
        return false;
    }

    // we only import Strings
    if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
        return false;
    }

    // check if the source actions (a bitwise-OR of supported actions)
    // contains the COPY action
    boolean copySupported = (COPY & support.getSourceDropActions()) == COPY;
    if (copySupported) {
        support.setDropAction(COPY);
        return true;
    }

    // COPY is not supported, so reject the transfer
    return false;
}

The code snippet displayed in bold shows where the source's supported drop actions are queried. If copy is supported, the setDropAction method is invoked to ensure that only a copy action will take place and the method returns true.

Next we will look at a demo that explicitly sets the drop action using setDropAction.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Demo - DropDemo
Next page: Demo - ChooseDropAction


Demo - ChooseDropAction (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Section: Choosing the Drop Action
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Demo - ChooseDropAction
The following demo, ChooseDropActionDemo, contains three lists. As you can see in the screen shot, the list on the left, labeled "Drag from here", is the drag source. This list supports both move and copy but it does not implement import — so you cannot drop into it.

On the right side are two lists that act as drop targets. The top list, labeled "Drop to COPY here" will only allow data to be copied to it. The bottom list, labeled "Drop to MOVE here" will only allow data to be moved to it. The source list only allows data to be dragged from it.

A snapshot of the ChooseDropActionDemo demo.

Try this:
  1. Click the Launch button to run ChooseDropActionDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ChooseDropActionDemo example

  2. Select an item in the source list and drag to the upper target list. As you drag over the target, notice that the copy-drop mouse cursor displays, even if you are not holding the Control key to signify that you want a copy action. (Note that the copy cursor does not appear on the Macintosh platform, unless you are pressing the Option key.)
  3. Drop the item. It is inserted into the target list but not removed from the source — as desired.
  4. Drag again from the source list, but this time into the lower target list. Drop the item. It is inserted into the target list and removed from the source list.
  5. Select another item in the source list and, while pressing the Control key to indicate a preference for the COPY action, drag the item to the lower target list.
  6. Drop the item into the list. The item is not inserted — the drop is rejected. The canImport method for the transfer handler was coded to reject the COPY action, but it could have been implemented to return true, in which case the user action would prevail and a copy would occur.

As you might guess, the ChooseDropActionDemo.java example contains two TransferHandler implementations:

/**
 * The FromTransferHandler allows dragging from the list and
 * supports both copy and move actions.  This transfer handler
 * does not support import.
 */
class FromTransferHandler extends TransferHandler {
    public int getSourceActions(JComponent comp) {
        return COPY_OR_MOVE;
    }

    private int index = 0;

    public Transferable createTransferable(JComponent comp) {
        index = dragFrom.getSelectedIndex();
        if (index < 0 || index >= from.getSize()) {
            return null;
        }

        return new StringSelection((String)dragFrom.getSelectedValue());
    }

    public void exportDone(JComponent comp, Transferable trans, int action) {
        if (action != MOVE) {
            return;
        }

        from.removeElementAt(index);
    }
}

/**
 * The ToTransferHandler has a constructor that specifies whether the
 * instance will support only the copy action or the move action.
 * This transfer handler does not support export.
 */
class ToTransferHandler extends TransferHandler {
    int action;

    public ToTransferHandler(int action) {
        this.action = action;
    }

    public boolean canImport(TransferHandler.TransferSupport support) {
        // for the demo, we will only support drops (not clipboard paste)
        if (!support.isDrop()) {
            return false;
        }

        // we only import Strings
        if (!support.isDataFlavorSupported(DataFlavor.stringFlavor)) {
            return false;
        }

        // check if the source actions contain the desired action -
        // either copy or move, depending on what was specified when
        // this instance was created
        boolean actionSupported = (action & support.getSourceDropActions()) == action;
        if (actionSupported) {
            support.setDropAction(action);
            return true;
        }

        // the desired action is not supported, so reject the transfer
        return false;
    }

    public boolean importData(TransferHandler.TransferSupport support) {
        // if we cannot handle the import, say so
        if (!canImport(support)) {
            return false;
        }

        // fetch the drop location
        JList.DropLocation dl = (JList.DropLocation)support.getDropLocation();

        int index = dl.getIndex();

        // fetch the data and bail if this fails
        String data;
        try {
            data = (String)support.getTransferable().getTransferData(DataFlavor.stringFlavor);
        } catch (UnsupportedFlavorException e) {
            return false;
        } catch (java.io.IOException e) {
            return false;
        }

        JList list = (JList)support.getComponent();
        DefaultListModel model = (DefaultListModel)list.getModel();
        model.insertElementAt(data, index);

        Rectangle rect = list.getCellBounds(index, index);
        list.scrollRectToVisible(rect);
        list.setSelectedIndex(index);
        list.requestFocusInWindow();

        return true;
    }
}

The FromTransferHandler, attached to the source list, allows for dragging from the list and supports both copy and move actions. If you try to drop onto this list, the drop will be rejected because FromTransferHandler has not implemented the canImport and importData methods.

The ToTransferHandler, attached to both the move-only and the copy-only target list, contains a constructor that specifies whether the target list will allow only copy or only move. An instance that supports the copy action is attached to the copy-only list and an instance that supports the move action is attached to the move-only list.

You might also be interested in the Top-Level Drop example which also illustrates choosing the drop action.

Next we look at showing the drop location.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Choosing the Drop Action
Next page: Showing the Drop Location


Showing the Drop Location (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Showing the Drop Location
Generally during a drag operation, a component gives visual feedback when it can accept the data. It might highlight the drop location, or it might show a caret or a horizontal line where the insertion would occur. Swing renders the drop location when the canImport method for the component's TransferHandler returns true.

To control this programmatically, you can use the setShowDropLocation method. Calling this method with true causes the visual feedback for the drop location to always be displayed, even if the drop will not be accepted. Calling this method with false prevents any visual feedback, even if the drop will be accepted. You always invoke this method from canImport.

The Demo - LocationSensitiveDemo page includes a combo box that enables you to choose to always show the drop location, or never show the drop location, or the default behavior. But first we will talk about location sensitive drop.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Demo - ChooseDropAction
Next page: Location Sensitive Drop


Location Sensitive Drop (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Location Sensitive Drop
Sometimes you have a complex component and you want the user to be able to drop on some parts of it, but not on others. Perhaps it is a table that allows data to be dropped only in certain columns; or perhaps it is a tree that allows data to be dropped only on certain nodes. Obviously you want the cursor to provide accurate feedback — it should only show the drop location when it is over the specific part of the component that accepts drops.

This is simple to accomplish by installing the necessary logic in the canImport(TransferHandler.TransferSupport) method of the TransferHandler class. It works only with this particular version of canImport because it is called continously while the drag gesture is over the bounds of the component. When this method returns true, Swing shows the drop cursor and the drop location is visually indicated; when this method returns false, Swing shows the "no-drag" cursor and the drop location is not displayed.

For example, imagine a table that allows drop, but not in the first column. The canImport method might look something like this:

public boolean canImport(TransferHandler.TransferSupport info) {
    // for the demo, we will only support drops (not clipboard paste)
    if (!info.isDrop()) {
        return false;
    }

    // we only import Strings
    if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) {
        return false;
    }

    // fetch the drop location
    JTable.DropLocation dl = (JTable.DropLocation)info.getDropLocation();

    int column = dl.getColumn();

    // we do not support invalid columns or the first column
    if (column == -1 || column == 0) {
        return false;
    }

    return true;
}

The code displayed in bold indicates the location-sensitive drop logic: When the user drops the data in such a way that the column cannot be calculated (and is therefore invalid) or when the user drops the text in the first column, the canImport method returns false — so Swing shows the "no-drag" mouse cursor. As soon as the user moves the mouse off the first column canImport returns true and Swing shows the drag cursor.

Next, we show a demo of a tree that has implemented location-sensitive drop.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Showing the Drop Location
Next page: Demo - LocationSensitiveDemo


Demo - LocationSensitiveDemo (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Section: Location Sensitive Drop
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Demo - LocationSensitiveDemo
The following demo, LocationSensitiveDemo, shows a JTree that has been configured to support drop on any node except for one called "names" (or its descendants). Use the text field at the top of the frame as the drag source (it will automatically increment the string number each time you drag from there).

A combo box below the tree allows you to toggle the behavior for showing the drop location. Swing's default behavior is to show the drop location only when the area can accept the drop. You can override this behavior to always show the drop location (even if the area cannot accept the drop) or to never show the drop location (even if the area can accept the drop).

A snapshot of the LocationSensitiveDemo demo.

Try this:
  1. Click the Launch button to run LocationSensitiveDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ListDemo example

  2. Initiate a drag by pressing on top of "String 0" in the text field and moving the mouse a short distance. Drag into the tree and move downwards. As you hover the mouse over most of the nodes, the drag acceptibility is indicated by both the mouse cursor and by the node becoming highlighted. Drop the text onto the "colors" node. The new item becomes a child of that node and a sibling to the colors listed.
  3. Drag "String 1" from the textfield into the tree. Try to drop it on the "names" node. As you drag over that node or its children, Swing will not provide any drop location feedback and it will not accept the data.
  4. Change the "Show drop location" combo box to "Always".
  5. Repeat steps 1 and 2. The drop location now displays for the "names" node, but you cannot drop data into that area.
  6. Change the "Show drop location" combo box to "Never".
  7. Repeat steps 1 and 2. The drop location will not display for any part of the tree, though you can still drop data into the nodes, other than "names".

The canImport method for LocationSensitiveDemo looks like this:

public boolean canImport(TransferHandler.TransferSupport info) {
    // for the demo, we will only support drops (not clipboard paste)
    if (!info.isDrop()) {
        return false;
    }

    String item = (String)indicateCombo.getSelectedItem();

    if (item.equals("Always")) {
        info.setShowDropLocation(true);
    } else if (item.equals("Never")) {
        info.setShowDropLocation(false);
    }

    // we only import Strings
    if (!info.isDataFlavorSupported(DataFlavor.stringFlavor)) {
        return false;
    }

    // fetch the drop location
    JTree.DropLocation dl = (JTree.DropLocation)info.getDropLocation();

    TreePath path = dl.getPath();

    // we do not support invalid paths or descendants of the names folder
    if (path == null || namesPath.isDescendant(path)) {
        return false;
    }

    return true;
}

The first code snippet displayed in bold modifies the drop location feedback mechanism. If "Always", then the drop location is always shown. If "Never", the drop location is never shown. Otherwise, the default behavior applies.

The second code snippet displayed in bold contains the logic that determines whether the tree will accept the data. If the path is not a valid path or if it is not the names path (or its descendant) it will return false and the import will not be accepted.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Location Sensitive Drop
Next page: Empty Table Drop


Empty Table Drop (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Empty Table Drop
Dragging and dropping into an empty table presents a unique challenge. When adhering to the proper steps:
  • Creating the empty table.
  • Creating and attaching a TransferHandler.
  • Enabling data transfer by calling setDragEnabled(true).
  • Creating a scroll pane and adding the table to the scroll pane.
You run the application and try to drag valid data into the table but it rejects the drop. What gives?

The reason is that the empty table (unlike an empty list or an empty tree) does not occupy any space in the scroll pane. The JTable does not automatically stretch to fill the height of a JScrollPane's viewport — it only takes up as much vertical room as needed for the rows that it contains. So, when you drag over the empty table, you are not actually over the table and the drop fails.

You can configure the table to allow drop anywhere in the view port by calling JTable.setFillsViewportHeight(boolean) . The default for this property is false to ensure backwards compatibility.

The following example, FillViewportHeightDemo, allows you to experiment with dropping onto an empty table. The demo contains an empty table with five columns that has its drop mode set to insert rows and a drag source that provides five comma-delimited values that autoincrement.

A snapshot of the FillViewportHeightDemo.

Try this:
  1. Click the Launch button to run FillViewportHeightDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the FillViewportHeightDemo example

  2. Drag from the text field labeled "Drag from here" to the table.
  3. Drop onto the table. The drop is rejected.
  4. Double-click on the drag source. It deposits the current values (0, 0, 0, 0, 0) into the table and increments the values in the text field.
  5. Once again, drag from the text field to the table. You can insert above or below the row, but not in the area underneath.
  6. From the Options menu, choose "Fill Viewport Height" to enable the "fillsViewportHeight" property.
  7. From the Options menu, choose "Reset" to empty the table.
  8. Drag from the text component to the table. You can now drop anywhere on the view port and it inserts the data at row 0.

You can examine the source for FillViewportHeightDemo.java, but the primary point to remember is that you should generally invoke setFillsViewportHeight(true) on any table that will accept dropped data.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Demo - LocationSensitiveDemo
Next page: Drop Location Rendering


Drop Location Rendering (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Drop Location Rendering
This is a more advanced topic and most people do not need to worry about it. However, if you have a custom component you will need to handle the drop location rendering yourself.

You can register to be notified whenever the dropLocation property changes. You would listen for this change and do your own rendering of the drop location in a custom renderer for the component or in the paintComponent method, using the getDropLocation method.

Here is an example of listening for the dropLocation property:

class Repainter extends PropertyChangeListener {
    public void propertyChange(PropertyChangeEvent pce) {
        repaintDropLocation(pce.getOldValue());
        repaintDropLocation(pce.getNewValue());
    }
}

comp.addPropertyChangeListener("dropLocation", newRepainter());

Here is an example of the paintComponent approach:

public void paintComponent(Graphics g) {
    super.paintComponent(g);

    DropLocation loc= getDropLocation();
    if (loc == null) {
        return;
    }

    renderPrettyIndicatorAt(loc);
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Empty Table Drop
Next page: Top-Level Drop


Top-Level Drop (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Top-Level Drop
Up until now, we have primarily focused on attaching a TransferHandler to one of the JComponent subclasses. But you can also set a TransferHandler directly on a top-level container, such as JFrame and JDialog.

This is particularly useful for applications that import files, such as editors, IDEs, image manipulation programs, CD burning programs. Such an application generally includes a menu, a toolbar, an area for editing documents, and probably a list or mechanism for switching between open documents.

We have such an example written by Shannon Hickey, the Swing team lead. Because this demo reads files, we do not provide a Java Web Start version — you will have to download and compile the demo yourself.

As you can see in the screen shot below, TopLevelTransferHandler has a menu (empty, except for the Demo submenu), a (non-functional) toolbar, an area (on the left) that displays a list of open documents, and a area (to the right) that displays the content of each open document. At startup the blue document area has been assigned a transfer handler that supports file imports — so is the only place that can accept a drop.

A snapshot of the TopLevelTransferHandlerDemo demo.

Try this:
  1. Compile and run the TopLevelTransferHandlerDemo example, consult the example index if you would like to download a zip file structured for NetBeans.
  2. Drag a file from your native desktop or file system and drop it on the blue document area to the right. The file is opened and a frame filled with its contents will appear. The document area, a JDesktopPane, contains a transfer handler that supports import of javaFileListFlavor.
  3. Drag another file and attempt to drop it on the document area. You will find that you cannot drop it on top of the frame displaying the last file. You also cannot drop it on the list, the menu, or the toolbar. The only place you can drop is the blue portion of the document area or on the menu bar of a previously opened frame. Inside each content frame there is a text component's transfer handler that doesn't understand a file drop — you can drop text into that area, but not a file.
  4. From the menu, choose Demo->Use Top-Level TransferHandler to install the transfer handler on the top-level container — a JFrame.
  5. Try dragging over the demo again. The number of areas that accept drops has increased. You can now drop most anywhere on the application including the menu bar, toolbar, the frame's title bar, except for the list (on the left) or the content area of a previously opened file. Neither the JList's nor the text area's transfer handlers know how to import files.
  6. Disable the transfer handlers on those remaining components by choosing Demo->Remove TransferHandler from List and Text from the menu.
  7. Drag over the demo again. You can now drop a file anywhere on the application!
  8. From the menu, choose Demo->Use COPY Action.
  9. Drag over the demo again. Note that the mouse cursor now shows the COPY cursor — this provides more accurate feedback because a successful drop does not remove the file from the source. The target can be programmed to select from the available drop actions as described in Choosing the Drop Action.

Note one undesirable side effect of disabling the default transfer handler on the text component: You can no longer drag and drop (or cut/copy/paste) text within the editing area. To fix this, you will need to implement a custom transfer handler for the text component that accepts file drops and also re-implements the missing support for text transfers. You might want to watch RFE 4830695 which would allow adding data import on top of an existing TransferHandler.

Here is the source code for TopLevelTransferHandlerDemo.java:

/**
 * Demonstration of the top-level {@code TransferHandler}
 * support on {@code JFrame}.
 *
 * @author Shannon Hickey
 */
public class TopLevelTransferHandlerDemo extends JFrame {

    private static boolean DEMO = false;

    private JDesktopPane dp = new JDesktopPane();
    private DefaultListModel listModel = new DefaultListModel();
    private JList list = new JList(listModel);
    private static int left;
    private static int top;
    private JCheckBoxMenuItem copyItem;
    private JCheckBoxMenuItem nullItem;
    private JCheckBoxMenuItem thItem;

    private class Doc extends InternalFrameAdapter implements ActionListener {
        String name;
        JInternalFrame frame;
        TransferHandler th;
        JTextArea area;

        public Doc(File file) {
            this.name = file.getName();
            try {
                init(file.toURI().toURL());
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
        }

        public Doc(String name) {
            this.name = name;
            init(getClass().getResource(name));
        }

        private void init(URL url) {
            frame = new JInternalFrame(name);
            frame.addInternalFrameListener(this);
            listModel.add(listModel.size(), this);

            area = new JTextArea();
            area.setMargin(new Insets(5, 5, 5, 5));

            try {
                BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
                String in;
                while ((in = reader.readLine()) != null) {
                    area.append(in);
                    area.append("\n");
                }
                reader.close();
            } catch (Exception e) {
                e.printStackTrace();
                return;
            }

            th = area.getTransferHandler();
            area.setFont(new Font("monospaced", Font.PLAIN, 12));
            area.setCaretPosition(0);
            area.setDragEnabled(true);
            area.setDropMode(DropMode.INSERT);
            frame.getContentPane().add(new JScrollPane(area));
            dp.add(frame);
            frame.show();
            if (DEMO) {
                frame.setSize(300, 200);
            } else {
                frame.setSize(400, 300);
            }
            frame.setResizable(true);
            frame.setClosable(true);
            frame.setIconifiable(true);
            frame.setMaximizable(true);
            frame.setLocation(left, top);
            incr();
            SwingUtilities.invokeLater(new Runnable() {
                public void run() {
                    select();
                }
            });
            nullItem.addActionListener(this);
            setNullTH();
        }

        public void internalFrameClosing(InternalFrameEvent event) {
            listModel.removeElement(this);
            nullItem.removeActionListener(this);
        }

        public void internalFrameOpened(InternalFrameEvent event) {
            int index = listModel.indexOf(this);
            list.getSelectionModel().setSelectionInterval(index, index);
        }

        public void internalFrameActivated(InternalFrameEvent event) {
            int index = listModel.indexOf(this);
            list.getSelectionModel().setSelectionInterval(index, index);
        }

        public String toString() {
            return name;
        }

        public void select() {
            try {
                frame.toFront();
                frame.setSelected(true);
            } catch (java.beans.PropertyVetoException e) {}
        }

        public void actionPerformed(ActionEvent ae) {
            setNullTH();
        }

        public void setNullTH() {
            if (nullItem.isSelected()) {
                area.setTransferHandler(null);
            } else {
                area.setTransferHandler(th);
            }
        }
    }

    private TransferHandler handler = new TransferHandler() {
        public boolean canImport(TransferHandler.TransferSupport support) {
            if (!support.isDataFlavorSupported(DataFlavor.javaFileListFlavor)) {
                return false;
            }

            if (copyItem.isSelected()) {
                boolean copySupported = (COPY & support.getSourceDropActions()) == COPY;

                if (!copySupported) {
                    return false;
                }

                support.setDropAction(COPY);
            }

            return true;
        }

        public boolean importData(TransferHandler.TransferSupport support) {
            if (!canImport(support)) {
                return false;
            }

            Transferable t = support.getTransferable();

            try {
                java.util.List l =
                    (java.util.List)t.getTransferData(DataFlavor.javaFileListFlavor);

                for (File f : l) {
                    new Doc(f);
                }
            } catch (UnsupportedFlavorException e) {
                return false;
            } catch (IOException e) {
                return false;
            }

            return true;
        }
    };

    private static void incr() {
        left += 30;
        top += 30;
        if (top == 150) {
            top = 0;
        }
    }

    public TopLevelTransferHandlerDemo() {
        super("TopLevelTransferHandlerDemo");
        setJMenuBar(createDummyMenuBar());
        getContentPane().add(createDummyToolBar(), BorderLayout.NORTH);

        JSplitPane sp = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, list, dp);
        sp.setDividerLocation(120);
        getContentPane().add(sp);
        //new Doc("sample.txt");
        //new Doc("sample.txt");
        //new Doc("sample.txt");

        list.getSelectionModel().setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

        list.addListSelectionListener(new ListSelectionListener() {
            public void valueChanged(ListSelectionEvent e) {
                if (e.getValueIsAdjusting()) {
                    return;
                }

                Doc val = (Doc)list.getSelectedValue();
                if (val != null) {
                    val.select();
                }
             }
        });

        final TransferHandler th = list.getTransferHandler();

        nullItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                if (nullItem.isSelected()) {
                    list.setTransferHandler(null);
                } else {
                    list.setTransferHandler(th);
                }
            }
        });
        thItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent ae) {
                if (thItem.isSelected()) {
                    setTransferHandler(handler);
                } else {
                    setTransferHandler(null);
                }
            }
        });
        dp.setTransferHandler(handler);
    }

    private static void createAndShowGUI(String[] args) {
        try {
            UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
        } catch (Exception e) {
        }

        TopLevelTransferHandlerDemo test = new TopLevelTransferHandlerDemo();
        test.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        if (DEMO) {
            test.setSize(493, 307);
        } else {
            test.setSize(800, 600);
        }
        test.setLocationRelativeTo(null);
        test.setVisible(true);
        test.list.requestFocus();
    }

    public static void main(final String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                //Turn off metal's use of bold fonts
            UIManager.put("swing.boldMetal", Boolean.FALSE);
                createAndShowGUI(args);
            }
        });
    }

    private JToolBar createDummyToolBar() {
        JToolBar tb = new JToolBar();
        JButton b;
        b = new JButton("New");
        b.setRequestFocusEnabled(false);
        tb.add(b);
        b = new JButton("Open");
        b.setRequestFocusEnabled(false);
        tb.add(b);
        b = new JButton("Save");
        b.setRequestFocusEnabled(false);
        tb.add(b);
        b = new JButton("Print");
        b.setRequestFocusEnabled(false);
        tb.add(b);
        b = new JButton("Preview");
        b.setRequestFocusEnabled(false);
        tb.add(b);
        tb.setFloatable(false);
        return tb;
    }

    private JMenuBar createDummyMenuBar() {
        JMenuBar mb = new JMenuBar();
        mb.add(createDummyMenu("File"));
        mb.add(createDummyMenu("Edit"));
        mb.add(createDummyMenu("Search"));
        mb.add(createDummyMenu("View"));
        mb.add(createDummyMenu("Tools"));
        mb.add(createDummyMenu("Help"));

        JMenu demo = new JMenu("Demo");
        demo.setMnemonic(KeyEvent.VK_D);
        mb.add(demo);

        thItem = new JCheckBoxMenuItem("Use Top-Level TransferHandler");
        thItem.setMnemonic(KeyEvent.VK_T);
        demo.add(thItem);

        nullItem = new JCheckBoxMenuItem("Remove TransferHandler from List and Text");
        nullItem.setMnemonic(KeyEvent.VK_R);
        demo.add(nullItem);

        copyItem = new JCheckBoxMenuItem("Use COPY Action");
        copyItem.setMnemonic(KeyEvent.VK_C);
        demo.add(copyItem);

        return mb;
    }

    private JMenu createDummyMenu(String str) {
        JMenu menu = new JMenu(str);
        JMenuItem item = new JMenuItem("[Empty]");
        item.setEnabled(false);
        menu.add(item);
        return menu;
    }
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Drop Location Rendering
Next page: Adding Cut, Copy and Paste (CCP)


Adding Cut, Copy and Paste (CCP) (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Adding Cut, Copy and Paste (CCP)
So far our discussion has centered mostly around drag and drop support. However, it is an easy matter to hook up cut or copy or paste (ccp) to a transfer handler. This requires the following steps:
  • Ensure a transfer handler is installed on the component.

  • Create a manner by which the TransferHandler's ccp support can be invoked. Typically this involves adding bindings to the input and action maps to have the TransferHandler's ccp actions invoked in response to particular keystrokes.

  • Create ccp menu items and/or buttons. (This step is optional but recommended.) This is easy to do with text components but requires a bit more work with other components, since you need logic to determine which component to fire the action on. See CCP in a non-Text Component for more information.

  • Decide where you want to perform the paste. Perhaps above or below the current selection. Install the logic in the importData method.

Next we look at a cut and paste example that feature a text component.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Top-Level Drop
Next page: CCP in a Text Component


CCP in a Text Component (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
CCP in a Text Component
If you are implementing cut, copy and paste using one of the Swing text components (text field, password field, formatted text field, or text area) your work is very straightforward. These text components utilize the DefaultEditorKit which provides built-in actions for cut, copy and paste. The default editor kit also handles the work of remembering which component last had the focus. This means that if the user initiates one of these actions using the menu or a keyboard equivalent, the correct component receives the action — no additional code is required.

The following demo, TextCutPaste, contains three text fields. As you can see in the screen shot, you can cut, copy, and paste to or from any of these text fields. They also support drag and drop.

A snapshot of the TextCutPaste demo.

Try this:
  1. Click the Launch button to run TextCutPaste using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TextCutPaste example

  2. Select text in one of the text fields. Use the Edit menu or the keyboard equivalent to cut or copy the text from the source.
  3. Position the caret where you want the text to be pasted.
  4. Paste the text using the menu or the keyboard equivalent.
  5. Perform the same operation using drag and drop.

Here is the code that creates the Edit menu by hooking up the built-in cut, copy, and paste actions defined in DefaultEditorKit to the menu items. This works with any component that descends from JComponent:

    /**
     * Create an Edit menu to support cut/copy/paste.
     */
    public JMenuBar createMenuBar () {
        JMenuItem menuItem = null;
        JMenuBar menuBar = new JMenuBar();
        JMenu mainMenu = new JMenu("Edit");
        mainMenu.setMnemonic(KeyEvent.VK_E);

        menuItem = new JMenuItem(new DefaultEditorKit.CutAction());
        menuItem.setText("Cut");
        menuItem.setMnemonic(KeyEvent.VK_T);
        mainMenu.add(menuItem);

        menuItem = new JMenuItem(new DefaultEditorKit.CopyAction());
        menuItem.setText("Copy");
        menuItem.setMnemonic(KeyEvent.VK_C);
        mainMenu.add(menuItem);

        menuItem = new JMenuItem(new DefaultEditorKit.PasteAction());
        menuItem.setText("Paste");
        menuItem.setMnemonic(KeyEvent.VK_P);
        mainMenu.add(menuItem);

        menuBar.add(mainMenu);
        return menuBar;
    }

Next we will look at how to accomplish the same functionality using a component that does not have the built-in support of the DefaultEditorKit.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Adding Cut, Copy and Paste (CCP)
Next page: CCP in a non-Text Component


CCP in a non-Text Component (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
CCP in a non-Text Component
If you are implementing cut, copy and paste using one of the Swing components that is not one of the text components you have to do some additional setup. First, you need to install the cut, copy, and paste actions in the action map. The following method shows how to do this:
    private void setMappings(JList list) {
        ActionMap map = list.getActionMap();
        map.put(TransferHandler.getCutAction().getValue(Action.NAME),
                TransferHandler.getCutAction());
        map.put(TransferHandler.getCopyAction().getValue(Action.NAME),
                TransferHandler.getCopyAction());
        map.put(TransferHandler.getPasteAction().getValue(Action.NAME),
                TransferHandler.getPasteAction());

When you set up the Edit menu, you can also choose to add menu accelerators, so that the user can type Control-C to initiate a copy, for example. In the following code snippet, the bolded text shows how to set the menu accelerator for the cut action:

    menuItem = new JMenuItem("Cut");
    menuItem.setActionCommand((String)TransferHandler.getCutAction().
             getValue(Action.NAME));
    menuItem.addActionListener(actionListener);
    menuItem.setAccelerator(
      KeyStroke.getKeyStroke(KeyEvent.VK_X, ActionEvent.CTRL_MASK));
    menuItem.setMnemonic(KeyEvent.VK_T);
    mainMenu.add(menuItem);

If you have set the menu accelerators for the CCP actions, this next step is redundant. If you have not set the menu accelerators, you need to add the CCP bindings to the input map. The following code snippet shows how this is done:

    // only required if you have not set the menu accelerators
    InputMap imap = this.getInputMap();
    imap.put(KeyStroke.getKeyStroke("ctrl X"),
        TransferHandler.getCutAction().getValue(Action.NAME));
    imap.put(KeyStroke.getKeyStroke("ctrl C"),
        TransferHandler.getCopyAction().getValue(Action.NAME));
    imap.put(KeyStroke.getKeyStroke("ctrl V"),
        TransferHandler.getPasteAction().getValue(Action.NAME));

Once the bindings have been installed and the Edit menu has been set up, there is another issue to be addressed: When the user initiates a cut, copy or a paste, which component should receive the action? In the case of a text component, the DefaultEditorKit remembers which component last had the focus and forwards the action to that component. The following class, TransferActionListener, performs the same function for non-text Swing components. This class can be dropped into most any application:

public class TransferActionListener implements ActionListener,
                                              PropertyChangeListener {
    private JComponent focusOwner = null;

    public TransferActionListener() {
        KeyboardFocusManager manager = KeyboardFocusManager.
           getCurrentKeyboardFocusManager();
        manager.addPropertyChangeListener("permanentFocusOwner", this);
    }

    public void propertyChange(PropertyChangeEvent e) {
        Object o = e.getNewValue();
        if (o instanceof JComponent) {
            focusOwner = (JComponent)o;
        } else {
            focusOwner = null;
        }
    }

    public void actionPerformed(ActionEvent e) {
        if (focusOwner == null)
            return;
        String action = (String)e.getActionCommand();
        Action a = focusOwner.getActionMap().get(action);
        if (a != null) {
            a.actionPerformed(new ActionEvent(focusOwner,
                                              ActionEvent.ACTION_PERFORMED,
                                              null));
        }
    }
}

Finally, you have to decide how to handle the paste. In the case of a drag and drop, you insert the data at the drop location. In the case of a paste, you do not have the benefit of the user pointing to the desired paste location. You need to decide what makes sense for your application — inserting the data before or after the current selection might be the best solution.

The following demo, ListCutPaste, shows how to implement CCP in an instance of JList. As you can see in the screen shot there are three lists and you can cut, copy, and paste to or from any of these lists. They also support drag and drop. For this demo, the pasted data is inserted after the current selection. If there is no current selection, the data is appended to the end of the list.

A snapshot of the ListCutPaste demo.

Try this:
  1. Click the Launch button to run ListCutPaste using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the ListCutPaste example

  2. Select an item in one of the lists. Use the Edit menu or the keyboard equivalent to cut or copy the list item from the source.
  3. Select the list item where you want the item to be pasted.
  4. Paste the text using the menu or the keyboard equivalent. The item is pasted after the current selection.
  5. Perform the same operation using drag and drop.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: CCP in a Text Component
Next page: Using and Creating a DataFlavor


Using and Creating a DataFlavor (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Using and Creating a DataFlavor
The DataFlavor class allows you to specify the content type of your data. You need to specify a DataFlavor when fetching the data from the importData method. Several flavor types are predefined for you:
  • imageFlavor represents data in the java.awt.Image format. This is used when dragging image data.
  • stringFlavor represents data in the most basic form of text — java.lang.String. This is the most commonly used data flavor for most applications.
  • javaFileListFlavor represents java.io.File objects in a java.util.List format. This is useful for applications that drag files, such as the TopLevelTransferHandler example, discussed in the Top-Level Drop lesson.

For most applications, this is all you need to know about data flavors. However, if you require a flavor other than these predefined types, you can create your own. If you create a custom component and want it to participate in data transfer, you will need to create a custom data flavor. The constructor for specifying a data flavor is DataFlavor(Class, String). For example, to create a data flavor for the java.util.ArrayList class:

new DataFlavor(ArrayList.class, "ArrayList");
To create a data flavor for an integer array:
new DataFlavor(int[].class, "Integer Array");

Transferring the data using this mechanism uses Object serialization, so the class you use to transfer the data must implement the Serializable interface, as must anything that is serialized with it. If everything is not serializable, you will see a NotSerializableException during drop or copy to the clipboard.

Creating a data flavor using the DataFlavor(Class, String) constructor allows you to transfer data between applications, including native applications. If you want to create a data flavor that transfers data only within an application, use javaJVMLocalObjectMimeType and the DataFlavor(String) constructor. For example, to specify a data flavor that transfers color from a JColorChooser only within your application, you could use this code:

String colorType = DataFlavor.javaJVMLocalObjectMimeType +
                   ";class=java.awt.Color";
DataFlavor colorFlavor = new DataFlavor(colorType);

To create a data flavor for an ArrayList that would work only within your application:

new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType +
               ";class=java.util.ArrayList");

To create a data flavor for an integer array:

new DataFlavor(DataFlavor.javaJVMLocalObjectMimeType +
               ";class=\"" + int[].class.getName() + "\"");

A MIME type containing special characters, such as [ or ;, must have those characters enclosed in quotes.

A Transferable can be implemented to support multiple flavors. For example, you can use both local and serialization flavors together, or you can use two forms of the same data, such as the ArrayList and integer array flavors, together, or you can create a TransferHandler that accepts different types of data, such as color and text.

When you create an array of DataFlavors to be returned from the Transferable's getTransferDataFlavors method, the flavors should be inserted in preferred order, with the most preferred appearing at element 0 of the array. Genereally the preferred order is from the richest, or most complex, form of the data down to the simpleset — the form most likely to be understood by other objects.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: CCP in a non-Text Component
Next page: Putting it All Together - DnD and CCP


Putting it All Together - DnD and CCP (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Putting it All Together - DnD and CCP
We have shown how to implement drag and drop support and how to implement cut, copy, paste support. How do you combine both in one component?

You implement both within the TransferHandler's importData method, like this:

if (transferSupport.isDrop()) {
    // put data in transferSupport.getDropLocation()
} else {
    // determine where you want the paste to go (ex: after current selection)
    // put data there
}

The ListCutPaste example, discussed on the CCP in a non-Text Component page, supports both dnd and ccp. Here is its importData method (the if-else drop logic is bolded):

    public boolean importData(TransferHandler.TransferSupport info) {
        String data = null;

        //If we cannot handle the import, bail now.
        if (!canImport(info)) {
            return false;
        }

        JList list = (JList)info.getComponent();
        DefaultListModel model = (DefaultListModel)list.getModel();
        //Fetch the data -- bail if this fails
        try {
            data = (String)info.getTransferable().getTransferData(DataFlavor.stringFlavor);
        } catch (UnsupportedFlavorException ufe) {
            System.out.println("importData: unsupported data flavor");
            return false;
        } catch (IOException ioe) {
            System.out.println("importData: I/O exception");
            return false;
        }

        if (info.isDrop()) { //This is a drop
            JList.DropLocation dl = (JList.DropLocation)info.getDropLocation();
            int index = dl.getIndex();
            if (dl.isInsert()) {
                model.add(index, data);
                return true;
            } else {
                model.set(index, data);
                return true;
            }
        } else { //This is a paste
            int index = list.getSelectedIndex();
            // if there is a valid selection,
            // insert data after the selection
            if (index >= 0) {
                model.add(list.getSelectedIndex()+1, data);
            // else append to the end of the list
            } else {
                model.addElement(data);
            }
            return true;
        }
    }

This is the only place where you need to install if-else logic to distinguish between dnd and ccp.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using and Creating a DataFlavor
Next page: Further Information


Further Information (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Further Information
One of the best places to get the latest information on data transfer is Shannon Hickey's blog. Shannon is the Swing team lead and he "owns" the Swing portion of drag and drop (among other things) and he wrote several of the demos used in this lesson. The following blog entries were written during the JDK 6 development process, so some of the method names and other details have changed, but it is an interesting peek into the process.

Here are some specific entries you may want to study:

  • First Class Drag and Drop Support in JDK 6
  • Location-Sensitive Drag and Drop
  • Top-Level Drop
  • Choosing the Drop Action and Other Changes to Drag and Drop
  • Enable Dropping into Empty JTables
  • Improved Drag Gesture
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Putting it All Together - DnD and CCP
Next page: Solving Common Data Transfer Problems


Solving Common Data Transfer Problems (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Solving Common Data Transfer Problems
This section discusses problems that you might encounter when using data transfer.

Problem: My drag gesture recognizer is not working properly with table/list/tree/text.

Do not use your own drag gesture recognizers with these components. Use setDragEnabled(true) and a TransferHandler.

Problem: I am unable to drop data onto my empty JTable.

You need to call seFillsViewportHeight(true) on the table. See Empty Table Drop for more information.

I need more common problems...

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Further Information
Next page: Writing Event Listeners


Lesson: Writing Event Listeners (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Lesson: Writing Event Listeners
Examples Index

This lesson gives you details about writing event listeners. You might not need to read this section. Your first source of information for event should be the how-to section for the component in question. You can find the appropriate section using the A Visual Guide to Swing Components (Java Look and Feel). Each component's section shows code for handling the events most commonly needed when implementing the component. For example, How to Use Check Boxes shows you how to handle mouse clicks on check boxes using an item listener.

Some Simple Event-Handling Examples

The programs in this section illustrate events and event handling.

General Information about Writing Event Listeners

This section provides information that is useful for handling all types of events. One of the topics includes information on using adapters and inner classes to implement event handlers.

Listeners Supported by Swing Components

This is the place to find out which Swing components can fire which kinds of events. You might want to bookmark this section so you can easily find its quick-reference table.

Implementing Listeners for Commonly Handled Events

This section has detailed information and examples of writing each common kind of event listener.

Listener API Table

This section features a quick-reference table that shows each listener, its adapter class (if any), and its methods.

Solving Common Event-Handling Problems

If you are having some hard-to-debug problems related to handling events, you might find the solution here.

Questions and Exercises

Try these questions and exercises to test what you have learned in this lesson.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Introduction to Event Listeners


Introduction to Event Listeners (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
Introduction to Event Listeners
If you have read any of the component how-to pages, you probably already know the basics of event listeners.

Let us look at one of the simplest event handling examples possible. It is called Beeper, and it features a button that beeps when you click it.

Click the Launch button to run Beeper using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the Beeper example

A Click Me Beeper Button

You can find the entire program in Beeper.java. Here is the code that implements the event handling for the button:
public class Beeper ... implements ActionListener {
    ...
    //where initialization occurs:
        button.addActionListener(this);
    ...
    public void actionPerformed(ActionEvent e) {
        ...//Make a beep sound...
    }
}
The Beeper class implements the ActionListener interface, which contains one method: actionPerformed. Since Beeper implements ActionListener, a Beeper object can register as a listener for the action events that buttons fire. Once the Beeper has been registered using the Button addActionListener method, the Beeper's actionPerformed method is called every time the button is clicked.

A More Complex Example

The event model, which you saw at its simplest in the preceding example, is quite powerful and flexible. Any number of event listener objects can listen for all kinds of events from any number of event source objects. For example, a program might create one listener per event source. Or a program might have a single listener for all events from all sources. A program can even have more than one listener for a single kind of event from a single event source.

Event source with multiple listeners

Multiple listeners can register to be notified of events of a particular type from a particular source. Also, the same listener can listen to notifications from different objects.

Each event is represented by an object that gives information about the event and identifies the event source. Event sources are often components or models, but other kinds of objects can also be event sources.

Whenever you want to detect events from a particular component, first check the how-to section for that component. A list of the component how-to sections is here. The how-to sections give examples of handling the events that you are most likely to care about. In How to Use Color Choosers, for instance, you will find an example of writing a change listener to track when the color changes in the color chooser.

The following example demonstrates that event listeners can be registered on multiple objects and that the same event can be sent to multiple listeners. The example contains two event sources (JButton instances) and two event listeners. One of the event listeners (an instance of a class called MultiListener) listens for events from both buttons. When it receives an event, it adds the event's "action command" (which is set to the text on the button's label) to the top text area. The second event listener (an instance of a class called Eavesdropper) listens for events on only one of the buttons. When it receives an event, it adds the action command to the bottom text area.

MultiListener and Eavesdropper responses to buttons

Try this:
  1. Click the Launch button to run MultiListener using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.
    Launches the MultiListener example
  2. Click the Blah blah blah button. Only the MultiListener object is registered to listen to this button.
  3. Click the You do not say! button. Both the MultiListener object and the Eavesdropper object are registered to listen to this button.
You can find the entire program in MultiListener.java. Here is the code that implements the event handling for the button:
public class MultiListener ... implements ActionListener {
    ...
    //where initialization occurs:
        button1.addActionListener(this);
        button2.addActionListener(this);

        button2.addActionListener(new Eavesdropper(bottomTextArea));
    }

    public void actionPerformed(ActionEvent e) {
        topTextArea.append(e.getActionCommand() + newline);
    }
}

class Eavesdropper implements ActionListener {
    ...
    public void actionPerformed(ActionEvent e) {
        myTextArea.append(e.getActionCommand() + newline);
    }
}
In the above code, both MultiListener and Eavesdropper implement the ActionListener interface and register as action listeners using the JButton addActionListener method. Both classes' implementations of the actionPerformed method are similar: they simply add the event's action command to a text area.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Writing Event Listeners
Next page: General Information about Writing Event Listeners


General Information about Writing Event Listeners (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
General Information about Writing Event Listeners
This section discusses several design considerations to keep in mind when implementing event handlers in your application. We then introduce you to event objects — small objects that describe each event. In particular, we talk about EventObject, the superclass for all AWT and Swing events. Next, we introduce the concepts of low-level events and semantic events, recommending that you prefer semantic events when possible. The remainder of this section discusses implementation techniques you might use in some event listeners or see in event listeners created by other people or by GUI builders.
  • Design Considerations
  • Getting Event Information: Event Objects
  • Concepts: Low-Level Events and Semantic Events
  • Event Adapters
  • Inner Classes and Anonymous Inner Classes
  • The EventHandler Class

Design Considerations
The most important rule to keep in mind about event listeners is that they should execute very quickly. Because all drawing and event-listening methods are executed in the same thread, a slow event-listener method can make the program seem unresponsive and slow to repaint itself. If you need to perform some lengthy operation as the result of an event, do it by starting up another thread (or somehow sending a request to another thread) to perform the operation. For help on using threads, see Concurrency in Swing.

You have many choices on how to implement an event listener. We can not recommend a specific approach because one solution would not suit all situations. However, we can give you some hints and show you some techniques that you might see, even if you do not use the same solution in your program.

For example, you might choose to implement separate classes for different kinds of event listeners. This can be an easy architecture to maintain, but many classes can also mean reduced performance.

When designing your program, you might want to implement your event listeners in a class that is not public, but somewhere more hidden. A private implementation is a more secure implementation.

If you have a very specific kind of simple event listener, you might be able to avoid creating a class at all by using the EventHandler class.

Getting Event Information: Event Objects
Every event-listener method has a single argument — an object that inherits from the EventObject class. Although the argument always descends from EventObject, its type is generally specified more precisely. For example, the argument for methods that handle mouse events is an instance of MouseEvent, where MouseEvent is an indirect subclass of EventObject.

The EventObject class defines one very useful method:

Object getSource()
Returns the object that fired the event.

Note that the getSource method returns an Object. Event classes sometimes define methods similar to getSource, but that have more restricted return types. For example, the ComponentEvent class defines a getComponent method that — just like getSource — returns the object that fired the event. The difference is that getComponent always returns a Component. Each how-to page for event listeners mentions whether you should use getSource or another method to get the event source.

Often, an event class defines methods that return information about the event. For example, you can query a MouseEvent object for information about where the event occurred, how many clicks the user made, which modifier keys were pressed, and so on.

Concepts: Low-Level Events and Semantic Events
Events can be divided into two groups: low-level events and semantic events. Low-level events represent window-system occurrences or low-level input. Everything else is a semantic event.

Examples of low-level events include mouse and key events — both of which result directly from user input. Examples of semantic events include action and item events. A semantic event might be triggered by user input; for example, a button customarily fires an action event when the user clicks it, and a text field fires an action event when the user presses Enter. However, some semantic events are not triggered by low-level events, at all. For example, a table-model event might be fired when a table model receives new data from a database.

Whenever possible, you should listen for semantic events rather than low-level events. That way, you can make your code as robust and portable as possible. For example, listening for action events on buttons, rather than mouse events, means that the button will react appropriately when the user tries to activate the button using a keyboard alternative or a look-and-feel-specific gesture. When dealing with a compound component such as a combo box, it is imperative that you stick to semantic events, since you have no reliable way of registering listeners on all the look-and-feel-specific components that might be used to form the compound component.

Event Adapters

Some listener interfaces contain more than one method. For example, the MouseListener interface contains five methods: mousePressed, mouseReleased, mouseEntered, mouseExited, and mouseClicked. Even if you care only about mouse clicks, if your class directly implements MouseListener, then you must implement all five MouseListener methods. Methods for those events you do not care about can have empty bodies. Here is an example:
//An example that implements a listener interface directly.
public class MyClass implements MouseListener {
    ...
    someObject.addMouseListener(this);
    ...
    /* Empty method definition. */
    public void mousePressed(MouseEvent e) {
    }

    /* Empty method definition. */
    public void mouseReleased(MouseEvent e) {
    }

    /* Empty method definition. */
    public void mouseEntered(MouseEvent e) {
    }

    /* Empty method definition. */
    public void mouseExited(MouseEvent e) {
    }

    public void mouseClicked(MouseEvent e) {
    ...//Event listener implementation goes here...
    }
}
The resulting collection of empty method bodies can make code harder to read and maintain. To help you avoid implementing empty method bodies, the API generally includes an adapter class for each listener interface with more than one method. (The Listener API Table lists all the listeners and their adapters.) For example, the MouseAdapter class implements the MouseListener interface. An adapter class implements empty versions of all its interface's methods.

To use an adapter, you create a subclass of it and override only the methods of interest, rather than directly implementing all methods of the listener interface. Here is an example of modifying the preceding code to extend MouseAdapter. By extending MouseAdapter, it inherits empty definitions of all five of the methods that MouseListener contains.

/*
 * An example of extending an adapter class instead of
 * directly implementing a listener interface.
 */
public class MyClass extends MouseAdapter {
    ...
    someObject.addMouseListener(this);
    ...
    public void mouseClicked(MouseEvent e) {
    ...//Event listener implementation goes here...
    }
}

Inner Classes and Anonymous Inner Classes

What if you want to use an adapter class, but do not want your public class to inherit from an adapter class? For example, suppose you write an applet, and you want your Applet subclass to contain some code to handle mouse events. Since the Java language does not permit multiple inheritance, your class cannot extend both the Applet and MouseAdapter classes. A solution is to define an inner class — a class inside of your Applet subclass — that extends the MouseAdapter class.

Inner classes can also be useful for event listeners that implement one or more interfaces directly.

//An example of using an inner class.
public class MyClass extends Applet {
    ...
    someObject.addMouseListener(new MyAdapter());
    ...
    class MyAdapter extends MouseAdapter {
        public void mouseClicked(MouseEvent e) {
        ...//Event listener implementation goes here...
        }
    }
}
Performance note: When considering whether to use an inner class, keep in mind that application startup time and memory footprint are typically directly proportional to the number of classes you load. The more classes you create, the longer your program takes to start up and the more memory it will take. As an application developer you have to balance this with other design constraints you may have. We are not suggesting you turn your application into a single monolithic class in hopes of cutting down startup time and memory footprint — this would lead to unnecessary headaches and maintenance burdens.

You can create an inner class without specifying a name — this is known as an anonymous inner class. While it might look strange at first glance, anonymous inner classes can make your code easier to read because the class is defined where it is referenced. However, you need to weigh the convenience against possible performance implications of increasing the number of classes.

Here is an example of using an anonymous inner class:

//An example of using an anonymous inner class.
public class MyClass extends Applet {
    ...
    someObject.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {
            ...//Event listener implementation goes here...
            }
    });
    ...
    }
}

Note: One drawback of anonymous inner classes is that they can not be seen by the long-term persistence mechanism. For more information see the API documentation for the JavaBeansTM package and the Bean Persistence lesson in the JavaBeans trail.

Inner classes work even if your event listener needs access to private instance variables from the enclosing class. As long as you do not declare an inner class to be static, an inner class can refer to instance variables and methods just as if its code is in the containing class. To make a local variable available to an inner class, just save a copy of the variable as a final local variable.

To refer to the enclosing instance, you can use EnclosingClass.this. For more information about inner classes, see Nested Classes.

The EventHandler Class

An EventHandler class supports dynamic generation of simple, one-statement event listeners. Although EventHandler is only useful for a certain type of extremely simple event listeners, it is worth mentioning for two reasons. It is useful for:
  • Making an event listener that persistence can see and yet does not clog up your own classes with event listener interfaces and methods.
  • Not adding to the number of classes defined in an application — this can help performance.

Creating an EventHandler by hand is difficult. An EventHandler must be carefully constructed. If you make a mistake, you would not be notified at compile time — it will throw an obscure exception at runtime. For this reason, EventHandlers are best created by a GUI builder. EventHandlers should be carefully documented. Otherwise you run the risk of producing hard-to-read code.

The EventHandler class is intended to be used by interactive tools, such as application builders, that allow developers to make connections between beans. Typically connections are made from a user interface bean (the event source) to an application logic bean (the target). The most effective connections of this kind isolate the application logic from the user interface. For example, the EventHandler for a connection from a JCheckBox to a method that accepts a boolean value can deal with extracting the state of the check box and passing it directly to the method so that the method is isolated from the user interface layer.

Inner classes are another, more general way to handle events from user interfaces. The EventHandler class handles only a subset of what is possible using inner classes. However, EventHandler works better with the long-term persistence scheme than inner classes. Also, using EventHandler in large applications in which the same interface is implemented many times can reduce the disk and memory footprint of the application.

Examples of Using EventHandler The simplest use of EventHandler is to install a listener that calls a method on the target object with no arguments. In the following example we create an ActionListener that invokes the toFront method on an instance of javax.swing.JFrame.

    myButton.addActionListener(
        (ActionListener)EventHandler.create(ActionListener.class, frame, "toFront"));

When myButton is pressed, the statement frame.toFront() will be executed. One could get the same effect, with some additional compile-time type safety, by defining a new implementation of the ActionListener interface and adding an instance of it to the button:

    //Equivalent code using an inner class instead of EventHandler.
    myButton.addActionListener(new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            frame.toFront();
        }
    });

The next simplest use of EventHandler is to extract a property value from the first argument of the method in the listener interface (typically an event object) and use it to set the value of a property in the target object. In the following example we create an ActionListener that sets the nextFocusableComponent property of the target (myButton) object to the value of the "source" property of the event.

    EventHandler.create(ActionListener.class, myButton, "nextFocusableComponent", "source")

This would correspond to the following inner class implementation:

    //Equivalent code using an inner class instead of EventHandler.
    new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            myButton.setNextFocusableComponent((Component)e.getSource());
        }
    }

It is also possible to create an EventHandler that just passes the incoming event object to the target's action. If the fourth EventHandler.create argument is an empty string, then the event is just passed along:

    EventHandler.create(ActionListener.class, target, "doActionEvent", "")

This would correspond to the following inner class implementation:

    //Equivalent code using an inner class instead of EventHandler.
    new ActionListener() {
        public void actionPerformed(ActionEvent e) {
            target.doActionEvent(e);
        }
    }

Probably the most common use of EventHandler is to extract a property value from the source of the event object and set this value as the value of a property of the target object. In the following example we create an ActionListener that sets the "label" property of the target object to the value of the "text" property of the source (the value of the "source" property) of the event.

    EventHandler.create(ActionListener.class, myButton, "label", "source.text")

This would correspond to the following inner class implementation:

    //Equivalent code using an inner class instead of EventHandler.
    new ActionListener {
        public void actionPerformed(ActionEvent e) {
            myButton.setLabel(((JTextField)e.getSource()).getText());
        }
    }
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Introduction to Event Listeners
Next page: Listeners Supported by Swing Components


Listeners Supported by Swing Components (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
Listeners Supported by Swing Components
You can tell what kinds of events a component can fire by looking at the kinds of event listeners you can register on it. For example, the JComboBox class defines these listener registration methods:
  • addActionListener
  • addItemListener
  • addPopupMenuListener
Thus, a combo box supports action, item, and popup menu listeners in addition to the listener methods it inherits from JComponent.

Listeners supported by Swing components fall into two categories:

  • Listeners that All Swing Components Support
  • Other Listeners that Swing Components Support

Listeners that All Swing Components Support
Because all Swing components descend from the AWT Component class, you can register the following listeners on any Swing component:
component listener
Listens for changes in the component's size, position, or visibility.
focus listener
Listens for whether the component gained or lost the keyboard focus.
key listener
Listens for key presses; key events are fired only by the component that has the current keyboard focus.
mouse listener
Listens for mouse clicks, mouse presses, mouse releases and mouse movement into or out of the component's drawing area.
mouse-motion listener
Listens for changes in the mouse cursor's position over the component.
mouse-wheel listener
Listens for mouse wheel movement over the component.
Hierarchy Listener
Listens for changes to a component's containment hierarchy of changed events.
Hierarchy Bounds Listener
Listens for changes to a component's containment hierarchy of moved and resized events.

All Swing components descend from the AWT Container class, but many of them are not used as containers. So, technically speaking, any Swing component can fire container events, which notify listeners that a component has been added to or removed from the container. Realistically speaking, however, only containers (such as panels and frames) and compound components (such as combo boxes) typically fire container events.

JComponent provides support for three more listener types. You can register an ancestor listener to be notified when a component's containment ancestors are added to or removed from a container, hidden, made visible, or moved. This listener type is an implementation detail which predated hierarchy listeners.

The other two listener types are part of the Swing components' conformance to the JavaBeansTM specification. Among other things, this means that Swing components support bound and constrained properties and notify listeners of changes to the properties. Property change listeners listen for changes to bound properties and are used by several Swing components, such as formatted text fields, to track changes on a component's bound properties. Also, property change listeners, as well as vetoable change listeners are used by builder tools to listen for changes on constrained properties. For more information refer to the Properties lesson in the JavaBeans trail.

Other Listeners that Swing Components Support
The following table lists Swing components and the specialized listeners they support, not including listeners supported by all Components, Containers, or JComponents. In many cases, the events are fired directly from the component. In other cases, the events are fired from the component's data or selection model. To find out the details for the particular component and listener you are interested in, go first to the component how-to section, and then if necessary to the listener how-to section.

This table lists Swing components with their specialized listeners
Component Listener
action caret change document,
undoable edit 		item list
selection 		window other
button

checked

checked

checked

check box

checked

checked

checked

color chooser

checked

combo box

checked

checked

dialog

checked

editor pane

checked

checked

hyperlink
file chooser

checked

formatted text field

checked

checked

checked

frame

checked

internal frame internal frame
list

checked

list data
menu menu
menu item

checked

checked

checked

menu key
menu drag mouse
option pane
password field

checked

checked

checked

popup menu popup menu
progress bar

checked

radio button

checked

checked

checked

slider

checked

spinner

checked

tabbed pane

checked

table

checked

table model
table column model
cell editor
text area

checked

checked

text field

checked

checked

checked

text pane

checked

checked

hyperlink
toggle button

checked

checked

checked

tree tree expansion
tree will expand
tree model
tree selection
viewport
(used by scrollpane)

checked

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: General Information about Writing Event Listeners
Next page: Implementing Listeners for Commonly Handled Events


Implementing Listeners for Commonly Handled Events (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
Implementing Listeners for Commonly Handled Events
The following sections give details about implementing specific kinds of event listeners. We do not have a how-to section for every single kind of event listener that you can write. Rather, we cover the listeners we think you are most likely to need. If you are interested in other listeners, you can find some information in the Listener API Table.

  • How to Write an Action Listener
  • How to Write a Caret Listener
  • How to Write a Change Listener
  • How to Write a Component Listener
  • How to Write a Container Listener
  • How to Write a Document Listener
  • How to Write a Focus Listener
  • How to Write an Internal Frame Listener
  • How to Write an Item Listener
  • How to Write a Key Listener
  • How to Write a List Data Listener
  • How to Write a List Selection Listener
  • How to Write a Mouse Listener
  • How to Write a Mouse-Motion Listener
  • How to Write a Mouse-Wheel Listener
  • How to Write a Property Change Listener
  • How to Write a Table Model Listener
  • How to Write a Tree Expansion Listener
  • How to Write a Tree Model Listener
  • How to Write a Tree Selection Listener
  • How to Write a Tree-Will-Expand Listener
  • How to Write an Undoable Edit Listener
  • How to Write Window Listeners
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Listeners Supported by Swing Components
Next page: How to Write an Action Listener


How to Write an Action Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write an Action Listener
Action listeners are probably the easiest — and most common — event handlers to implement. You implement an action listener to define what should be done when an user performs certain operation.

An action event occurs, whenever an action is performed by the user. Examples: When the user clicks a button, chooses a menu item, presses Enter in a text field. The result is that an actionPerformed message is sent to all action listeners that are registered on the relevant component.

To write an Action Listener, follow the steps given below:

  1. Declare an event handler class and specify that the class either implements an ActionListener interface or extends a class that implements an ActionListener interface. For example:
              public class MyClass implements ActionListener {
  2. Register an instance of the event handler class as a listener on one or more components. For example:
              someComponent.addActionListener(instanceOfMyClass);
  3. Include code that implements the methods in listener interface. For example:
              public void actionPerformed(ActionEvent e) {
              ...//code that reacts to the action...
          }

In general, to detect when the user clicks an onscreen button (or does the keyboard equivalent), a program must have an object that implements the ActionListener interface. The program must register this object as an action listener on the button (the event source), using the addActionListener method. When the user clicks the onscreen button, the button fires an action event. This results in the invocation of the action listener's actionPerformed method (the only method in the ActionListener interface). The single argument to the method is an ActionEvent object that gives information about the event and its source.

Let us write a simple program which displays how many number of times a button is clicked by the user. First, here is the code that sets up the TextField , button and numClicks variable:

public class AL extends Frame implements WindowListener,ActionListener {
TextField text = new TextField(20);
Button b;
private int numClicks = 0;

In the above example, the event handler class is AL which implements ActionListener.

We would like to handle the button-click event, so we add an action listener to the button b as below:

b = new Button("Click me");
b.addActionListener(this);

In the above code, Button b is a component upon which an instance of event handler class AL is registered.

Now, we want to display the text as to how many number of times a user clicked button. We can do this by writing the code as below:

public void actionPerformed(ActionEvent e) {
     numClicks++;
     text.setText("Button Clicked " + numClicks + " times");
Now, when the user clicks the Button b, the button fires an action event which invokes the action listener's actionPerformed method. Each time the user presses the button, numClicks variable is appended and the message is displayed in the text field.

Here is the complete program(AL.java):

import java.awt.*;
import java.awt.event.*;

public class AL extends Frame implements WindowListener,ActionListener {
    TextField text = new TextField(20);
    Button b;
    private int numClicks = 0;

    public static void main(String[] args) {
        AL myWindow = new AL("My first window");
        myWindow.setSize(350,100);
        myWindow.setVisible(true);
    }

    public AL(String title) {

        super(title);
        setLayout(new FlowLayout());
        addWindowListener(this);
        b = new Button("Click me");
        add(b);
        add(text);
        b.addActionListener(this);
    }

    public void actionPerformed(ActionEvent e) {
        numClicks++;
        text.setText("Button Clicked " + numClicks + " times");
    }

    public void windowClosing(WindowEvent e) {
        dispose();
        System.exit(0);
    }

    public void windowOpened(WindowEvent e) {}
    public void windowActivated(WindowEvent e) {}
    public void windowIconified(WindowEvent e) {}
    public void windowDeiconified(WindowEvent e) {}
    public void windowDeactivated(WindowEvent e) {}
    public void windowClosed(WindowEvent e) {}

}
More Examples: Beeper program example is available in this trail's introduction to events, Introduction to Event Listeners. You can find the entire program in Beeper.java. The other example described in that section, MultiListener.java, has two action sources and two action listeners, with one listener listening to both sources and the other listening to just one.

The Action Listener API

The ActionListener Interface

Because ActionListener has only one method, it has no corresponding adapter class.
Method | Purpose
actionPerformed(actionEvent) | Called just after the user performs an action.

The ActionEvent Class

Method | Purpose
String getActionCommand() | Returns the string associated with this action. Most objects that can fire action events support a method called setActionCommand that lets you set this string.
int getModifiers() Returns an integer representing the modifier keys the user was pressing when the action event occurred. You can use the ActionEvent-defined constants SHIFT_MASK, CTRL_MASK, META_MASK, and ALT_MASK to determine which keys were pressed. For example, if the user Shift-selects a menu item, then the following expression is nonzero:
actionEvent.getModifiers() & ActionEvent.SHIFT_MASK
Object getSource()
(in java.util.EventObject) 		Returns the object that fired the event.

Examples that Use Action Listeners

The following table lists some of the many examples that use action listeners.

Example | Where Described | Notes
Beeper | This section and Introduction to Event Listeners | Contains one button with one action listener that beeps when you click the button.
MultiListener | Introduction to Event Listeners | Registers two different action listeners on one button. Also registers the same action listener on two different buttons.
RadioButtonDemo | How to Use Radio Buttons | Registers the same action listener on five radio buttons. The listener uses the getActionCommand method to determine which radio button fired the event.
MenuDemo | How to Use Menus | Shows how to listen for action events on menu items.
DragPictureDemo2 | Adding Cut/Copy/Paste Support to Data Transfer | Uses setActionCommand to attach the cut, copy, and paste actions to the menu. Then uses an action listener to forward the cut/copy/paste actions to the currently focused component.
TextDemo | How to Use Icons | Loads an image in an action listener. Because loading an image can take a while, this program uses a SwingWorker to load the image in a background thread.
TableDialogEditDemo | How to Use Tables | Registers an action listener through a factory method on the OK button of a color chooser dialog.
SliderDemo | How to Use Sliders | Registers an action listener on a timer that controls an animation loop.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Implementing Listeners for Commonly Handled Events
Next page: How to Write a Caret Listener


How to Write a Caret Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Caret Listener
Caret events occur when the caret — the cursor indicating the insertion point — in a text component moves or when the selection in a text component changes. The text component's document can initiate caret events when it inserts or removes text, for example. You can attach a caret listener to an instance of any JTextComponent subclass with the addCaretListener method.
Note: An alternate way of detecting caret changes is to attach a listener directly to the caret object itself rather than to the text component that manages the caret. A caret fires change events (not caret events), so you would need to write a change listener rather than a caret listener.

Here is the caret event handling code from an application called TextComponentDemo:

...
//where initialization occurs
CaretListenerLabel caretListenerLabel =
    new CaretListenerLabel("Caret Status");
...
textPane.addCaretListener(caretListenerLabel);
...
protected class CaretListenerLabel extends JLabel
                                   implements CaretListener
{
    ...
    //Might not be invoked from the event dispatching thread.
    public void caretUpdate(CaretEvent e) {
        displaySelectionInfo(e.getDot(), e.getMark());
    }

    //This method can be invoked from any thread.  It
    //invokes the setText and modelToView methods, which
    //must run in the event dispatching thread. We use
    //invokeLater to schedule the code for execution
    //in the event dispatching thread.
    protected void displaySelectionInfo(final int dot,
                                        final int mark) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                if (dot == mark) {  // no selection
                    ...
                }
            });
        }
    }
}
Note: The caretUpdate method is not guaranteed to be called in the event-dispatching thread. To use any methods inside of caretUpdate that update the GUI special handling is required to ensure they are executed on the event-dispatching thread. You can do this by wrapping the code inside a Runnable and calling SwingUtilities.invokeLater on that Runnable.
You can find a link to the source file for TextComponentDemo in the example index for using Swing Components. For a discussion about the caret listener aspect of the program see Listening for Caret and Selection Changes in Text Component Features.

The Caret Listener API

The CaretListener Interface

Because CaretListener has only one method, it has no corresponding adapter class.
Method | Purpose
caretUpdate(CaretEvent) | Called when the caret in the listened-to component moves or when the selection in the listened-to component changes.

The CaretEvent Class

Method | Purpose
int getDot() | Returns the current location of the caret. If text is selected, the caret marks one end of the selection.
int getMark() | Returns the other end of the selection. If nothing is selected, the value returned by this method is equal to the value returned by getDot. Note that the dot is not guaranteed to be less than the mark.
Object getSource()
(in java.util.EventObject) 		Returns the object that fired the event.

Examples that Use Caret Listeners
The following table lists the examples that use caret listeners.

Example | Where Described | Notes
TextComponentDemo | Listening for Caret and Selection Changes | Uses a listener label to display caret and selection status. | Listening for Caret and Selection Changes | Uses a listener label to display caret and selection status. | Listening for Caret and Selection Changes | Uses a listener label to display caret and selection status.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write an Action Listener
Next page: How to Write a Change Listener


How to Write a Change Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Change Listener
A change listener is similar to a property change listener. A change listener is registered on an object — typically a component, but it could be another object, like a model — and the listener is notified when the object has changed. The big difference from a property change listener is that a change listener is not notified of what has changed, but simply that the source object has changed. Therefore, a change listener is most useful when it is only necessary to know when an object has changed in any way.

Several Swing components (including JTabbedPane, JViewPort) rely on change events for basic functionality — sliders, color choosers and spinners. To learn when the value in a slider changes, you need to register a change listener. Similarly, you need to register a change listener on a color chooser to be informed when the user chooses a new color. You register a change listener on a spinner, a component introduced in release 1.4, to be notified when the spinner's value changes.

Here is an example of change event handling code for a slider:

//...where initialization occurs:
framesPerSecond.addChangeListener(new SliderListener());
...
class SliderListener implements ChangeListener {
    public void stateChanged(ChangeEvent e) {
        JSlider source = (JSlider)e.getSource();
        if (!source.getValueIsAdjusting()) {
            int fps = (int)source.getValue();
        ...
        }
    }
}
You can find the source file for SliderDemo in the example index for Using Swing Components.

The Change Listener API

The ChangeListener Interface

Because ChangeListener has only one method, it has no corresponding adapter class.
Method | Purpose
stateChanged(ChangeEvent) | Called when the listened-to component changes state.

The ChangeEvent Class

Method Purpose
Object getSource()
(in java.util.EventObject) 		Returns the object that fired the event.

Examples that Use Change Listeners
The following table lists the examples that use change listeners.

Example | Where Described | Notes
SliderDemo and
SliderDemo2 		How to Use Sliders Registers a change listener on a slider that controls animation speed. The change listener ignores the change events until the user releases the slider.
ColorChooserDemo and
ColorChooserDemo2 		How to Use Color Choosers Uses a change listener on the selection model of a color chooser to learn when the user changes the current color.
SpinnerDemo3 | Detecting Spinner Value Changes in How to Use Spinners. | Uses a change listener on a date-field spinner to change the color of the text as the spinner's date changes.
SpinnerDemo4 | Detecting Spinner Value Changes in How to Use Spinners. | Uses a change listener on a spinner to cycle through the gray scale as the spinner's value changes.
ConverterRangeModel
and its subclass,
FollowerRangeModel 		How to Use Models Implement custom models for the sliders used in the Converter demo. Both models explicitly fire change events when necessary.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Caret Listener
Next page: How to Write a Component Listener


How to Write a Component Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Component Listener
The Component listener is a listener interface for receiving component events. A component is an object having a graphical representation that can be displayed on the screen and that can interact with the user. Some of the examples of components are the buttons, checkboxes, and scrollbars of a typical graphical user interface.

The class that is interested in processing a component event either implements this interface and all the methods it contains, or extends the abstract ComponentAdapter class overriding only the methods of interest. The listener object created from that class is then registered with a component using the component's addComponentListener method. When the component's size, location, or visibility changes, the relevant method in the listener object is invoked, and the ComponentEvent is passed to it.

One or more component events are fired by a Component object just after the component is hidden, made visible, moved, or resized.

The component-hidden and component-shown events occur only as the result of calls to a Component 's setVisible method. For example, a window might be miniaturized into an icon (iconified) without a component-hidden event being fired.

To write a simple Component listener program, follow the steps mentioned below:

  • Declare a class which implements Component listener. For example:
    public class ComponentEventDemo ... implements ComponentListener
  • Identify the components that you would like to catch the events for. For example: pane, label, checkbox, etc.
  • Add the Component Listener to the identified components. For example:
    ....
label.addComponentListener(this);
.....
checkbox.addComponentListener(this);
....
panel.addComponentListener(this);
...
frame.addComponentListener(this);
  • Finally, catch the different events of these components by using four methods of Component Listener as shown below:
    public void componentHidden(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " --- Hidden");
    }

    public void componentMoved(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " --- Moved");
    }

    public void componentResized(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " --- Resized ");
    }

    public void componentShown(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " --- Shown");

    }

    • The following example demonstrates component events. The window contains a panel that has a label and a check box. The check box controls whether the label is visible. A text area displays a message every time the window, panel, label, or check box fires a component event.

    A window demonstrating component events

    Try this:
    1. Click the Launch button to run ComponentEventDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.
      Launches the ComponentEventDemo example

    2. When the window appears, one or more component-shown events have been fired.
    3. Click the check box to hide the label.
      The label fires a component-hidden event. The panel fires component-moved and component-resized events. The check box fires a component-moved event.
    4. Click the check box again to show the label.
      The label fires a component-shown event. The panel fires component-moved and component-resized events. The check box fires a component-moved event.
    5. Iconify and then deiconify the window.
      You do not get component-hidden or -shown events. If you want to be notified of iconification events, you should use a window listener or a window state listener.
    6. Resize the window.
      You will see component-resized (and possibly component-moved) events from all four components — label, check box, panel, and frame. If the frame and panel's layout manager did not make every component as wide as possible, the panel, label, and check box would not have been resized.

    You can find the demo's code in ComponentEventDemo.java. Here is just the code related to handling component events:

    public class ComponentEventDemo ... implements ComponentListener {
    static JFrame frame;
    JLabel label;
    ...
    public ComponentEventDemo() {
        ...
        JPanel panel = new JPanel(new BorderLayout());
        label = new JLabel("This is a label", JLabel.CENTER);
        label.addComponentListener(this);
        panel.add(label, BorderLayout.CENTER);

        JCheckBox checkbox = new JCheckBox("Label visible", true);
        checkbox.addComponentListener(this);
        panel.add(checkbox, BorderLayout.PAGE_END);
        panel.addComponentListener(this);
        ...
        frame.addComponentListener(this);
    }
    ...
     public void componentHidden(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " --- Hidden");
    }

    public void componentMoved(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " --- Moved");
    }

    public void componentResized(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " --- Resized ");
    }

    public void componentShown(ComponentEvent e) {
        displayMessage(e.getComponent().getClass().getName() + " --- Shown");

    }

    public static void main(String[] args) {
        ...
        //Create and set up the window.
        frame = new JFrame("ComponentEventDemo");
        ...
        JComponent newContentPane = new ComponentEventDemo();
        frame.setContentPane(newContentPane);
        ...
    }
}

The Component Listener API

The ComponentListener Interface

All of these methods are also in the adapter class, ComponentAdapter.
Method | Purpose
componentHidden(ComponentEvent) | Called after the listened-to component is hidden as the result of the setVisible method being called.
componentMoved(ComponentEvent) | Called after the listened-to component moves, relative to its container. For example, if a window is moved, the window fires a component-moved event, but the components it contains do not.
componentResized(ComponentEvent) | Called after the listened-to component's size (rectangular bounds) changes.
componentShown(ComponentEvent) | Called after the listened-to component becomes visible as the result of the setVisible method being called.

The ComponentEvent Class

Method | Purpose
Component getComponent() | Returns the component that fired the event. You can use this instead of the getSource method.

Examples that Use Component Listeners
The following table lists the examples that use component listeners.

Example | Where Described | Notes
ComponentEventDemo | This section | Reports all component events that occur on several components to demonstrate the circumstances under which component events are fired.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Change Listener
Next page: How to Write a Container Listener


How to Write a Container Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Container Listener
Container events are fired by a Container just after a component is added to or removed from the container. These events are for notification only — no container listener need be present for components to be successfully added or removed.

The following example demonstrates container events. By clicking Add a button or Remove a button, you can add buttons to or remove them from a panel at the bottom of the window. Each time a button is added to or removed from the panel, the panel fires a container event, and the panel's container listener is notified. The listener displays descriptive messages in the text area at the top of the window.

A screenshot which demonstrates container events

Try this:
  1. Click the Launch button to run ContainerEventDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.
    Launches the ContainerEventDemo example
  2. Click the button labeled Add a button.
    You will see a button appear near the bottom of the window. The container listener reacts to the resulting component-added event by displaying "JButton #1 was added to javax.swing.JPanel" at the top of the window.
  3. Click the button labeled Remove a button.
    This removes the most recently added button from the panel, causing the container listener to receive a component-removed event.

You can find the demo's code in ContainerEventDemo.java. Here is the demo's container event handling code:

public class ContainerEventDemo ... implements ContainerListener ... {
    ...//where initialization occurs:
    buttonPanel = new JPanel(new GridLayout(1,1));
    buttonPanel.addContainerListener(this);
    ...
    public void componentAdded(ContainerEvent e) {
    displayMessage(" added to ", e);
    }

    public void componentRemoved(ContainerEvent e) {
    displayMessage(" removed from ", e);
    }

    void displayMessage(String action, ContainerEvent e) {
    display.append(((JButton)e.getChild()).getText()
               + " was"
               + action
               + e.getContainer().getClass().getName()
               + newline);
    }
    ...
}

The Container Listener API

The ContainerListener Interface

The corresponding adapter class is ContainerAdapter.
Method | Purpose
componentAdded(ContainerEvent) | Called just after a component is added to the listened-to container.
componentRemoved(ContainerEvent) | Called just after a component is removed from the listened-to container.

The ContainerEvent Class

Method | Purpose
Component getChild() | Returns the component whose addition or removal triggered this event.
Container getContainer() | Returns the container that fired this event. You can use this instead of the getSource method.

Examples that Use Container Listeners
The following table lists the examples that use container listeners.

Example | Where Described | Notes
ContainerEventDemo | This section | Reports all container events that occur on a single panel to demonstrate the circumstances under which container events are fired.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Component Listener
Next page: How to Write a Document Listener


How to Write a Document Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Document Listener
A Swing text component uses a Document to represent its content. Document events occur when the content of a document changes in any way. You attach a document listener to a text component's document, rather than to the text component itself. See Implementing a Document Filterfor more information.

The following example demonstrates document events on two plain text components.

This screenshot demonstrates the output of DocumentEventDemo example.

Try this:
  1. Click the Launch button to run DocumentEventDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.
    Launches the DocumentEventDemo example
  2. Type in the text field at the upper left of the window or the text area beneath the text field.
    One document event is fired for each character typed.
  3. Delete text with the backspace key.
    One document event is fired for each backspace key typed.
  4. Select text and then delete it by typing backspace or by using a keyboard command such as CTRL-X (cut).
    One document event is fired for the entire deletion.
  5. Copy text from one text component into the other using keyboard commands such as CTRL-C (copy) and CTRL-V (paste).
    One document event is fired for the entire paste operation regardless of the length of the text pasted. If text is selected in the target text component before the paste command is issued, an additional document event is fired because the selected text is deleted first.

You can find the demo's code in DocumentEventDemo.java. Here is the demo's document event handling code:

public class DocumentEventDemo ... {
    ...//where initialization occurs:
    textField = new JTextField(20);
    textField.addActionListener(new MyTextActionListener());
    textField.getDocument().addDocumentListener(new MyDocumentListener());
    textField.getDocument().putProperty("name", "Text Field");

    textArea = new JTextArea();
    textArea.getDocument().addDocumentListener(new MyDocumentListener());
    textArea.getDocument().putProperty("name", "Text Area");
    ...

class MyDocumentListener implements DocumentListener {
    String newline = "\n";

    public void insertUpdate(DocumentEvent e) {
        updateLog(e, "inserted into");
    }
    public void removeUpdate(DocumentEvent e) {
        updateLog(e, "removed from");
    }
    public void changedUpdate(DocumentEvent e) {
        //Plain text components do not fire these events
    }

    public void updateLog(DocumentEvent e, String action) {
        Document doc = (Document)e.getDocument();
        int changeLength = e.getLength();
        displayArea.append(
            changeLength + " character" +
            ((changeLength == 1) ? " " : "s ") +
            action + doc.getProperty("name") + "." + newline +
            "  Text length = " + doc.getLength() + newline);
    }
}
Document listeners should not modify the contents of the document; The change is already complete by the time the listener is notified of the change. Instead, write a custom document that overrides the insertString or remove methods, or both. See Listening for Changes on a Document for details.

The Document Listener API

The DocumentListener Interface

DocumentListener has no adapter class.
Method | Purpose
changedUpdate(DocumentEvent) | Called when the style of some of the text in the listened-to document changes. This sort of event is fired only from a StyledDocument — a PlainDocument does not fire these events.
insertUpdate(DocumentEvent) | Called when text is inserted into the listened-to document.
removeUpdate(DocumentEvent) | Called when text is removed from the listened-to document.

The DocumentEvent Interface

Each document event method is passed an object that implements the DocumentEvent interface. Typically, this is an instance of DefaultDocumentEvent, defined in AbstractDocument.
Method | Purpose
Document getDocument() | Returns the document that fired the event. Note that the DocumentEvent interface does not inherit from EventObject. Therefore, it does not inherit the getSource method.
int getLength() | Returns the length of the change.
int getOffset() | Returns the location within the document of the first character changed.
ElementChange getChange(Element) | Returns details about what elements in the document have changed and how. ElementChange is an interface defined within the DocumentEvent interface.
EventType getType() | Returns the type of change that occurred. EventType is a class defined within the DocumentEvent interface that enumerates the possible changes that can occur on a document: insert text, remove text, and change text style.

Examples that Use Document Listeners
The following table lists the examples that use document listeners.

Example | Where Described | Notes
DocumentEventDemo | This section | Reports all document events that occur on the documents for both a text field and a text area. One listener listens to both text components and uses a client property on the document to determine which component fired the event.
TextComponentDemo | Listening for Changes on a Document | Updates a change log every time text in the listened-to document changes. The document in this example supports styled text, so changedUpdate gets called in this example. Requires this additional source file: DocumentSizeFilter

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Container Listener
Next page: How to Write a Focus Listener


How to Write a Focus Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Focus Listener
Focus events are fired whenever a component gains or loses the keyboard focus. This is true whether the change in focus occurs through the mouse, the keyboard, or programmatically. To get familiar with basic focus concepts or to obtain detailed information about focus, see How to Use the Focus Subsystem.

This section explains how to get focus events for a particular component by registering a FocusListener instance on it. To get focus for a window only, implement a WindowFocusListener instance instead. To obtain the focus status of many components, consider implementing a PropertyChangeListener instance on the KeyboardFocusManager class, as described in Tracking Focus Changes to Multiple Components in How to Use the Focus Subsystem.

The following example demonstrates focus events. The window displays a variety of components. A focus listener, registered on each component, reports every focus-gained and focus-lost event. For each event, the other component involved in the focus change, the opposite component, is reported. For example, when the focus goes from a button to a text field, a focus-lost event is fired by the button (with the text field as the opposite component) and then a focus-gained event is fired by the text field (with the button as the opposite component). Focus-lost as well as focus-gained events can be temporary. For example, a temporary focus-lost event occurs when the window loses the focus. A temporary focus-gained event occurs on popup menus.

The Focus Event Window, which demonstrates the events that are fired when the keyboard focus changes.

Try this:
  1. Click the Launch button to run FocusEventDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the FocusEventDemo application
  2. You will see a "Focus gained: JTextField" message in the text area — its "opposite component" is null, since it is the first component to have the focus.
  3. Click the label. Nothing happens because the label, by default, cannot get the focus.
  4. Click the combo box. A focus-lost event is fired by the text field and a focus-gained event by the combo box. The combo box now shows that it has the focus, perhaps with a dotted line around the text — exactly how this is represented is look and feel dependent.
    Notice that when the focus changes from one component to another, the first component fires a focus-lost event before the second component fires a focus-gained event.
  5. Select a choice from the combo box's menu. Click the combo box again. Notice that no focus event is reported. As long as the user manipulates the same component, the focus stays on that component.
  6. Click the text area where the focus events are printed. Nothing happens because the text area has been rendered unclickable with setRequestFocusEnabled(false).
  7. Click the text field to return the focus to the initial component.
  8. Press Tab on the keyboard. The focus moves to the combo box and skips over the label.
  9. Press Tab again. The focus moves to the button.
  10. Click another window so that the FocusEventDemo window loses the focus. A temporary focus-lost event is generated for the button.
  11. Click the top of the FocusEventDemo window. A focus-gained event is fired by the button.
  12. Press Tab on the keyboard. The focus moves to the list.
  13. Press Tab again. The focus moves to the text area.
    Notice that even though you are not allowed to click on the text area, you can tab to it. This is so users who use assistive technologies can determine that a component is there and what it contains. The demo disables click-to-focus for the text area, while retaining its tab-to-focus capability, by invoking setRequestFocusEnabled(false) on the text area. The demo could use setFocusable(false) to truly remove the text area from the focus cycle, but that would have the unfortunate effect of making the component unavailable to those who use assistive technologies.
  14. Press Tab again. The focus moves from the list back to the text field. You have just completed a focus cycle. See the introduction in How to Use the Focus Subsystem for a discussion of focus terminology and concepts.

The complete code for this demo is in the FocusEventDemo.java file. The following code snippet represents the focus-event handling mechanism:

public class FocusEventDemo ... implements FocusListener ... {
    public FocusEventDemo() {
        ...
        JTextField textField = new JTextField("A TextField");
        textField.addFocusListener(this);
        ...
    JLabel label = new JLabel("A Label");
    label.addFocusListener(this);
        ...
        JComboBox comboBox = new JComboBox(vector);
        comboBox.addFocusListener(this);
        ...
        JButton button = new JButton("A Button");
        button.addFocusListener(this);
        ...
        JList list = new JList(listVector);
        list.setSelectedIndex(1); //It's easier to see the focus change
                                  //if an item is selected.
        list.addFocusListener(this);
        JScrollPane listScrollPane = new JScrollPane(list);

        ...

        //Set up the area that reports focus-gained and focus-lost events.
        display = new JTextArea();
        display.setEditable(false);
        //The method setRequestFocusEnabled prevents a
        //component from being clickable, but it can still
        //get the focus through the keyboard - this ensures
        //user accessibility.
        display.setRequestFocusEnabled(false);
        display.addFocusListener(this);
        JScrollPane displayScrollPane = new JScrollPane(display);

        ...
    }
    ...
    public void focusGained(FocusEvent e) {
    displayMessage("Focus gained", e);
    }

    public void focusLost(FocusEvent e) {
    displayMessage("Focus lost", e);
    }

    void displayMessage(String prefix, FocusEvent e) {
    display.append(prefix
                       + (e.isTemporary() ? " (temporary):" : ":")
                       +  e.getComponent().getClass().getName()
                       + "; Opposite component: "
                       + (e.getOppositeComponent != null ?
                          e.getOppositeComponent().getClass().getName() : "null")
               + newline);
    }
    ...
}

The Focus Listener API

The FocusListener Interface

The corresponding adapter class is FocusAdapter.
Method | Purpose
focusGained(FocusEvent) | Called just after the listened-to component gets the focus.
focusLost(FocusEvent) | Called just after the listened-to component loses the focus.

The FocusEvent API

Method | Purpose
boolean isTemporary() | Returns the true value if a focus-lost or focus-gained event is temporary.
Component getComponent()
(in java.awt.event.ComponentEvent) 		Returns the component that fired the focus event.
Component getOppositeComponent() | Returns the other component involved in the focus change. For a FOCUS_GAINED event, this is the component that lost the focus. For a FOCUS_LOST event, this is the component that gained the focus. If the focus change involves a native application, a Java application in a different VM or context, or no other component, then null is returned.

Examples that Use Focus Listeners
The following table lists the examples that use focus listeners.

Example | Where Described | Notes
FocusEventDemo | This section | Reports all focus events that occur on several components to demonstrate the circumstances under which focus events are fired.
TrackFocusDemo | How to Use the Focus Subsystem | The custom component, Picture, implements a focus listener to draw a red border around the component when it is the current focus owner.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Document Listener
Next page: How to Write an Internal Frame Listener


How to Write an Internal Frame Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write an Internal Frame Listener
An InternalFrameListener is similar to a WindowListener. Like the window listener, the internal frame listener listens for events that occur when the "window" has been shown for the first time, disposed of, iconified, deiconified, activated, or deactivated. Before using an internal frame listener, please familiarize yourself with the WindowListener interface in How to Write Window Listeners.

The application shown in the following figure demonstrates internal frame events. The application listens for internal frame events from the Event Generator frame, displaying a message that describes each event.

A window which demonstrates internal frame events that are fired by Event Generator frame

Try this:
  1. Click the Launch button to run InternalFrameEventDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.
    Launches the InternalFrameEventDemo example
  2. Bring up the Event Generator internal frame by clicking the Show internal frame button.
    You should see an "Internal frame opened" message in the display area.
  3. Try various operations to see what happens. For example, click the Event Generator so that it gets activated. Click the Event Watcher so that the Event Generator gets deactivated. Click the Event Generator's decorations to iconify, maximize, minimize, and close the window.
    See How to Write Window Listeners for information on what kinds of events you will see.
Here is the internal frame event handling code:
public class InternalFrameEventDemo ...
             implements InternalFrameListener ... {
    ...

    public void internalFrameClosing(InternalFrameEvent e) {
    displayMessage("Internal frame closing", e);
    }

    public void internalFrameClosed(InternalFrameEvent e) {
    displayMessage("Internal frame closed", e);
    listenedToWindow = null;
    }

    public void internalFrameOpened(InternalFrameEvent e) {
    displayMessage("Internal frame opened", e);
    }

    public void internalFrameIconified(InternalFrameEvent e) {
    displayMessage("Internal frame iconified", e);
    }

    public void internalFrameDeiconified(InternalFrameEvent e) {
    displayMessage("Internal frame deiconified", e);
    }

    public void internalFrameActivated(InternalFrameEvent e) {
    displayMessage("Internal frame activated", e);
    }

    public void internalFrameDeactivated(InternalFrameEvent e) {
    displayMessage("Internal frame deactivated", e);
    }

    void displayMessage(String prefix, InternalFrameEvent e) {
    String s = prefix + ": " + e.getSource();
    display.append(s + newline);
    }

    public void actionPerformed(ActionEvent e) {
    if (SHOW.equals(e.getActionCommand())) {
        ...
        if (listenedToWindow == null) {
            listenedToWindow = new JInternalFrame("Event Generator",
                                  true,  //resizable
                                  true,  //closable
                                  true,  //maximizable
                                  true); //iconifiable
                //We want to reuse the internal frame, so we need to
                //make it hide (instead of being disposed of, which is
                //the default) when the user closes it.
            listenedToWindow.setDefaultCloseOperation(
                        WindowConstants.HIDE_ON_CLOSE);

            listenedToWindow.addInternalFrameListener(this);
            ...
        }
    }
    ...
    }
}

The Internal Frame Listener API

The InternalFrameListener Interface

The corresponding adapter class is InternalFrameAdapter.
Method | Purpose
internalFrameOpened(InternalFrameEvent) | Called just after the listened-to internal frame has been shown for the first time.
internalFrameClosing(InternalFrameEvent) | Called in response to a user request that the listened-to internal frame be closed. By default, JInternalFrame hides the window when the user closes it. You can use the JInternalFrame setDefaultCloseOperation method to specify another option, which must be either DISPOSE_ON_CLOSE or DO_NOTHING_ON_CLOSE (both defined in WindowConstants, an interface that JInternalFrame implements). Or by implementing an internalFrameClosing method in the internal frame's listener, you can add custom behavior (such as bringing up dialogs or saving data) to internal frame closing.
internalFrameClosed(InternalFrameEvent) | Called just after the listened-to internal frame has been disposed of.
internalFrameIconified(InternalFrameEvent)
internalFrameDeiconified(InternalFrameEvent) 		Called just after the listened-to internal frame is iconified or deiconified, respectively.
internalFrameActivated(InternalFrameEvent)
internalFrameDeactivated(InternalFrameEvent) 		Called just after the listened-to internal frame is activated or deactivated, respectively.

Each internal frame event method has a single parameter: an InternalFrameEvent object. The InternalFrameEvent class defines no generally useful methods. To get the internal frame that fired the event, use the getSource method, which InternalFrameEvent inherits from java.util.EventObject.

Examples that Use Internal Frame Listeners
No other source files currently contain internal frame listeners. However, internal frame listeners are very similar to WindowListeners and several Swing programs have window listeners:

Example | Where Described | Notes
InternalFrameEventDemo | This section | Reports all internal frame events that occur on one internal frame to demonstrate the circumstances under which internal frame events are fired.
DialogDemo | Text Component Features | CustomDialog.java uses setDefaultCloseOperation instead of a window listener to determine what action to take when the user closes the window.
SliderDemo | How to Use Sliders | Listens for window iconify and deiconify events, so that it can stop the animation when the window is not visible.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Focus Listener
Next page: How to Write an Item Listener


How to Write an Item Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write an Item Listener
Item events are fired by components that implement the ItemSelectable interface. Generally, ItemSelectable components maintain on/off state for one or more items. The Swing components that fire item events include buttons like check boxes, check menu items, toggle buttons etc...and combo boxes.

Here is some item-event handling code taken from ComponentEventDemo.java:

//where initialization occurs
checkbox.addItemListener(this);
...
public void itemStateChanged(ItemEvent e) {
    if (e.getStateChange() == ItemEvent.SELECTED) {
        label.setVisible(true);
        ...
    } else {
        label.setVisible(false);
    }
}

The Item Listener API

The ItemListener Interface

Because ItemListener has only one method, it has no corresponding adapter class.
Method | Purpose
itemStateChanged(ItemEvent) | Called just after a state change in the listened-to component.

The ItemEvent Class

Method | Purpose
Object getItem() | Returns the component-specific object associated with the item whose state changed. Often this is a String containing the text on the selected item.
ItemSelectable getItemSelectable() | Returns the component that fired the item event. You can use this instead of the getSource method.
int getStateChange() | Returns the new state of the item. The ItemEvent class defines two states: SELECTED and DESELECTED.

Examples that Use Item Listeners
The following table lists some examples that use item listeners.

Example | Where Described | Notes
ComponentEventDemo | This section and How to Write a Component Listener | Listens for item events on a check box, which determines whether a lable is visible.
CheckBoxDemo | How to Use Check Boxes | Four check boxes share one item listener, which uses getItemSelected to determine which check box fired the event.
MenuDemo | How to Use Menus | Listens for item events on a check box menu item.
MenuDemo | How to Use Scroll Panes | Listens for item events on a toggle button.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write an Internal Frame Listener
Next page: How to Write a Key Listener


How to Write a Key Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Key Listener
Key events indicate when the user is typing at the keyboard. Specifically, key events are fired by the component with the keyboard focus when the user presses or releases keyboard keys. For detailed information about focus, see How to Use the Focus Subsystem.
Note: To define special reactions to particular keys, use key bindings instead of a key listener. For further information, see How to Use Key Bindings.

Notifications are sent about two basic kinds of key events:

  • The typing of a Unicode character
  • The pressing or releasing of a key on the keyboard
The first kind of event is called a key-typed event. The second kind is either a key-pressed or key-released event.

In general, you react to only key-typed events unless you need to know when the user presses keys that do not correspond to characters. For example, to know when the user types a Unicode character — whether by pressing one key such as 'a' or by pressing several keys in sequence — you handle key-typed events. On the other hand, to know when the user presses the F1 key, or whether the user pressed the '3' key on the number pad, you handle key-pressed events.

Note: To fire keyboard events, a component must have the keyboard focus.

To make a component get the keyboard focus, follow these steps:

  1. Make sure the component's isFocusable method returns true. This state allows the component to receive the focus. For example, you can enable keyboard focus for a JLabel component by calling the setFocusable(true) method on the label.
  2. Make sure the component requests the focus when appropriate. For custom components, implement a mouse listener that calls the requestFocusInWindow method when the component is clicked.
Version note: This page reflects the focus API introduced in JDK release 1.4. As of that release, the focus subsystem consumes focus traversal keys, such as Tab and Shift Tab. If you need to prevent the focus traversal keys from being consumed, you can call
component.setFocusTraversalKeysEnabled(false)
on the component that is firing the key events. Your program must then handle focus traversal on its own. Alternatively, you can use the KeyEventDispatcher class to pre-listen to all key events. The focus page has detailed information on the focus subsystem.
You can obtain detailed information about a particular key-pressed event. For example, you can query a key-pressed event to determine if it was fired from an action key. Examples of action keys include Copy, Paste, Page Up, Undo, and the arrow and function keys. As of JDK release 1.4, you can also query a key-pressed or key-released event to determine the location of the key that fired the event. Most key events are fired from the standard keyboard, but the events for some keys, such as Shift, have information on whether the user pressed the Shift key on the left or the right side of the keyboard. Likewise, the number '2' can be typed from either the standard keyboard or from the number pad.

For key-typed events you can obtain the key character value as well as any modifiers used.

Note: You should not rely on the key character value returned from getKeyChar unless it is involved in a key-typed event.

The following example demonstrates key events. It consists of a text field that you can type into, followed by a text area that displays a message every time the text field fires a key event. A button at the bottom of the window lets you clear both the text field and text area.

Try this:
  1. Click the Launch button to run KeyEventDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the KeyEventDemo application
  2. Type a lowercase 'a' by pressing and releasing the A key on the keyboard.
    The text field fires three events: a key-pressed event, a key-typed event, and a key-released event. Note that the key-typed event doesn't have key code information, and key-pressed and key-released events don't have key character information. None of the events so far are from modifier or action keys and the key location, reported on the key-pressed and key-released events, is most likely standard.
  3. Press the Clear button.
    You might want to do this after each of the following steps.
  4. Press and release the Shift key.
    The text field fires two events: a key-pressed and a key-released. The text field doesn't fire a key-typed event because Shift, by itself, doesn't correspond to any character.
  5. Type an uppercase 'A' by pressing the Shift and A keys.
    You'll see the following events, although perhaps not in this order: key-pressed (Shift), key-pressed (A), key typed ('A'), key-released (A), key-released (Shift). Note that Shift is listed as the modifier key for the key-typed and key-pressed events.
  6. Type an uppercase 'A' by pressing and releasing the Caps Lock key, and then pressing the A key.
    You should see the following events: key-pressed (Caps Lock), key-pressed (A), key typed ('A'), key-released (A). Note that Caps Lock is not listed as a modifier key.
  7. Press the Tab key. No Tab key-pressed or key-released events are received by the key event listener. This is because the focus subsystem consumes focus traversal keys, such as Tab and Shift Tab. Press Tab twice more to return the focus to the text area.
  8. Press a function key, such as F3. You'll see that the function key is an action key.
  9. Press the left Shift key, followed by the right Shift key. The key-pressed and key-released events indicate which Shift key was typed.
  10. Press the Num Lock key if your keyboard has a number pad.
    As for Caps Lock, there is a key-pressed event, but no key-released event.
  11. Press the '2' key on the number pad. You see the key-pressed, key-typed, and key-released events for the number '2'.
  12. Press the '2' key on the standard keyboard. Again, you see the three event messages. The key-typed events for both number 2 keys are identical. But the key-pressed and key-released events indicate different key codes and different key locations.
  13. Press the Num Lock key again. A key-released event is fired.

You can find the example's code in KeyEventDemo.java. Here is the demo's key event handling code:

public class KeyEventDemo ...  implements KeyListener ... {
    ...//where initialization occurs:
    typingArea = new JTextField(20);
    typingArea.addKeyListener(this);

        //Uncomment this if you wish to turn off focus
        //traversal.  The focus subsystem consumes
        //focus traversal keys, such as Tab and Shift Tab.
        //If you uncomment the following line of code, this
        //disables focus traversal and the Tab events
        //become available to the key event listener.
        //typingArea.setFocusTraversalKeysEnabled(false);
    ...
    /** Handle the key typed event from the text field. */
    public void keyTyped(KeyEvent e) {
    displayInfo(e, "KEY TYPED: ");
    }

    /** Handle the key-pressed event from the text field. */
    public void keyPressed(KeyEvent e) {
    displayInfo(e, "KEY PRESSED: ");
    }

    /** Handle the key-released event from the text field. */
    public void keyReleased(KeyEvent e) {
    displayInfo(e, "KEY RELEASED: ");
    }
    ...
    private void displayInfo(KeyEvent e, String keyStatus){

        //You should only rely on the key char if the event
        //is a key typed event.
        int id = e.getID();
        String keyString;
        if (id == KeyEvent.KEY_TYPED) {
            char c = e.getKeyChar();
            keyString = "key character = '" + c + "'";
        } else {
            int keyCode = e.getKeyCode();
            keyString = "key code = " + keyCode
                    + " ("
                    + KeyEvent.getKeyText(keyCode)
                    + ")";
        }

        int modifiersEx = e.getModifiersEx();
        String modString = "extended modifiers = " + modifiersEx;
        String tmpString = KeyEvent.getModifiersExText(modifiersEx);
        if (tmpString.length() > 0) {
            modString += " (" + tmpString + ")";
        } else {
            modString += " (no extended modifiers)";
        }

        String actionString = "action key? ";
        if (e.isActionKey()) {
            actionString += "YES";
        } else {
            actionString += "NO";
        }

        String locationString = "key location: ";
        int location = e.getKeyLocation();
        if (location == KeyEvent.KEY_LOCATION_STANDARD) {
            locationString += "standard";
        } else if (location == KeyEvent.KEY_LOCATION_LEFT) {
            locationString += "left";
        } else if (location == KeyEvent.KEY_LOCATION_RIGHT) {
            locationString += "right";
        } else if (location == KeyEvent.KEY_LOCATION_NUMPAD) {
            locationString += "numpad";
        } else { // (location == KeyEvent.KEY_LOCATION_UNKNOWN)
            locationString += "unknown";
        }

        ...//Display information about the KeyEvent...
    }
}

The Key Listener API

The KeyListener Interface

The corresponding adapter class is KeyAdapter.
Method | Purpose
keyTyped(KeyEvent) | Called just after the user types a Unicode character into the listened-to component.
keyPressed(KeyEvent) | Called just after the user presses a key while the listened-to component has the focus.
keyReleased(KeyEvent) | Called just after the user releases a key while the listened-to component has the focus.

The KeyEvent Class

The KeyEvent class inherits many useful methods from the InputEvent class, such as getModifiersEx, and a couple of useful methods from the ComponentEvent and AWTEvent classes. See the InputEvent Class table in the mouse listener page for a complete list.
Method | Purpose
int getKeyChar() | Obtains the Unicode character associated with this event. Only rely on this value for key-typed events.
int getKeyCode() | Obtains the key code associated with this event. The key code identifies the particular key on the keyboard that the user pressed or released. The KeyEvent class defines many key code constants for commonly seen keys. For example, VK_A specifies the key labeled A, and VK_ESCAPE specifies the Escape key.
String getKeyText(int)
String getKeyModifiersText(int) 		Return text descriptions of the event's key code and modifier keys, respectively.
int getModifiersEx()
String getModifiersExText(int modifiers) 		Return the extended modifiers mask for this event. There are methods inherited from the InputEvent class. Extended modifiers represent the state of all modal keys. The getModifiersExText method returns a string describing the extended modifier keys and mouse buttons. Since the getModifiersEx and getModifiersExText methods provide more information about key events, they are preferred over the getKeyText or getKeyModifiersText methods.
boolean isActionKey() | Returns true if the key firing the event is an action key. Examples of action keys include Cut, Copy, Paste, Page Up, Caps Lock, the arrow and function keys. This information is valid only for key-pressed and key-released events.
int getKeyLocation() | Returns the location of the key that fired this event. This provides a way to distinguish keys that occur more than once on a keyboard, such as the two shift keys, for example. The possible values are KEY_LOCATION_STANDARD, KEY_LOCATION_LEFT, KEY_LOCATION_RIGHT, KEY_LOCATION_NUMPAD, or KEY_LOCATION_UNKNOWN. This method always returns KEY_LOCATION_UNKNOWN for key-typed events. Introduced in JDK release 1.4.

Examples that Use Key Listeners
The following table lists the examples that use key listeners.

Example | Where Described | Notes
KeyEventDemo | This section | Reports all key events that occur on a text field to demonstrate the circumstances under which key events are fired.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write an Item Listener
Next page: How to Write a List Data Listener


How to Write a List Data Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a List Data Listener
List data events occur when the contents of a mutable list change. Since the model — not the component — fires these events, you have to register a list data listener with the list model. If you have not explicitly created a list with a mutable list model, then your list is immutable, and its model will not fire these events.
Note: Combo box models also fire list data events. However, you normally do not need to know about them unless you are creating a custom combo box model.

The following example demonstrates list data events on a mutable list:

An output of the ListDataEventDemo which demonstrates list data events.

Try this:
  1. Click the Launch button to run ListDataEventDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.
    Launches the ListDataEventDemo example
  2. Type in the name of your favorite ski resort and click the Add button. An intervalAdded event was fired.
  3. Select a few continguous items in the list and click the Delete button. An intervalRemoved event was fired.
  4. Select one item and move it up or down in the list with the arrow buttons. Two contentsChanged events are fired — one for the item that moved and one for the item that was displaced.
You can find the demo's code in ListDataEventDemo.java. Here is the code that registers a list data listener on the list model and implements the listener:
//...where member variables are declared...
private DefaultListModel listModel;
...
//Create and populate the list model
listModel = new DefaultListModel();
...
listModel.addListDataListener(new MyListDataListener());

class MyListDataListener implements ListDataListener {
    public void contentsChanged(ListDataEvent e) {
        log.append("contentsChanged: " + e.getIndex0() +
               ", " + e.getIndex1() + newline);
    }
    public void intervalAdded(ListDataEvent e) {
        log.append("intervalAdded: " + e.getIndex0() +
               ", " + e.getIndex1() + newline);
    }
    public void intervalRemoved(ListDataEvent e) {
        log.append("intervalRemoved: " + e.getIndex0() +
               ", " + e.getIndex1() + newline);
    }
}

The List Data Listener API

The ListDataListener Interface

ListDataListener has no corresponding adapter class.
Method | Purpose
intervalAdded(ListDataEvent) | Called when one or more items have been added to the list.
intervalRemoved(ListDataEvent) | Called when one or more items have been removed from the list.
contentsChanged(ListDataEvent) | Called when the contents of one or more items in the list have changed.

The ListDataEvent API

Method | Purpose
Object getSource()
(in java.util.EventObject) 		Return the object that fired the event.
int getIndex0() | Return the index of the first item whose value has changed.
int getIndex1() | Return the index of the last item whose value has changed.
int getType() | Return the event type. The possible values are: CONTENTS_CHANGED, INTERVAL_ADDED, or INTERVAL_REMOVED.

Examples that Use List Data Listeners
The following table lists the examples that use list data listeners.

Example | Where Described | Notes
ListDataEventDemo | This section | Reports all list data events that occur on a list.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Key Listener
Next page: How to Write a List Selection Listener


How to Write a List Selection Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a List Selection Listener
List selection events occur when the selection in a list or table is either changing or has just changed. List selection events are fired from an object that implements the ListSelectionModel interface. To get a table's list selection model object, you can use either getSelectionModel method or getColumnModel().getSelectionModel().

To detect list selection events, you register a listener on the appropriate list selection model object. The JList class also gives you the option of registering a listener on the list itself, rather than directly on the list selection model.

This section looks at two examples that show how to listen to list selection events on a selection model. Examples that Use List Selection Listeners lists examples that listen on the list directly.

In these two examples, you can dynamically change the selection mode to any of the three supported modes:

  • single selection mode
  • single interval selection mode
  • multiple interval selection mode

Here is a picture of ListSelectionDemo example running in a List :

A snapshot of ListSelectionDemo, which demonstrates selection modes and list selection model.

Try this:
  1. Click the Launch button to run ListSelectionDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.
    Launches the ListSelectionDemo example
  2. Select and deselect items in the list. The mouse and keyboard commands required to select items depends on the look and feel. For the Java look and feel, click the left mouse button to begin a selection, use the shift key to extend a selection contiguously, and use the control key to extend a selection discontiguously. Note that there are two types of selections: Lead and Anchor. Lead is the focused item and Anchor is the highlighted item. When you press ctrl key and move up and down, the lead selection causes the events being fired even though the actual selection has not changed. Dragging the mouse moves or extends the selection, depending on the list selection mode.
Here is a picture of TableListSelectionDemo example running in a Table:

A snapshot of TableListSelectionDemo, which demonstrates selection modes and list selection model.

Try this:
  1. Click the Launch button to run TableListSelectionDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.
    Launches the TableListSelectionDemo example
  2. Select and deselect items in the table. The mouse and keyboard commands required to select items depends on the look and feel. For the Java look and feel, click the left mouse button to begin a selection, use the shift key to extend a selection contiguously, and use the control key to extend a selection discontiguously. Note that there are two types of selections: Lead and Anchor. Lead is the focused item and Anchor is the highlighted item. When you press ctrl key and move up or down, the lead selection causes the events being fired even though the actual selection has not changed. Dragging the mouse moves or extends the selection, depending on the list selection mode.
You can find the entire program of ListSelectionDemo in ListSelectionDemo.java and the entire program of TableListSelectionDemo in TableListSelectionDemo.java.

Here is the code from ListSelectionDemo that sets up the selection model and adds a listener to it:

...//where the member variables are defined
JList list;
    ...//in the init method:
    listSelectionModel = list.getSelectionModel();
    listSelectionModel.addListSelectionListener(
                            new SharedListSelectionHandler());
    ...
And here is the code for the listener, which works for all the possible selection modes:
class SharedListSelectionHandler implements ListSelectionListener {
    public void valueChanged(ListSelectionEvent e) {
        ListSelectionModel lsm = (ListSelectionModel)e.getSource();

        int firstIndex = e.getFirstIndex();
        int lastIndex = e.getLastIndex();
        boolean isAdjusting = e.getValueIsAdjusting();
        output.append("Event for indexes "
                      + firstIndex + " - " + lastIndex
                      + "; isAdjusting is " + isAdjusting
                      + "; selected indexes:");

        if (lsm.isSelectionEmpty()) {
            output.append(" <none>");
        } else {
            // Find out which indexes are selected.
            int minIndex = lsm.getMinSelectionIndex();
            int maxIndex = lsm.getMaxSelectionIndex();
            for (int i = minIndex; i <= maxIndex;="maxIndex;" i++)="i++)" {="{" if="if" (lsm.isSelectedIndex(i))="(lsm.isSelectedIndex(i))" {="{" output.append("="output.append("">
This valueChanged method displays the first and last indices reported by the event, the value of the event's isAdjusting flag, and the indices currently selected.

Note that the first and last indices reported by the event indicate the inclusive range of items for which the selection has changed. If the selection mode is multiple interval selection some items within the range might not have changed. The isAdjusting flag is true if the user is still manipulating the selection, and false if the user has finished changing the selection.

The ListSelectionEvent object passed into valueChanged indicates only that the selection has changed. The event contains no information about the current selection. So, this method queries the selection model to figure out the current selection.

The List Selection Listener API

The ListSelectionListener Interface

Because ListSelectionListener has only one method, it has no corresponding adapter class.
Method | Purpose
valueChanged(ListSelectionEvent) | Called in response to selection changes.

The ListSelectionEvent API

Method | Purpose
Object getSource()
(in java.util.EventObject) 		Return the object that fired the event. If you register a list selection listener on a list directly, then the source for each event is the list. Otherwise, the source is the selection model.
int getFirstIndex() | Return the index of the first item whose selection value has changed. Note that for multiple interval selection, the first and last items are guaranteed to have changed but items between them might not have. However, when you press ctrl key and move up or down, the lead selection causes the events being fired even though the actual selection has not changed.
int getLastIndex() | Return the index of the last item whose selection value has changed. Note that for multiple interval selection, the first and last items are guaranteed to have changed but items between them might not have. However, when you press ctrl key and move up and down, the lead selection causes the events being fired even though the actual selection has not changed.
boolean getValueIsAdjusting() | Return true if the selection is still changing. Many list selection listeners are interested only in the final state of the selection and can ignore list selection events when this method returns true.

Examples that Use List Selection Listeners
The following table lists the examples that use list selection listeners.

Example | Where Described | Notes
ListSelectionDemo | This section | Reports all list selection events that occur on a list. Lets the user dynamically change the selection mode.
TableListSelectionDemo | This section | Reports all list selection events that occur on a table. Lets the user dynamically change the selection mode.
ListDemo | How to Use Lists | Listens to events on a single-selection list (not on its selection model). Enables and disables a button depending on whether any items are selected in the list.
SplitPaneDemo | How to Use Lists | Listens to events on a single-selection list (not on its selection model).
SimpleTableSelectionDemo | How to Use Tables | Uses two different list selection listeners on one table. One listener listens to list selection events on table columns, the other listens to list selection events on table rows.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a List Data Listener
Next page: How to Write a Mouse Listener


How to Write a Mouse Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Mouse Listener
Mouse events notify when the user uses the mouse (or similar input device) to interact with a component. Mouse events occur when the cursor enters or exits a component's onscreen area and when the user presses or releases one of the mouse buttons.

Tracking the cursor's motion involves significantly more system overhead than tracking other mouse events. That is why mouse-motion events are separated into Mouse Motion listener type (see How to Write a Mouse Motion Listener).

To track mouse wheel events, you can register a mouse-wheel listener. See How to Write a Mouse Wheel Listener for more information.

If an application requires the detection of both mouse events and mouse-motion events, use the MouseInputAdapter class. This class implements the MouseInputListener, a convenient interface that implements the MouseListener and MouseMotionListener interfaces. However, the MouseInputListener interface does not implement the MouseWheelListener interface.

Alternatively, use the corresponding AWT MouseAdapter class, which implements the MouseListener, MouseMotionListener, and MouseWheelListener interfaces.

The following example shows a mouse listener. At the top of the window is a blank area (implemented by a class named BlankArea). The mouse listener listens for events both on the BlankArea and on its container, an instance of MouseEventDemo. Each time a mouse event occurs, a descriptive message is displayed under the blank area. By moving the cursor on top of the blank area and occasionally pressing mouse buttons, you can fire mouse events.

Try this:
  1. Click the Launch button to run MouseEventDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the MouseEventDemo application
  2. Move the cursor into the yellow rectangle at the top of the window.
    You will see one or more mouse-entered events.
  3. Press and hold the left mouse button without moving the mouse.
    You will see a mouse-pressed event. You might see some extra mouse events, such as mouse-exited and then mouse-entered.
  4. Release the mouse button.
    You will see a mouse-released event. If you did not move the mouse, a mouse-clicked event will follow.
  5. Press and hold the mouse button again, and then drag the mouse so that the cursor ends up outside the window. Release the mouse button.
    You will see a mouse-pressed event, followed by a mouse-exited event, followed by a mouse-released event. You are not notified of the cursor's motion. To get mouse-motion events, you need to implement a mouse-motion listener.
You can find the demo's code in MouseEventDemo.java and BlankArea.java. Here is the demo's mouse event handling code:
public class MouseEventDemo ... implements MouseListener {
    //where initialization occurs:
        //Register for mouse events on blankArea and the panel.
        blankArea.addMouseListener(this);
        addMouseListener(this);
    ...

    public void mousePressed(MouseEvent e) {
       saySomething("Mouse pressed; # of clicks: "
                    + e.getClickCount(), e);
    }

    public void mouseReleased(MouseEvent e) {
       saySomething("Mouse released; # of clicks: "
                    + e.getClickCount(), e);
    }

    public void mouseEntered(MouseEvent e) {
       saySomething("Mouse entered", e);
    }

    public void mouseExited(MouseEvent e) {
       saySomething("Mouse exited", e);
    }

    public void mouseClicked(MouseEvent e) {
       saySomething("Mouse clicked (# of clicks: "
                    + e.getClickCount() + ")", e);
    }

    void saySomething(String eventDescription, MouseEvent e) {
        textArea.append(eventDescription + " detected on "
                        + e.getComponent().getClass().getName()
                        + "." + newline);
    }
}

The Mouse Listener API

The MouseListener Interface

Method | Purpose
mouseClicked(MouseEvent) | Called just after the user clicks the listened-to component.
mouseEntered(MouseEvent) | Called just after the cursor enters the bounds of the listened-to component.
mouseExited(MouseEvent) | Called just after the cursor exits the bounds of the listened-to component.
mousePressed(MouseEvent) | Called just after the user presses a mouse button while the cursor is over the listened-to component.
mouseReleased(MouseEvent) | Called just after the user releases a mouse button after a mouse press over the listened-to component.

The MouseAdapter class (the AWT adapter class) is abstract. All its methods have an empty body. So a developer can define methods for events specific to the application. You can also use the MouseInputAdapter class, which has all the methods available from MouseListener and MouseMotionListener.

The MouseEvent Class

Method | Purpose
int getClickCount() | Returns the number of quick, consecutive clicks the user has made (including this event). For example, returns 2 for a double click.
int getX()
int getY()
Point getPoint() 		Return the (x,y) position at which the event occurred, relative to the component that fired the event.
int getXOnScreen()
int getYOnScreen()
int getLocationOnScreen() 		Return the absolute (x,y) position of the event. These coordinates are relative to the virtual coordinate system for the multi-screen environment. Otherwise, these coordinates are relative to the coordinate system associated with the Component's Graphics Configuration.
int getButton() | Returns which mouse button, if any, has a changed state. One of the following constants is returned: NOBUTTON, BUTTON1, BUTTON2, or BUTTON3. Introduced in release 1.4.
boolean isPopupTrigger() | Returns true if the mouse event should cause a popup menu to appear. Because popup triggers are platform dependent, if your program uses popup menus, you should call isPopupTrigger for all mouse-pressed and mouse-released events fired by components over which the popup can appear. See Bringing Up a Popup Menu for more information about popup menus.
String getMouseModifiersText(int) | Returns a String describing the modifier keys and mouse buttons that were active during the event, such as "Shift", or "Ctrl+Shift". These strings can be localized using the awt.properties file. Introduced in release 1.4.

The InputEvent Class

The MouseEvent class inherits many useful methods from InputEvent and a couple handy methods from the ComponentEvent and AWTEvent classes.
Method | Purpose
int getID()
(in java.awt.AWTEvent) 		Returns the event type, which defines the particular action. For example, the MouseEvent id reflects the state of the mouse buttons for every mouse event. The following states could be specified by the MouseEvent id: MouseEvent.MOUSE_PRESSED, MouseEvent.MOUSE_RELEASED, and MouseEvent.MOUSE_CLICKED.
Component getComponent()
(in ComponentEvent) 		Returns the component that fired the event. You can use this method instead of the getSource method.
int getWhen() | Returns the timestamp of when this event occurred. The higher the timestamp, the more recently the event occurred.
boolean isAltDown()
boolean isControlDown()
boolean isMetaDown()
boolean isShiftDown()
 Return the state of individual modifier keys at the time the event was fired.
int getModifiers() Returns the state of all the modifier keys and mouse buttons when the event was fired. You can use this method to determine which mouse button was pressed (or released) when a mouse event was fired. The InputEvent class defines these constants for use with the getModifiers method: ALT_MASK, BUTTON1_MASK, BUTTON2_MASK, BUTTON3_MASK, CTRL_MASK, META_MASK, and SHIFT_MASK. For example, the following expression is true if the right button was pressed:
(mouseEvent.getModifiers() & InputEvent.BUTTON3_MASK)
== InputEvent.BUTTON3_MASK
int getModifiersEx() Returns the extended modifier mask for this event. Extended modifiers represent the state of the mouse button and all modal keys, such as ALT, CTRL, META, just after the event occurred. You can check the status of the modifiers using one of the following predefined bitmasks: SHIFT_DOWN_MASK, CTRL_DOWN_MASK, META_DOWN_MASK, ALT_DOWN_MASK, BUTTON1_DOWN_MASK, BUTTON2_DOWN_MASK, BUTTON3_DOWN_MASK, or ALT_GRAPH_DOWN_MASK. For example, to check that button 1 is down, but that buttons 2 and 3 are up, you would use the following code snippet:
if (event.getModifiersEx() & (BUTTON1_DOWN_MASK |
                              BUTTON2_DOWN_MASK |
                              BUTTON3_DOWN_MASK)
                               == BUTTON1_DOWN_MASK) {
    ...
}
Introduced in release 1.4.
int getModifiersExText(int) | Returns a string describing the extended modifier keys and mouse buttons, such as "Shift", "Button1", or "Ctrl+Shift". These strings can be localized by changing the awt.properties file. Introduced in release 1.4.

The MouseInfo Class

The MouseInfo class provides methods to obtain information about the mouse pointer location at any time while an application runs.
Method | Purpose
getPointerInfo() | Returns a PointerInfo instance that represents the current location of the mouse pointer.
getNumberOfButtons() | Returns the number of buttons on the mouse or -1 , if a system does not support a mouse.

Examples That Use Mouse Listeners
The following table lists the examples that use mouse listeners.

Example | Where Described | Notes
MouseEventDemo | This section | Reports all mouse events that occur within a blank panel to demonstrate the circumstances under which mouse events are fired.
GlassPaneDemo | How to Use Root Panes | Uses a subclass of MouseInputAdapter to listen to mouse events and mouse-motion events on the root pane's glass pane. Re-dispatches the events to underlying components.
TableSortDemo | How to Use Tables | Listens to mouse events on a table header. Sorts data in the selected column.
PopupMenuDemo | How to Use Menus | Displays a popup menu in response to mouse clicks.
TrackFocusDemo | How to Use the Focus Subsystem | The custom component, Picture, implements a mouse listener that requests the focus when a user clicks on the component.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a List Selection Listener
Next page: How to Write a Mouse-Motion Listener


How to Write a Mouse-Motion Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Mouse-Motion Listener
Mouse-motion events notify when the user uses the mouse (or a similar input device) to move the onscreen cursor. For information on listening for other kinds of mouse events, such as clicks, see How to Write a Mouse Listener. For information on listening for mouse-wheel events, see How to Write a Mouse Wheel Listener.

If an application requires the detection of both mouse events and mouse-motion events, use the MouseInputAdapter class, which implements the MouseInputListener a convenient interface that implements both the MouseListener and MouseMotionListener interfaces.

Alternatively, use the corresponding MouseAdapter AWT class, which implements the MouseMotionListener interface, to create a MouseMotionEvent and override the methods for the specific events.

The following demo code contains a mouse-motion listener. This demo is exactly the same as the demo described in the How to Write a Mouse Listener section, except for substituting the MouseMotionListener interface for the MouseListener interface. Additionally, MouseMotionEventDemo implements the mouseDragged and mouseMoved methods instead of the mouse listener methods, and displays coordinates instead of numbers of clicks.

Try this:
  1. Click the Launch button to run MouseMotionEventDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the MouseMotionEventDemo application
  2. Move the cursor into the yellow rectangle at the top of the window.
    You will see one or more mouse-moved events.
  3. Press and hold the mouse button, and then move the mouse so that the cursor is outside the yellow rectangle.
    You will see mouse-dragged events.

You can find the demo's code in MouseMotionEventDemo.java and BlankArea.java. The following code snippet from MouseMotionEventDemo implements the mouse-motion event handling:

public class MouseMotionEventDemo extends JPanel
                                  implements MouseMotionListener {
    //...in initialization code:
        //Register for mouse events on blankArea and panel.
        blankArea.addMouseMotionListener(this);
        addMouseMotionListener(this);
        ...
    }

    public void mouseMoved(MouseEvent e) {
       saySomething("Mouse moved", e);
    }

    public void mouseDragged(MouseEvent e) {
       saySomething("Mouse dragged", e);
    }

    void saySomething(String eventDescription, MouseEvent e) {
        textArea.append(eventDescription
                        + " (" + e.getX() + "," + e.getY() + ")"
                        + " detected on "
                        + e.getComponent().getClass().getName()
                        + newline);
    }
}

The SelectionDemo example, draws a rectangle illustrating the user's current dragging. To draw the rectangle, the application must implement an event handler for three kinds of mouse events: mouse presses, mouse drags, and mouse releases. To be informed of all these events, the handler must implement both the MouseListener and MouseMotionListener interfaces, and be registered as both a mouse listener and a mouse-motion listener. To avoid having to define empty methods, the handler doesn't implement either listener interface directly. Instead, it extends MouseInputAdapter, as the following code snippet shows.

...//where initialization occurs:
    MyListener myListener = new MyListener();
    addMouseListener(myListener);
    addMouseMotionListener(myListener);
...
private class MyListener extends MouseInputAdapter {
    public void mousePressed(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        currentRect = new Rectangle(x, y, 0, 0);
        updateDrawableRect(getWidth(), getHeight());
        repaint();
    }

    public void mouseDragged(MouseEvent e) {
        updateSize(e);
    }

    public void mouseReleased(MouseEvent e) {
        updateSize(e);
    }

    void updateSize(MouseEvent e) {
        int x = e.getX();
        int y = e.getY();
        currentRect.setSize(x - currentRect.x,
                            y - currentRect.y);
        updateDrawableRect(getWidth(), getHeight());
        Rectangle totalRepaint = rectToDraw.union(previouseRectDrawn);
        repaint(totalRepaint.x, totalRepaint.y,
                totalRepaint.width, totalRepaint.height);
    }
}

The Mouse-Motion Listener API

The MouseMotionListener Interface

The corresponding adapter classes are MouseMotionAdapter and MouseAdapter.
Method | Purpose
mouseDragged(MouseEvent) | Called in response to the user moving the mouse while holding a mouse button down. This event is fired by the component that fired the most recent mouse-pressed event, even if the cursor is no longer over that component.
mouseMoved(MouseEvent) | Called in response to the user moving the mouse with no mouse buttons pressed. This event is fired by the component that's currently under the cursor.

Each mouse-motion event method has a single parameter — and it's not called MouseMotionEvent! Instead, each mouse-motion event method uses a MouseEvent argument. See The MouseEvent API for information about using MouseEvent objects.

Examples That Use Mouse-Motion Listeners
The following table lists the examples that use mouse-motion listeners.

Example | Where Described | Notes
MouseMotionEventDemo | This section | Reports all mouse motion events that occur within a blank panel to demonstrate the circumstances under which mouse motion events are fired.
LayeredPaneDemo and
LayeredPaneDemo2 		How to Use Layered Panes Moves an image of Duke around within a layered pane in response to mouse motion events.
SelectionDemo   | Lets the user drag a rectangle to select a portion of an image. Uses a subclass of MouseInputAdapter to listen to both mouse events and mouse-motion events.
GlassPaneDemo | How to Use Root Panes | Uses a subclass of MouseInputAdapter to listen to mouse events and mouse-motion events on the root pane's glass pane. Redispatches the events to underlying components.
ScrollDemo | How to Use Scroll Panes | The label subclass, ScrollablePicture, uses a mouse-motion listener to allow the user to scroll the picture even when the user drags the cursor outside the window.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Mouse Listener
Next page: How to Write a Mouse-Wheel Listener


How to Write a Mouse-Wheel Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Mouse-Wheel Listener
Mouse-wheel events notify when the wheel on the mouse rotates. For information on listening to other mouse events, such as clicks, see How to Write a Mouse Listener. For information on listening to mouse-dragged events, see How to Write a Mouse-Motion Listener. Not all mice have wheels and, in that case, mouse-wheel events are never generated. There is no way to programmatically detect whether the mouse is equipped with a mouse wheel.

Alternatively, use the corresponding MouseAdapter AWT class, which implements the MouseWheelListener interface, to create a MouseWheelEvent and override the methods for the specific events.

Usually it is not necessary to implement a mouse-wheel listener because the mouse wheel is used primarily for scrolling. Scroll panes automatically register mouse-wheel listeners that react to the mouse wheel appropriately.

However, to create a custom component to be used inside a scroll pane you may need to customize its scrolling behavior — specifically you might need to set the unit and block increments. For a text area, for example, scrolling one unit means scrolling by one line of text. A block increment typically scrolls an entire "page", or the size of the viewport. For more information, see Implementing a Scrolling-Savvy Client in the How to Use Scroll Panes page.

To generate mouse-wheel events, the cursor must be over the component registered to listen for mouse-wheel events. The type of scrolling that occurs, either WHEEL_UNIT_SCROLL or WHEEL_BLOCK_SCROLL, is platform dependent. The amount that the mouse wheel scrolls is also platform dependent. Both the type and amount of scrolling can be set via the mouse control panel for the platform.

The following example demonstrates mouse-wheel events.

Try this:
  1. Click the Launch button to run MouseWheelEventDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the MouseWheelEventDemo application
  2. Move the cursor over the text area.
  3. Rotate the mouse wheel away from you. You will see one or more mouse-wheel events in the up direction.
  4. Rotate the mouse wheel in the opposite direction. You will see mouse-wheel events in the down direction.
  5. Try changing your mouse wheel's scrolling behavior your system's mouse control panel to see how the output changes. You should not need to restart the demo to see the changes take effect.

The output from MouseWheelEventDemo for a system that uses unit increments for its mouse wheel might look as follows:

javax.swing.JTextArea: Mouse wheel moved UP 1 notch(es)
    Scroll type: WHEEL_UNIT_SCROLL
    Scroll amount: 3 unit increments per notch
    Units to scroll: -3 unit increments
    Vertical unit increment: 16 pixels
The scroll amount, returned by the getScrollAmount method, indicates how many units will be scrolled and always presents a positive number. The units to scroll, returned by the getUnitsToScroll method, are positive when scrolling down and negative when scrolling up. The number of pixels for the vertical unit is obtained from the vertical scroll bar using the getUnitIncrement method. In the preceding example, rolling the mouse wheel one notch upward should result in the text area scrolling upward 48 pixels (3x16).

For a system that uses block increments for mouse-wheel scrolling, for the same movement of the mouse wheel the output might look as follows:

javax.swing.JTextArea: Mouse wheel moved UP 1 notch(es)
    Scroll type: WHEEL_BLOCK_SCROLL
    Vertical block increment: 307 pixels
The vertical block increment is obtained from the vertical scroll bar using the getBlockIncrement method. In this case, rolling the mouse wheel upward one notch means that the text area should scroll upward 307 pixels.

Find the demo's code in the MouseWheelEventDemo.java file. The following code snippet is related to the mouse-wheel event handling:

public class MouseWheelEventDemo ... implements MouseWheelListener ... {
    public MouseWheelEventDemo() {
        //where initialization occurs:
        //Register for mouse-wheel events on the text area.
        textArea.addMouseWheelListener(this);
        ...
    }

    public void mouseWheelMoved(MouseWheelEvent e) {
       String message;
       int notches = e.getWheelRotation();
       if (notches < 0) {
           message = "Mouse wheel moved UP "
                        + -notches + " notch(es)" + newline;
       } else {
           message = "Mouse wheel moved DOWN "
                        + notches + " notch(es)" + newline;
       }
       if (e.getScrollType() == MouseWheelEvent.WHEEL_UNIT_SCROLL) {
           message += "    Scroll type: WHEEL_UNIT_SCROLL" + newline;
           message += "    Scroll amount: " + e.getScrollAmount()
                   + " unit increments per notch" + newline;
           message += "    Units to scroll: " + e.getUnitsToScroll()
                   + " unit increments" + newline;
           message += "    Vertical unit increment: "
               + scrollPane.getVerticalScrollBar().getUnitIncrement(1)
               + " pixels" + newline;
       } else { //scroll type == MouseWheelEvent.WHEEL_BLOCK_SCROLL
           message += "    Scroll type: WHEEL_BLOCK_SCROLL" + newline;
           message += "    Vertical block increment: "
               + scrollPane.getVerticalScrollBar().getBlockIncrement(1)
               + " pixels" + newline;
       }
       saySomething(message, e);
    }
    ...
}

The Mouse Wheel Listener API

The MouseWheelListener Interface

Although MouseWheelListener has only one method, it has the corresponding adapter class — MouseAdapter. This capability enables an application to have only one adapter class instance for the component to manage all types of events from the mouse pointer.
Method | Purpose
mouseWheelMoved(MouseWheelEvent) | Called when the mouse wheel is rotated.

The MouseWheelEvent Class

Method | Purpose
int getScrollType() | Returns the type of scrolling to be used. Possible values are WHEEL_BLOCK_SCROLL and WHEEL_UNIT_SCROLL, and are determined by the native platform.
int getWheelRotation() | Returns the number of notches the mouse wheel was rotated. If the mouse wheel rotated towards the user (down) the value is positive. If the mouse wheel rotated away from the user (up) the value is negative.
int getScrollAmount() | Returns the number of units that should be scrolled per notch. This is always a positive number and is only valid if the scroll type is MouseWheelEvent.WHEEL_UNIT_SCROLL.
int getUnitsToScroll() | Returns the positive or negative units to scroll for the current event. This is only valid when the scroll type is MouseWheelEvent.WHEEL_UNIT_SCROLL.

Examples That Use Mouse Wheel Listeners
The following table lists the examples that use mouse-wheel listeners.

Example | Where Described | Notes
MouseWheelEventDemo | This section | Reports all mouse wheel events that occur within a text area to demonstrate the circumstances under which mouse wheel events are fired.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Mouse-Motion Listener
Next page: How to Write a Property Change Listener


How to Write a Property Change Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Property Change Listener

Property-change events occur whenever the value of a bound property changes for a bean — a component that conforms to the JavaBeansTM specification. You can find out more about beans from the JavaBeans trail of the Java Tutorial. All Swing components are also beans.

A JavaBeans property is accessed through its get and set methods. For example, JComponent has the property font which is accessible through the getFont and setFont methods.

Besides the get and set methods, a bound property fires a property-change event when its value changes. For more information, see the Bound Properties page in the JavaBeans trail.

Some scenarios that commonly require property-change listeners include:

  • You have implemented a formatted text field and need a way to detect when the user has entered a new value. You can register a property-change listener on the formatted text field to listen to changes on the value property. See FormattedTextFieldDemo in How to Use Formatted Text Fields for an example of this.

  • You have implemented a dialog and need to know when a user has clicked one of the dialog's buttons or changed a selection in the dialog. See DialogDemo in How to Make Dialogs for an example of registering a property-change listener on an option pane to listen to changes to the value property. You can also check out FileChooserDemo2 in How to Use File Choosers for an example of how to register a property-change listener to listen to changes to the directoryChanged and selectedFileChanged properties.

  • You need to be notified when the component that has the focus changes. You can register a property-change listener on the keyboard focus manager to listen to changes to the focusOwner property. See TrackFocusDemo and DragPictureDemo in How to Use the Focus Subsystem for examples of this.

Although these are some of the more common uses for property-change listeners, you can register a property-change listener on the bound property of any component that conforms to the JavaBeans specification.

You can register a property change listener in two ways. The first uses the method addPropertyChangeListener(PropertyChangeListener). When you register a listener this way, you are notified of every change to every bound property for that object. In the propertyChange method, you can get the name of the property that has changed using the PropertyChangeEvent getPropertyName method, as in the following code snippet:

KeyboardFocusManager focusManager =
   KeyboardFocusManager.getCurrentKeyboardFocusManager();
focusManager.addPropertyChangeListener(new FocusManagerListener());
...
public FocusManagerListener() implements PropertyChangeListener {
    public void propertyChange(PropertyChangeEvent e) {
        String propertyName = e.getPropertyName();
        if ("focusOwner".equals(propertyName) {
            ...
        } else if ("focusedWindow".equals(propertyName) {
            ...
        }
    }
    ...
}

The second way to register a property change listener uses the method addPropertyChangeListener(String, PropertyChangeListener). The String argument is the name of a property. Using this method means that you only receive notification when a change occurs to that particular property. So, for example, if you registered a property change listener like this:

aComponent.addPropertyChangeListener("font",
                                     new FontListener());

FontListener only receives notification when the value of the component's font property changes. It does not receive notification when the value changes for transferHandler, opaque, border, or any other property.

The following example shows how to register a property change listener on the value property of a formatted text field using the two-argument version of addPropertyChangeListener:

//...where initialization occurs:
double amount;
JFormattedTextField amountField;
...
amountField.addPropertyChangeListener("value",
                                      new FormattedTextFieldListener());
...
class FormattedTextFieldListener implements PropertyChangeListener {
    public void propertyChanged(PropertyChangeEvent e) {
        Object source = e.getSource();
        if (source == amountField) {
            amount = ((Number)amountField.getValue()).doubleValue();
            ...
        }
        ...//re-compute payment and update field...
    }
}

The Property Change Listener API

Registering a PropertyChangeListener

Method | Purpose
addPropertyChangeListener(PropertyChangeListener) | Add a property-change listener to the listener list.
addPropertyChangeListener(String, PropertyChangeListener) | Add a property-change listener for a specific property. The listener is called only when there is a change to the specified property.

The PropertyChangeListener Interface

Because PropertyChangeListener has only one method, it has no corresponding adapter class.
Method | Purpose
propertyChange(PropertyChangeEvent) | Called when the listened-to bean changes a bound property.

The PropertyChangeEvent Class

Method | Purpose
Object getNewValue()
Object getOldValue() 		Return the new, or old, value of the property, respectively.
String getPropertyName() | Return the name of the property that was changed.
void setPropagationId() | Get or set the propagation ID value. Reserved for future use.

Examples that Use Property Change Listeners
The following table lists the examples that use property-change listeners.

Example | Where Described | Notes
FormattedTextFieldDemo | How to Use Formatted Text Fields | A property-change listener is registered on several formatted text fields to track changes to the value property.
DialogDemo | How to Make Dialogs | The CustomDialog class registers a property-change listener on an option pane to listen to the value and inputValue properties.
FileChooserDemo2 | How to Use File Choosers | The ImagePreview class registers a property-change listener on the file chooser to listen to the directoryChanged and selectedFileChanged properties.
TrackFocusDemo | How to Use the Focus Subsystem | A property-change listener is registered on the keyboard focus manager to track changes to the focusOwner property.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Mouse-Wheel Listener
Next page: How to Write a Table Model Listener


How to Write a Table Model Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Table Model Listener

Upon instantiation, each JTable object is passed a table model object that manages the data it displays. By default, a JTable object inherits a DefaultTable object if no custom TableModel object is specified, but by default, this model only manages strings. To handle objects, perform calculations, or to retrieve data from databases or other programs, you must design your own custom TableModel object, which implements the TableModel interface. See Creating a Table Model for details.

To detect changes to the data managed by a table model object, the JTable class needs to implement the TableModelListener interface, call addTableModelListener() to catch events, and then override tableChanged() to respond to listener events. See Listening for Data Changes for details.

The Table Model Listener API

The TableModelListener Interface

Because TableModelListener has only one method, it has no corresponding adapter class.
Method | Purpose
tableChanged(TableModelEvent) | Called when the structure of or data in the table has changed.

The TableModelEvent API

Method | Purpose
Object getSource()
(in java.util.EventObject) 		Return the object that fired the event.
int getFirstRow() | Return the index of the first row that changed. TableModelEvent.HEADER_ROW specifies the table header.
int getLastRow() | The last row that changed. Again, HEADER_ROW is a possible value.
int getColumn() | Return the index of the column that changed. The constant TableModelEvent.ALL_COLUMNS specifies that all the columns might have changed.
int getType() | What happened to the changed cells. The returned value is one of the following: TableModelEvent.INSERT, TableModelEvent.DELETE, or TableModelEvent.UPDATE.

Examples that Use Table Model Listeners
The following table lists the examples that use table model listeners.

Example | Where Described | Notes
TableMap | Sorting and Otherwise Manipulating Data | A superclass for data-manipulating table models. It implements a table model that sits between a table data model and a JTable. The TableMap listens for table model events from the data model, and then simply forwards them to its table model listeners (such as the JTable).
Sorting and Otherwise Manipulating Data | A sorting table model implemented as a subclass of TableMap. In addition to forwarding table model events, the tableChanged method keeps track of the number of rows.
SharedModelDemo — Does not implement a table model listener. Instead, it implements a combined list and table model.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Property Change Listener
Next page: How to Write a Tree Expansion Listener


How to Write a Tree Expansion Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Tree Expansion Listener

Sometimes when using a tree, you might need to react when a branch becomes expanded or collapsed. For example, you might need to load or save data.

Two kinds of listeners report expansion and collapse occurrences: tree expansion listeners and tree-will-expand listeners. This page discusses tree expansion listeners. See How to Write a Tree-Will-Expand Listener for a description of Tree-Will-Expand listeners.

A tree expansion listener detects when an expansion or collapse has already occured. In general, you should implement a tree expansion listener unless you need to prevent an expansion or collapse from ocurring .

This example demonstrates a simple tree expansion listener. The text area at the bottom of the window displays a message every time a tree expansion event occurs. It's a straightforward, simple demo. To see a more interesting version that can veto expansions, see How to Write a Tree-Will-Expand Listener.

Try this:
  1. Click the Launch button to run TreeExpandEventDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TreeExpandEventDemo example
  2. Expand a node. A tree-expanded event is fired.
  3. Collapse the node. A tree-collapsed event is fired.

The following code shows how the program handles expansion events. You can find the source code for this example in TreeExpandEventDemo.java.

public class TreeExpandEventDemo ... {
    ...
    void saySomething(String eventDescription, TreeExpansionEvent e) {
        textArea.append(eventDescription + "; "
                        + "path = " + e.getPath()
                        + newline);
    }

    class DemoArea ... implements TreeExpansionListener {
        ...
        public DemoArea() {
            ...
            tree.addTreeExpansionListener(this);
            ...
        }
        ...
        // Required by TreeExpansionListener interface.
        public void treeExpanded(TreeExpansionEvent e) {
            saySomething("Tree-expanded event detected", e);
        }

        // Required by TreeExpansionListener interface.
        public void treeCollapsed(TreeExpansionEvent e) {
            saySomething("Tree-collapsed event detected", e);
        }
    }
}

The Tree Expansion Listener API

The TreeExpansionListener Interface

TreeExpansionListener has no adapter class.
Method | Purpose
treeCollapsed(TreeExpansionEvent) | Called just after a tree node collapses.
treeExpanded(TreeExpansionEvent) | Called just after a tree node expands.

The TreeExpansionEvent API

Method | Purpose
Object getSource() | Return the object that fired the event.
TreePath getPath() | Returns a TreePath object that identifies each node from the root of the tree to the collapsed/expanded node, inclusive.

Examples that Use Tree Expansion Listeners
The following table lists the examples that use tree expansion listeners.

Example | Where Described | Notes
TreeExpandEventDemo | This section | Displays a message whenever a tree expansion event occurs.
TreeExpandEventDemo2 | How to Write a Tree-Will-Expand Listener | Adds a tree-will-expand listener to TreeExpandEventDemo.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Table Model Listener
Next page: How to Write a Tree Model Listener


How to Write a Tree Model Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Tree Model Listener
By implementing a tree model listener, you can detect when the data displayed by a tree changes. You can use a tree model listener to detect when the user edits tree nodes. All notifications describe changes relative to a node in the tree. For details, read Dynamically Changing a Tree.

The Tree Model Listener API

The TreeModelListener Interface

TreeModelListener has no adapter class.
Method | Purpose
treeNodesChanged(TreeModelEvent) | Called when one or more sibling nodes have changed in some way.
treeNodesInserted(TreeModelEvent) | Called after nodes have been inserted into the tree.
treeNodesRemoved(TreeModelEvent) | Called after nodes have been removed from the tree.
treeStructureChanged(TreeModelEvent) | Called after the tree's structure has drastically changed from the current node on down. This event applies to all nodes connected to this node.

The TreeModelEvent API

Method | Purpose
Object getSource()
(in java.util.EventObject) 		Return the object that fired the event.
int[] getChildIndices() | For treeNodesChanged, treeNodesInserted, and treeNodesRemoved, returns the indices of the changed, inserted, or deleted nodes, respectively. Returns nothing useful for treeStructureChanged.
Object[] getChildren() | Returns the objects corresponding to the child indices.
Object[] getPath() | Returns the path to the parent of the changed, inserted, or deleted nodes. For treeStructureChanged, returns the path to the node beneath which the structure has changed.
TreePath getTreePath() | Returns the same thing as getPath, but as a TreePath object.

Examples that Use Tree Model Listeners
The following table lists the examples that use tree expansion listeners.

Example | Where Described | Notes
DynamicTreeDemo | How to Use Trees | The DynamicTree class implements a tree model listener to detect when the user has edited a node's data.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Tree Expansion Listener
Next page: How to Write a Tree Selection Listener


How to Write a Tree Selection Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Tree Selection Listener
To detect when the user selects a node in a tree, you need to register a tree selection listener. Here is an example, taken from the TreeDemo example discussed in Responding to Node Selection, of detecting node selection in a tree that can have at most one node selected at a time:
tree.addTreeSelectionListener(new TreeSelectionListener() {
    public void valueChanged(TreeSelectionEvent e) {
        DefaultMutableTreeNode node = (DefaultMutableTreeNode)
                           tree.getLastSelectedPathComponent();

    /* if nothing is selected */
        if (node == null) return;

    /* retrieve the node that was selected */
        Object nodeInfo = node.getUserObject();
    ...
    /* React to the node selection. */
    ...
    }
});
To specify that the tree should support single selection, the program uses this code:
tree.getSelectionModel().setSelectionMode
        (TreeSelectionModel.SINGLE_TREE_SELECTION);
The TreeSelectionModel interface defines three values for the selection mode:
DISCONTIGUOUS_TREE_SELECTION
This is the default mode for the default tree selection model. With this mode, any combination of nodes can be selected.
SINGLE_TREE_SELECTION
This is the mode used by the preceding example. At most one node can be selected at a time.
CONTIGUOUS_TREE_SELECTION
With this mode, only nodes in adjoining rows can be selected.

The Tree Selection Listener API

The TreeSelectionListener Interface

Because TreeSelectionListener has only one method, it has no corresponding adapter class.
Method | Purpose
valueChanged(TreeSelectionEvent) | Called whenever the selection changes.

The TreeSelectionEvent API

Method | Purpose
Object getSource()
(in java.util.EventObject) 		Return the object that fired the event.
TreePath getNewLeadSelectionPath() | Return the current lead path.
TreePath getOldLeadSelectionPath() | Return the path that was previously the lead path.
TreePath getPath() | Return the first path element.
TreePath[] getPaths() | Return the paths that have been added or removed from the selection.
boolean isAddedPath() | Return true if the first path element has been added to the selection. Returns false if the first path has been removed from the selection.
boolean isAddedPath(int) | Return true if the path specified by the index was added to the selection.
boolean isAddedPath(TreePath) | Return true if the specified path was added to the selection.
Object getLastSelectedPathComponent() | Return the last path component in the first node of the current selection.
TreePath getLeadSelectionPath()
(in JTree) 		Return the current lead path.

Examples that Use Tree Selection Listeners
The following table lists the examples that use tree selection listeners.

Example Where Described Notes
TreeDemo
How to Use Trees The tree listener responds to node clicks by showing the appropriate HTML document.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Tree Model Listener
Next page: How to Write a Tree-Will-Expand Listener


How to Write a Tree-Will-Expand Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write a Tree-Will-Expand Listener
The tree-will-expand listener prevents a tree node from expanding or collapsing. To be notified just after an expansion or collapse occurs, you should use a tree expansion listener instead.

This demo adds a tree-will-expand listener to the TreeExpandEventDemo example discussed in How to Write a Tree Expansion Listener. The code added here demonstrates that tree-will-expand listeners prevent node expansions and collapses: The listener will prompt you for confirmation each time you try to expand a node.

Try this:
  1. Click the Launch button to run TreeExpandEventDemo2 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

    Launches the TreeExpandEventDemo2 example
  2. Click the graphic to the left of the Potrero Hill node. This tells the tree that you want to expand the node.
    A dialog appears asking you whether you really want to expand the node.
  3. Click "Expand" or dismiss the dialog.
    Messages in the text area tell you that both a tree-will-expand event and a tree-expanded event have occurred. At the end of each message is the path to the expanded node.
  4. Try to expand another node, but this time press the "Cancel Expansion" button in the dialog.
    The node does not expand. Messages in the text area tell you that a tree-will-expand event occurred, and that you cancelled a tree expansion.
  5. Collapse the Potrero Hill node.
    The node collapses without a dialog appearing, because the event handler's treeWillCollapse method lets the collapse occur, uncontested.

The following snippet shows the code that this program adds to TreeExpandEventDemo. The bold line prevents the tree expansion from happening. You can find all the demo's source code in TreeExpandEventDemo2.java.

public class TreeExpandEventDemo2 ... {
    ...
    class DemoArea ... implements ... TreeWillExpandListener {
        ...
        public DemoArea() {
            ...
            tree.addTreeWillExpandListener(this);
            ...
        }
        ...
        //Required by TreeWillExpandListener interface.
        public void treeWillExpand(TreeExpansionEvent e)
                    throws ExpandVetoException {
            saySomething("Tree-will-expand event detected", e);
            //...show a dialog...
            if (/* user said to cancel the expansion */) {
                //Cancel expansion.
                saySomething("Tree expansion cancelled", e);
                throw new ExpandVetoException(e);
            }
        }

        //Required by TreeWillExpandListener interface.
        public void treeWillCollapse(TreeExpansionEvent e) {
            saySomething("Tree-will-collapse event detected", e);
        }
        ...
    }
}

The Tree-Will-Expand Listener API

The TreeWillExpandListener Interface

TreeWillExpandListener has no adapter class.
Method | Purpose
treeWillCollapse(TreeExpansionEvent) | Called just before a tree node collapses. To prevent the collapse from occurring, your implementation of this method should throw a ExpandVetoException event.
treeWillExpand(TreeExpansionEvent) | Called just before a tree node expands. To prevent the expansion from occurring, your implementation of this method should throw a ExpandVetoException event.

See The Tree Expansion Event API for information about the TreeExpansionEvent argument for the preceding methods.

Examples that Use Tree-Will-Expand Listeners
TreeExpandEventDemo2, featured in this section, is our only example that uses a tree-will-expand listener.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Tree Selection Listener
Next page: How to Write an Undoable Edit Listener


How to Write an Undoable Edit Listener (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write an Undoable Edit Listener
Undoable edit events occur when an operation that can be undone occurs on a component. Currently, only text components fire undoable edit events, and then only indirectly. The text component's document fires the events. For text components, undoable operations include inserting characters, deleting characters, and modifying the style of text. Programs typically listen to undoable edit events to assist in the implementation of undo and redo commands.

Here is the undoable edit event handling code from an application called TextComponentDemo.

...
//where initialization occurs
document.addUndoableEditListener(new MyUndoableEditListener());
...
protected class MyUndoableEditListener implements UndoableEditListener {
    public void undoableEditHappened(UndoableEditEvent e) {
        //Remember the edit and update the menus
        undo.addEdit(e.getEdit());
        undoAction.updateUndoState();
        redoAction.updateRedoState();
    }
}
You can find a link to the source file for TextComponentDemo in the example index for Using Swing Components. For a discussion about the undoable edit listener aspect of the program see Implementing Undo and Redo

The Undoable Edit Listener API

The UndoableEditListener Interface

Because UndoableEditListener has only one method, it has no corresponding adapter class.
Method | Purpose
undoableEditHappened(UndoableEditEvent) | Called when an undoable event occurs on the listened-to component.

The UndoableEditEvent Class

Method | Purpose
Object getSource()
(in java.util.EventObject) 		Return the object that fired the event.
UndoableEdit getEdit() | Returns an UndoableEdit object that represents the edit that occurred and contains information about and commands for undoing or redoing the edit.

Examples that Use Undoable Edit Listeners
The following table lists the examples that use undoable edit listeners.

Example | Where Described | Notes
TextComponentDemo | Implementing Undo and Redo | Implements undo and redo on a text pane with help from an undoable edit listener.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write a Tree-Will-Expand Listener
Next page: How to Write Window Listeners


How to Write Window Listeners (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Section: Implementing Listeners for Commonly Handled Events
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
How to Write Window Listeners
This section explains how to implement three kinds of window-related event handlers: WindowListener, WindowFocusListener, and WindowStateListener. All three listeners handle WindowEvent objects. The methods in all three event handlers are implemented by the abstract WindowAdapter class.

When the appropriate listener has been registered on a window (such as a frame or dialog), window events are fired just after the window activity or state has occurred. A window is considered as a "focus owner", if this window receives keyboard input.

The following window activities or states can precede a window event:

  • Opening a window — Showing a window for the first time.
  • Closing a window — Removing the window from the screen.
  • Iconifying a window — Reducing the window to an icon on the desktop.
  • Deiconifying a window — Restoring the window to its original size.
  • Focused window — The window which contains the "focus owner".
  • Activated window (frame or dialog) — This window is either the focused window, or owns the focused window.
  • Deactivated window — This window has lost the focus. For more information about focus, see the AWT Focus Subsystem specification.
  • Maximizing the window — Increasing a window's size to the maximum allowable size, either in the vertical direction, the horizontal direction, or both directions.

    The WindowListener interface defines methods that handle most window events, such as the events for opening and closing the window, activation and deactivation of the window, and iconification and deiconification of the window.

    The other two window listener interfaces, WindowFocusListener and WindowStateListener, were introduced in JDK release 1.4. WindowFocusListener contains methods to detect when the window becomes the focus owner or it loses the focus owner status. WindowStateListener has a single method to detect a change to the state of the window, such as when the window is iconified, deiconified, maximized, or restored to normal.

    Version note: Prior to JDK release 1.4, focus-gained and focus-lost events were inferred by using the WindowListener methods windowActivated and windowDeactivated. This approach did not work with windows that were not frames or dialogs, because such windows never received those events. To determine a window's iconification, the ComponentListener methods componentHidden and componentShown were used. As of JDK release 1.4, the methods defined in WindowFocusListener and WindowStateListener are preferred.

    While you can use the WindowListener methods to detect some window states, such as iconification, there are two reasons why a WindowStateListener might be preferable: it has only one method for you to implement, and it provides support for maximization.

    Note: Not all window managers/native platforms support all window states. The 1.4 java.awt.Toolkit method isFrameStateSupported(int) can be used to determine whether a particular window state is supported by a particular window manager. The WindowEventDemo example, described later in this section, shows how this method can be used.

    Window listeners are commonly used to implement custom window-closing behavior. For example, a window listener is used to save data before closing the window, or to exit the program when the last window closes.

    A user does not necessarily need to implement a window listener to specify what a window should do when the user closes it. By default, when the user closes a window the window becomes invisible. To specify different behavior, use the setDefaultCloseOperation method of the JFrame or JDialog classes. To implement a window-closing handler, use the setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE) method to enable the window listener to provide all window-closing duties. See Responding to Window-Closing Events for details on how to use setDefaultCloseOperation.

    Version note: As of JDK release 1.4, when the last displayable window within the Java virtual machine (VM) is disposed of, the VM may terminate. In previous releases, such as 1.3, the VM remained running even if all windows were disposed of. Note, however, that there can be a delay before the program exits automatically, and that under some circumstances the program might keep running. It is quicker and safer to explicitly exit the program using System.exit(int). See AWT Threading Issues for more information.

    Window listeners are also commonly used to stop threads and release resources when a window is iconified, and to start up again when the window is deiconified. This avoids unnecessarily using the processor or other resources. For example, when a window that contains animation is iconified, it should stop its animation thread and free any large buffers. When the window is deiconified, it can start the thread again and recreate the buffers.

    The following example demonstrates window events. A non-editable text area reports all window events that are fired by its window. This demo implements all methods in the WindowListener, WindowFocusListener, and WindowStateListener interfaces. You can find the demo's code in WindowEventDemo.java.

    Try this:
    1. Click the Launch button to run WindowEventDemo using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

      Launches the WindowEventDemo application
    2. When the window appears, several messages are already displayed. One line reports whether your window manager supports MAXIMIZED_BOTH. If the window manager does not support other window states, this condition is also reported. Next, several lines are displayed, reporting that the window's window listener has received window-opened, activated, and gained-focus events. All the messages displayed in the window are also sent to standard output.
    3. Click another window. The "window lost focus" and "window deactivated" messages will be displayed. If this window is not a frame or a dialog, it will receive the activated or deactivated events.
    4. Click the WindowEventDemo window. You'll see "window activated" and "window gained focus" messages.
    5. Iconify the window, using the window controls. Two iconification messages are displayed, one from the window listener and the other from the window state listener. Unless you are looking at standard output, the messages will not display until the window is deiconified. Window-deactivation and window-lost-focus events are also reported.
    6. De-iconify the window. Two deiconification messages are displayed, one from the window listener and the other from the window state listener. The windowStateChanged method in WindowStateListener class gives the same information that you get using the windowIconified and windowDeiconified methods in WindowListener class. Window-activation and window-gained-focus events are also reported.
    7. Maximize the window, if your look and feel provides a way to do so. Note that some look and feels running on some window managers, such as the Java look and feel on dtwm, provide a way to maximize the window, but no events are reported. This is because dtwm mimics maximization by resizing the window, but it is not a true maximization event. Some look and feels provide a way to maximize the window in the vertical or horizontal direction only. Experiment with your window controls to see what options are available.
    8. Close the window, using the window controls. A window closing message is displayed. Once the window has closed, a window closed message is sent to standard output.

    Here is the demo's window event handling code:

    public class WindowEventDemo extends JFrame implements WindowListener,
                                            WindowFocusListener,
                                            WindowStateListener {
    ...
    static WindowEventDemo frame = new WindowEventDemo("WindowEventDemo");
    JTextArea display;
    ...

    private void addComponentsToPane() {
        display = new JTextArea();
        display.setEditable(false);
        JScrollPane scrollPane = new JScrollPane(display);
        scrollPane.setPreferredSize(new Dimension(500, 450));
        getContentPane().add(scrollPane, BorderLayout.CENTER);

        addWindowListener(this);
        addWindowFocusListener(this);
        addWindowStateListener(this);

        checkWM();
    }

    public WindowEventDemo(String name) {
        super(name);
    }

    //Some window managers don't support all window states.

    public void checkWM() {
        Toolkit tk = frame.getToolkit();
        if (!(tk.isFrameStateSupported(Frame.ICONIFIED))) {
            displayMessage(
                    "Your window manager doesn't support ICONIFIED.");
        }  else displayMessage(
                "Your window manager supports ICONIFIED.");
        if (!(tk.isFrameStateSupported(Frame.MAXIMIZED_VERT))) {
            displayMessage(
                    "Your window manager doesn't support MAXIMIZED_VERT.");
        }  else displayMessage(
                "Your window manager supports MAXIMIZED_VERT.");
        if (!(tk.isFrameStateSupported(Frame.MAXIMIZED_HORIZ))) {
            displayMessage(
                    "Your window manager doesn't support MAXIMIZED_HORIZ.");
        } else displayMessage(
                "Your window manager supports MAXIMIZED_HORIZ.");
        if (!(tk.isFrameStateSupported(Frame.MAXIMIZED_BOTH))) {
            displayMessage(
                    "Your window manager doesn't support MAXIMIZED_BOTH.");
        } else {
            displayMessage(
                    "Your window manager supports MAXIMIZED_BOTH.");
        }
    }

    public void windowClosing(WindowEvent e) {
        displayMessage("WindowListener method called: windowClosing.");
        //A pause so user can see the message before
        //the window actually closes.
        ActionListener task = new ActionListener() {
            boolean alreadyDisposed = false;
            public void actionPerformed(ActionEvent e) {
                if (frame.isDisplayable()) {
                    alreadyDisposed = true;
                    frame.dispose();
                }
            }
        };
        Timer timer = new Timer(500, task); //fire every half second
        timer.setInitialDelay(2000);        //first delay 2 seconds
        timer.setRepeats(false);
        timer.start();
    }

    public void windowClosed(WindowEvent e) {
        //This will only be seen on standard output.
        displayMessage("WindowListener method called: windowClosed.");
    }

    public void windowOpened(WindowEvent e) {
        displayMessage("WindowListener method called: windowOpened.");
    }

    public void windowIconified(WindowEvent e) {
        displayMessage("WindowListener method called: windowIconified.");
    }

    public void windowDeiconified(WindowEvent e) {
        displayMessage("WindowListener method called: windowDeiconified.");
    }

    public void windowActivated(WindowEvent e) {
        displayMessage("WindowListener method called: windowActivated.");
    }

    public void windowDeactivated(WindowEvent e) {
        displayMessage("WindowListener method called: windowDeactivated.");
    }

    public void windowGainedFocus(WindowEvent e) {
        displayMessage("WindowFocusListener method called: windowGainedFocus.");
    }

    public void windowLostFocus(WindowEvent e) {
        displayMessage("WindowFocusListener method called: windowLostFocus.");
    }

    public void windowStateChanged(WindowEvent e) {
        displayStateMessage(
          "WindowStateListener method called: windowStateChanged.", e);
    }

    void displayMessage(String msg) {
        display.append(msg + newline);
        System.out.println(msg);
    }

    void displayStateMessage(String prefix, WindowEvent e) {
        int state = e.getNewState();
        int oldState = e.getOldState();
        String msg = prefix
                   + newline + space
                   + "New state: "
                   + convertStateToString(state)
                   + newline + space
                   + "Old state: "
                   + convertStateToString(oldState);
        displayMessage(msg);
    }

    String convertStateToString(int state) {
        if (state == Frame.NORMAL) {
            return "NORMAL";
        }
        String strState = " ";
        if ((state & Frame.ICONIFIED) != 0) {
            strState += "ICONIFIED";
        }
        //MAXIMIZED_BOTH is a concatenation of two bits, so
        //we need to test for an exact match.
        if ((state & Frame.MAXIMIZED_BOTH) == Frame.MAXIMIZED_BOTH) {
            strState += "MAXIMIZED_BOTH";
        } else {
            if ((state & Frame.MAXIMIZED_VERT) != 0) {
                strState += "MAXIMIZED_VERT";
            }
            if ((state & Frame.MAXIMIZED_HORIZ) != 0) {
                strState += "MAXIMIZED_HORIZ";
            }
            if (" ".equals(strState)){
                strState = "UNKNOWN";
            }
        }
        return strState.trim();
    }
}

The Window Listener API

The window listener API consists of three window listener interfaces and the WindowEvent class. Their methods are listed in the following tables:
  • The WindowListener Interface
  • The WindowFocusListener Interface
  • The WindowStateListener Interface
  • The WindowEvent Class
The methods from all three interfaces are available through the WindowAdapter class.

The WindowListener Interface

Method | Purpose
windowOpened(WindowEvent) | Called just after the listened-to window has been shown for the first time.
windowClosing(WindowEvent) | Called in response to a user request for the listened-to window to be closed. To actually close the window, the listener should invoke the window's dispose or setVisible(false) method.
windowClosed(WindowEvent) | Called just after the listened-to window has closed.
windowIconified(WindowEvent)
windowDeiconified(WindowEvent) 		Called just after the listened-to window is iconified or deiconified, respectively.
windowActivated(WindowEvent)
windowDeactivated(WindowEvent) 		Called just after the listened-to window is activated or deactivated, respectively. These methods are not sent to windows that are not frames or dialogs. For this reason, we prefer the 1.4 windowGainedFocus and windowLostFocus methods to determine when a window gains or loses the focus.

The WindowFocusListener Interface

Method Purpose
windowGainedFocus(WindowEvent)
windowLostFocus(WindowEvent) 		Called just after the listened-to window gains or loses the focus, respectively.

The WindowStateListener Interface

Method Purpose
windowStateChanged(WindowEvent) Called just after the listened-to window's state is changed by being iconified, deiconified, maximized, or returned to normal. The state is available through the WindowEvent as a bitwise mask. The possible values, defined in java.awt.Frame, are:
  • NORMAL. Indicates that no state bits are set.
  • ICONIFIED.
  • MAXIMIZED_HORIZ.
  • MAXIMIZED_VERT.
  • MAXIMIZED_BOTH. Concatenates MAXIMIZED_HORIZ and MAXIMIZED_VERT. A window manager may support MAXIMIZED_BOTH, while not supporting MAXIMIZED_HORIZ or MAXIMIZED_VERT. The java.awt.Toolkit method isFrameStateSupported(int) can be used to determine what states are supported by the window manager.

The WindowEvent Class
Method | Purpose
Window getWindow() | Returns the window that fired the event. You can use this instead of the getSource method.
Window getOppositeWindow() | Returns the other window involved in this focus or activation change. For a WINDOW_ACTIVATED or WINDOW_GAINED_FOCUS event, this returns the window that lost activation or the focus. For a WINDOW_DEACTIVATED or WINDOW_LOST_FOCUS event, this returns the window that gained activation or the focus. For any other type of WindowEvent with a Java application in a different VM or context, or with no other window, null is returned. This method was introduced in JDK release 1.4.
int getOldState()
int getNewState() 		For WINDOW_STATE_CHANGED events, these methods return the previous or new state of the window as a bitwise mask. These methods were introduced in JDK release 1.4.

Examples that Use Window Listeners
The following table lists the examples that use window listeners.

Example | Where Described | Notes
WindowEventDemo | This section | Reports all window events that occur on one window to demonstrate the circumstances under which window events are fired.
SliderDemo | How to Use Sliders | Listens for window iconify and deiconify events, so that it can stop the animation when the window isn't visible.
InternalFrameEventDemo | How to Write an Internal Frame Listener | Reports all internal frame events that occur on one internal frame to demonstrate the circumstances under which internal frame events are fired. Internal frame events are similar to window events.
DialogDemo | Text Component Features | CustomDialog.java uses setDefaultCloseOperation instead of a window listener to determine what action to take when the user closes the window.
Framework — A demo that allows multiple windows to be created and destroyed.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write an Undoable Edit Listener
Next page: Listener API Table


Listener API Table (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
Listener API Table
In the table that follows, the first column gives the name of the listener interface, with either a link to the tutorial page that discusses the listener or, if the tutorial doesn't discuss the listener, a link to the API docs. The second column names the corresponding adapter class, if any. (For a discussion of using adapters, see Using Adapters and Inner Classes to Handle Events.) The third column lists the methods that the listener interface contains and shows the type of the event object passed into the method. Typically, the listener, the adapter, and the event type have the same name prefix, but this is not always the case.

To see which Swing components can fire which kinds of events, see Listeners Supported by Swing Components.

Listener Interface | Adapter Class | Listener Methods
ActionListener | none | actionPerformed(ActionEvent)
AncestorListener none ancestorAdded(AncestorEvent)
ancestorMoved(AncestorEvent)
ancestorRemoved(AncestorEvent)
CaretListener | none | caretUpdate(CaretEvent)
CellEditorListener none editingStopped(ChangeEvent)
editingCanceled(ChangeEvent)
ChangeListener | none | stateChanged(ChangeEvent)
ComponentListener ComponentAdapter componentHidden(ComponentEvent)
componentMoved(ComponentEvent)
componentResized(ComponentEvent)
componentShown(ComponentEvent)
ContainerListener ContainerAdapter componentAdded(ContainerEvent)
componentRemoved(ContainerEvent)
DocumentListener none changedUpdate(DocumentEvent)
insertUpdate(DocumentEvent)
removeUpdate(DocumentEvent)
ExceptionListener | none | exceptionThrown(Exception)
FocusListener FocusAdapter focusGained(FocusEvent)
focusLost(FocusEvent)
HierarchyBoundsListener HierarchyBoundsAdapter ancestorMoved(HierarchyEvent)
ancestorResized(HierarchyEvent)
HierarchyListener | none | hierarchyChanged(HierarchyEvent)
HyperlinkListener | none | hyperlinkUpdate(HyperlinkEvent)
InputMethodListener none caretPositionChanged(InputMethodEvent)
inputMethodTextChanged(InputMethodEvent)
InternalFrameListener InternalFrameAdapter internalFrameActivated(InternalFrameEvent)
internalFrameClosed(InternalFrameEvent)
internalFrameClosing(InternalFrameEvent)
internalFrameDeactivated(InternalFrameEvent)
internalFrameDeiconified(InternalFrameEvent)
internalFrameIconified(InternalFrameEvent)
internalFrameOpened(InternalFrameEvent)
ItemListener | none | itemStateChanged(ItemEvent)
KeyListener KeyAdapter keyPressed(KeyEvent)
keyReleased(KeyEvent)
keyTyped(KeyEvent)
ListDataListener none contentsChanged(ListDataEvent)
intervalAdded(ListDataEvent)
intervalRemoved(ListDataEvent)
ListSelectionListener | none | valueChanged(ListSelectionEvent)
MenuDragMouseListener none menuDragMouseDragged(MenuDragMouseEvent)
menuDragMouseEntered(MenuDragMouseEvent)
menuDragMouseExited(MenuDragMouseEvent)
menuDragMouseReleased(MenuDragMouseEvent)
MenuKeyListener none menuKeyPressed(MenuKeyEvent)
menuKeyReleased(MenuKeyEvent)
menuKeyTyped(MenuKeyEvent)
MenuListener none menuCanceled(MenuEvent)
menuDeselected(MenuEvent)
menuSelected(MenuEvent)
MouseInputListener (extends MouseListener and MouseMotionListener MouseInputAdapter
MouseAdapter 		mouseClicked(MouseEvent)
mouseEntered(MouseEvent)
mouseExited(MouseEvent)
mousePressed(MouseEvent)
mouseReleased(MouseEvent)
mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
MouseAdapter(MouseEvent)
MouseListener MouseAdapter, MouseInputAdapter mouseClicked(MouseEvent)
mouseEntered(MouseEvent)
mouseExited(MouseEvent)
mousePressed(MouseEvent)
mouseReleased(MouseEvent)
MouseMotionListener MouseMotionAdapter, MouseInputAdapter mouseDragged(MouseEvent)
mouseMoved(MouseEvent)
MouseWheelListener MouseAdapter mouseWheelMoved(MouseWheelEvent)
MouseAdapter
PopupMenuListener none popupMenuCanceled(PopupMenuEvent)
popupMenuWillBecomeInvisible(PopupMenuEvent)
popupMenuWillBecomeVisible(PopupMenuEvent)
PropertyChangeListener | none | propertyChange(PropertyChangeEvent)
TableColumnModelListener none columnAdded(TableColumnModelEvent)
columnMoved(TableColumnModelEvent)
columnRemoved(TableColumnModelEvent)
columnMarginChanged(ChangeEvent)
columnSelectionChanged(ListSelectionEvent)
TableModelListener | none | tableChanged(TableModelEvent)
TreeExpansionListener none treeCollapsed(TreeExpansionEvent)
treeExpanded(TreeExpansionEvent)
TreeModelListener none treeNodesChanged(TreeModelEvent)
treeNodesInserted(TreeModelEvent)
treeNodesRemoved(TreeModelEvent)
treeStructureChanged(TreeModelEvent)
TreeSelectionListener | none | valueChanged(TreeSelectionEvent)
TreeWillExpandListener none treeWillCollapse(TreeExpansionEvent)
treeWillExpand(TreeExpansionEvent)
UndoableEditListener | none | undoableEditHappened(UndoableEditEvent)
VetoableChangeListener | none | vetoableChange(PropertyChangeEvent)
WindowFocusListener WindowAdapter windowGainedFocus(WindowEvent)
windowLostFocus(WindowEvent)
WindowListener WindowAdapter windowActivated(WindowEvent)
windowClosed(WindowEvent)
windowClosing(WindowEvent)
windowDeactivated(WindowEvent)
windowDeiconified(WindowEvent)
windowIconified(WindowEvent)
windowOpened(WindowEvent)
WindowStateListener | WindowAdapter | windowStateChanged(WindowEvent)

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How to Write Window Listeners
Next page: Solving Common Event-Handling Problems


Solving Common Event-Handling Problems (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
Solving Common Event-Handling Problems
This section discusses problems that you might encounter while handling events.

Problem: I'm trying to handle certain events from a component, but the component isn't generating the events it should.

  • First, make sure you registered the right kind of listener to detect the events. See whether another kind of listener might detect the kind of events you need.
  • Make sure you registered the listener on the right object.
  • Did you implement the event handler correctly? For example, if you extended an adapter class, then make sure you used the right method signature. Make sure each event-handling method is public void, that the name spelled right and that the argument is of the right type.
  • If you still think that the component isn't generating the events it should, check the Java Developer Connection to see whether this is a known bug.

Problem: My combo box isn't generating low-level events such as focus events.

  • Combo boxes are compound components — components implemented using multiple components. For this reason, combo boxes don't fire the low-level events that simple components fire. For more information, see Handling Events on a Combo Box.

Problem: The document for an editor pane (or text pane) isn't firing document events.

  • The document instance for an editor pane or text pane might change when loading text from a URL. Thus, your listeners might be listening for events on an unused document. For example, if you load an editor pane or text pane with HTML that was previously loaded with plain text, the document will change to an HTMLDocument instance. If your program dynamically loads text into an editor pane or text pane, make sure the code adjusts for possible changes to the document (re-register document listeners on the new document, and so on).
If you don't see your problem in this list, see Solving Common Component Problems.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Listener API Table
Next page: Questions and Exercises: Writing Event Listeners


Questions and Exercises: Writing Event Listeners (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Questions and Exercises: Writing Event Listeners
Use this lesson’s tables, the component how-to sections and the event listeners how-to sections to complete these questions and exercises.

Questions

1. What listener would you implement to be notified when a particular component has appeared on screen? What method tells you this information?

2. What listener would you implement to be notified when the user has finished editing a text field by pressing Enter? What listener would you implement to be notified as each character is typed into a text field? Note that you should not implement a general- purpose key listener, but a listener specific to text.

3. What listener would you implement to be notified when a spinner’s value has changed? How would you get the spinner’s new value?

4. The default behavior for the focus subsystem is to consume the focus traversal keys, such as Tab and Shift Tab. Say you want to prevent this from happening in one of your application’s components. How would you accomplish this?

Exercises

1. Take the Beeper.java (in a .java source file) example and add a text field. Implement it so that when the user has finishing entering data, the system beeps.

2. Take the Beeper.java (in a .java source file) example and add a selectable component that allows the user to enter a number from 1 to 10. For example, you can use a combo box, a set of radio buttons, or a spinner. Implement it so that when the user has selected the number, the system beeps that many times.

Check your answers.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Solving Common Event-Handling Problems
Next page: Performing Custom Painting


Lesson: Performing Custom Painting (The Java™ Tutorials > Creating a GUI with JFC/Swing)

Performing Custom Painting
Creating the Demo Application (Step 1)
Creating the Demo Application (Step 2)
Creating the Demo Application (Step 3)
Refining the Design
A Closer Look at the Paint Mechanism
Summary
Solving Common Painting Problems
Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • Trail • Next »
Lesson: Performing Custom Painting
This lesson describes custom painting in Swing. Many programs will get by just fine without writing their own painting code; they will simply use the standard GUI components that are already available in the Swing API. But if you need specific control over how your graphics are drawn, then this lesson is for you. We will explore custom painting by creating a simple GUI application that draws a shape in response to the user's mouse activity. By intentionally keeping its design simple, we can focus on the underlying painting concepts, which in turn will relate to other GUI applications that you develop in the future.

This lesson explains each concept in steps as you construct the demo application. It presents the code as soon as possible with a minimum amount of background reading. Custom painting in Swing is similar to custom painting in AWT, but since we do not recommend writing your applications entirely with the AWT, its painting mechanism is not specifically discussed here. You may find it useful to read this lesson followed by the in-depth discussion of Painting in AWT and Swing on the Sun Developer Network (SDN).

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Creating the Demo Application (Step 1)


Creating the Demo Application (Step 1) (The Java™ Tutorials > Creating a GUI with JFC/Swing > Performing Custom Painting)

Trail: Creating a GUI with JFC/Swing
Lesson: Performing Custom Painting
Performing Custom Painting
Creating the Demo Application (Step 1)
Creating the Demo Application (Step 2)
Creating the Demo Application (Step 3)
Refining the Design
A Closer Look at the Paint Mechanism
Summary
Solving Common Painting Problems
Home Page > Creating a GUI with JFC/Swing > Performing Custom Painting
« Previous • Trail • Next »
Creating the Demo Application (Step 1)

All Graphical User Interfaces require some kind of main application frame in which to display. In Swing, this is an instance of javax.swing.JFrame. Therefore, our first step is to instantiate this class and make sure that everything works as expected. Note that when programming in Swing, your GUI creation code should be placed on the Event Dispatch Thread (EDT). This will prevent potential race conditions that could lead to deadlock. The following code listing shows how this is done.

Figure of an empty JFrame with Swing Paint Demo as the title

An Instance of javax.swing.JFrame

Click the Launch button to run SwingPaintDemo1 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SwingPaintDemo1 example

package painting;

import javax.swing.SwingUtilities;
import javax.swing.JFrame;

public class SwingPaintDemo1 {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        System.out.println("Created GUI on EDT? "+
                SwingUtilities.isEventDispatchThread());
        JFrame f = new JFrame("Swing Paint Demo");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.setSize(250,250);
        f.setVisible(true);
    }
}

This creates the frame, sets its title, and makes everything visible. We have used the SwingUtilities helper class to construct this GUI on the Event Dispatch Thread. Note that by default, a JFrame does not exit the application when the user clicks its "close" button. We provide this behavior by invoking the setDefaultCloseOperation method, passing in the appropriate argument. Also, we are explicity setting the frame's size to 250 x 250 pixels. This step will not be necessary once we start adding components to the frame.

Exercises:

  1. Compile and run the application.
  2. Test the minimize and maximize buttons.
  3. Click the close button (the application should exit.)

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Performing Custom Painting
Next page: Creating the Demo Application (Step 2)


Creating the Demo Application (Step 2) (The Java™ Tutorials > Creating a GUI with JFC/Swing > Performing Custom Painting)

Trail: Creating a GUI with JFC/Swing
Lesson: Performing Custom Painting
Performing Custom Painting
Creating the Demo Application (Step 1)
Creating the Demo Application (Step 2)
Creating the Demo Application (Step 3)
Refining the Design
A Closer Look at the Paint Mechanism
Summary
Solving Common Painting Problems
Home Page > Creating a GUI with JFC/Swing > Performing Custom Painting
« Previous • Trail • Next »
Creating the Demo Application (Step 2)
Next, we will add a custom drawing surface to the frame. For this we will create a subclass of javax.swing.JPanel (a generic lightweight container) which will supply the code for rendering our custom painting.

Creating a New Project within the GUI

A javax.swing.JPanel Subclass

Click the Launch button to run SwingPaintDemo2 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SwingPaintDemo2 example

package painting;

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;

public class SwingPaintDemo2 {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        System.out.println("Created GUI on EDT? "+
        SwingUtilities.isEventDispatchThread());
        JFrame f = new JFrame("Swing Paint Demo");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new MyPanel());
        f.pack();
        f.setVisible(true);
    }
}

class MyPanel extends JPanel {

    public MyPanel() {
        setBorder(BorderFactory.createLineBorder(Color.black));
    }

    public Dimension getPreferredSize() {
        return new Dimension(250,200);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);

        // Draw Text
        g.drawString("This is my custom Panel!",10,20);
    }
}

The first change you will notice is that we are now importing a number of additional classes, such as JPanel, Color, and Graphics. Since some of the older AWT classes are still used in modern Swing applications, it is normal to see the java.awt package in a few of the import statements. We have also defined a custom JPanel subclass, called MyPanel, which comprises the majority of the new code.

The MyPanel class definition has a constructor that sets a black border around its edges. This is a subtle detail that might be difficult to see at first (if it is, just comment out the invocation of setBorder and then recompile.) MyPanel also overrides getPreferredSize, which returns the desired width and height of the panel (in this case 250 is the width, 200 is the height.) Because of this, the SwingPaintDemo class no longer needs to specify the size of the frame in pixels. It simply adds the panel to the frame and then invokes pack.

The paintComponent method is where all of your custom painting takes place. This method is defined by javax.swing.JComponent and then overridden by your subclasses to provide their custom behavior. Its sole parameter, a java.awt.Graphics object, exposes a number of methods for drawing 2D shapes and obtaining information about the application's graphics environment. In most cases the object that is actually received by this method will be an instance of java.awt.Graphics2D (a Graphics subclass), which provides support for sophisticated 2D graphics rendering.

Most of the standard Swing components have their look and feel implemented by separate "UI Delegate" objects. The invocation of super.paintComponent(g) passes the graphics context off to the component's UI delegate, which paints the panel's background. For a closer look at this process, see the section entitled "Painting and the UI Delegate" in the aforementioned SDN article.

Exercises:

  1. Now that you have drawn some custom text to the screen, try minimizing and restoring the application as you did before.
  2. Obscure a part of the text with another window, then move that window out of the way to re-expose the custom text. In both cases, the painting subsystem will determine that the component is damaged and will ensure that your paintComponent method is invoked.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating the Demo Application (Step 1)
Next page: Creating the Demo Application (Step 3)


Creating the Demo Application (Step 3) (The Java™ Tutorials > Creating a GUI with JFC/Swing > Performing Custom Painting)

Trail: Creating a GUI with JFC/Swing
Lesson: Performing Custom Painting
Performing Custom Painting
Creating the Demo Application (Step 1)
Creating the Demo Application (Step 2)
Creating the Demo Application (Step 3)
Refining the Design
A Closer Look at the Paint Mechanism
Summary
Solving Common Painting Problems
Home Page > Creating a GUI with JFC/Swing > Performing Custom Painting
« Previous • Trail • Next »
Creating the Demo Application (Step 3)
Finally, we will add the event-handling code to programatically repaint the component whenever the user clicks or drags the mouse. To keep our custom painting as efficient as possible, we will track the mouse coordinates and repaint only the areas of the screen that have changed. This is a recommended best practice that will keep your application running as efficiently as possible.

The completed application, showing a red square with black border

The Completed Application

Figure 3: The Completed Application

Click the Launch button to run SwingPaintDemo3 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SwingPaintDemo3 example

package painting;

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseMotionAdapter;

public class SwingPaintDemo3 {

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        System.out.println("Created GUI on EDT? "+
        SwingUtilities.isEventDispatchThread());
        JFrame f = new JFrame("Swing Paint Demo");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new MyPanel());
        f.pack();
        f.setVisible(true);
    }
}

class MyPanel extends JPanel {

    private int squareX = 50;
    private int squareY = 50;
    private int squareW = 20;
    private int squareH = 20;

    public MyPanel() {

        setBorder(BorderFactory.createLineBorder(Color.black));

        addMouseListener(new MouseAdapter() {
            public void mousePressed(MouseEvent e) {
                moveSquare(e.getX(),e.getY());
            }
        });

        addMouseMotionListener(new MouseAdapter() {
            public void mouseDragged(MouseEvent e) {
                moveSquare(e.getX(),e.getY());
            }
        });

    }

    private void moveSquare(int x, int y) {
        int OFFSET = 1;
        if ((squareX!=x) || (squareY!=y)) {
            repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
            squareX=x;
            squareY=y;
            repaint(squareX,squareY,squareW+OFFSET,squareH+OFFSET);
        }
    }

    public Dimension getPreferredSize() {
        return new Dimension(250,200);
    }

    protected void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawString("This is my custom Panel!",10,20);
        g.setColor(Color.RED);
        g.fillRect(squareX,squareY,squareW,squareH);
        g.setColor(Color.BLACK);
        g.drawRect(squareX,squareY,squareW,squareH);
    }
}

This change first imports the various mouse classes from the java.awt.event package, making the application capable of responding to the user's mouse activity. The constructor has been updated to register event listeners for mouse presses and drags. Whenever a MouseEvent received, it is forwarded to the moveSquare method, which updates the square's coordinates and repaints the component in an intelligent manner. Note that by default, any code that is placed within these event handlers will be executed on the Event Dispatch Thread.

But the most important change is the invocation of the repaint method. This method is defined by java.awt.Component and is the mechanism that allows you to programatically repaint the surface of any given component. It has a no-arg version (which repaints the entire component) and a multi-arg version (which repaints only the specified area.) This area is also known as the clip. Invoking the multi-arg version of repaint takes a little extra effort, but guarantees that your painting code will not waste cycles repainting areas of the screen that have not changed.

Because we are manually setting the clip, our moveSquare method invokes the repaint method not once, but twice. The first invocation tells Swing to repaint the area of the component where the square previously was (the inherited behavior uses the UI Delegate to fill that area with the current background color.) The second invocation paints the area of the component where the square currently is. An important point worth noting is that although we have invoked repaint twice in a row in the same event handler, Swing is smart enough to take that information and repaint those sections of the screen all in one single paint operation. In other words, Swing will not repaint the component twice in a row, even if that is what the code appears to be doing.

Exercises:

  1. Comment out the first invocation of repaint and note what happens when you click or drag the mouse. Because that line is responsible for filling in the background, you should notice that all squares remain on screen after they are painted.

  2. With multiple squares on screen, minimize and restore the application frame. What happens? You should notice that the act of maximizing the screen causes the system to entirely repaint the components surface, which will erase all squares except the current one.

  3. Comment out both invocations of repaint, and add a line at the end of the paintComponent method to invoke the zero-arg version of repaint instead. The application will appear to be restored to its original behavior, but painting will now be less efficient since the entire surface area of the component is now being painted. You may notice slower performace, especially if the application is maximized.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating the Demo Application (Step 2)
Next page: Refining the Design


Refining the Design (The Java™ Tutorials > Creating a GUI with JFC/Swing > Performing Custom Painting)

Trail: Creating a GUI with JFC/Swing
Lesson: Performing Custom Painting
Performing Custom Painting
Creating the Demo Application (Step 1)
Creating the Demo Application (Step 2)
Creating the Demo Application (Step 3)
Refining the Design
A Closer Look at the Paint Mechanism
Summary
Solving Common Painting Problems
Home Page > Creating a GUI with JFC/Swing > Performing Custom Painting
« Previous • Trail • Next »
Refining the Design
For demonstration purposes it makes sense to keep the painting logic entirely contained within the MyPanel class. But if your application will need to track multiple instances, one pattern that you could use is to factor that code out into a separate class so that each square can be treated as an individual object. This technique is common in 2D game programming and is sometimes referred to as "sprite animation."

Click the Launch button to run SwingPaintDemo4 using Java™ Web Start (download JDK 6). Alternatively, to compile and run the example yourself, consult the example index.

Launches the SwingPaintDemo4 example

package painting;

import javax.swing.SwingUtilities;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.BorderFactory;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseMotionAdapter;

public class SwingPaintDemo4 {

    public static void main(String[] args) {

        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                createAndShowGUI();
            }
        });
    }

    private static void createAndShowGUI() {
        System.out.println("Created GUI on EDT? "+
        SwingUtilities.isEventDispatchThread());
        JFrame f = new JFrame("Swing Paint Demo");
        f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        f.add(new MyPanel());
        f.setSize(250,250);
        f.setVisible(true);
    }

}

class MyPanel extends JPanel {

    RedSquare redSquare = new RedSquare();

    public MyPanel() {

        setBorder(BorderFactory.createLineBorder(Color.black));

        addMouseListener(new MouseAdapter(){
            public void mousePressed(MouseEvent e){
                moveSquare(e.getX(),e.getY());
            }
        });

        addMouseMotionListener(new MouseAdapter(){
            public void mouseDragged(MouseEvent e){
                moveSquare(e.getX(),e.getY());
            }
        });

    }

    private void moveSquare(int x, int y){

        // Current square state, stored as final variables
        // to avoid repeat invocations of the same methods.
        final int CURR_X = redSquare.getX();
        final int CURR_Y = redSquare.getY();
        final int CURR_W = redSquare.getWidth();
        final int CURR_H = redSquare.getHeight();
        final int OFFSET = 1;

        if ((CURR_X!=x) || (CURR_Y!=y)) {

            // The square is moving, repaint background
            // over the old square location.
            repaint(CURR_X,CURR_Y,CURR_W+OFFSET,CURR_H+OFFSET);

            // Update coordinates.
            redSquare.setX(x);
            redSquare.setY(y);

            // Repaint the square at the new location.
            repaint(redSquare.getX(), redSquare.getY(),
                    redSquare.getWidth()+OFFSET,
                    redSquare.getHeight()+OFFSET);
        }
    }

    public Dimension getPreferredSize() {
        return new Dimension(250,200);
    }

    public void paintComponent(Graphics g) {
        super.paintComponent(g);
        g.drawString("This is my custom Panel!",10,20);

        redSquare.paintSquare(g);
    }
}

class RedSquare{

    private int xPos = 50;
    private int yPos = 50;
    private int width = 20;
    private int height = 20;

    public void setX(int xPos){
        this.xPos = xPos;
    }

    public int getX(){
        return xPos;
    }

    public void setY(int yPos){
        this.yPos = yPos;
    }

    public int getY(){
        return yPos;
    }

    public int getWidth(){
        return width;
    }

    public int getHeight(){
        return height;
    }

    public void paintSquare(Graphics g){
        g.setColor(Color.RED);
        g.fillRect(xPos,yPos,width,height);
        g.setColor(Color.BLACK);
        g.drawRect(xPos,yPos,width,height);
    }
}

In this particular implementation we have created a RedSquare class entirely from scratch. Another approach would be to resuse the functionlity of java.awt.Rectangle by making the RedSquare a subclass of it. Regardless of how RedSquare is implemented, the important point is that we have given the class a method that accepts a Graphics object, and that method is invoked from the panel's paintComponent method. This separation keeps your code clean because it essentially tells each red square to paint itself.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating the Demo Application (Step 3)
Next page: A Closer Look at the Paint Mechanism


A Closer Look at the Paint Mechanism (The Java™ Tutorials > Creating a GUI with JFC/Swing > Performing Custom Painting)

Trail: Creating a GUI with JFC/Swing
Lesson: Performing Custom Painting
Performing Custom Painting
Creating the Demo Application (Step 1)
Creating the Demo Application (Step 2)
Creating the Demo Application (Step 3)
Refining the Design
A Closer Look at the Paint Mechanism
Summary
Solving Common Painting Problems
Home Page > Creating a GUI with JFC/Swing > Performing Custom Painting
« Previous • Trail • Next »
A Closer Look at the Paint Mechanism
By now you know that the paintComponent method is where all of your painting code should be placed. It is true that this method will be invoked when it is time to paint, but painting actually begins higher up the class heirarchy, with the paint method (defined by java.awt.Component.) This method will be executed by the painting subsystem whenever you component needs to be rendered. Its signature is:

  • public void paint(Graphics g)
javax.swing.JComponent extends this class and further factors the paint method into three separate methods, which are invoked in the following order:

  • protected void paintComponent(Graphics g)
  • protected void paintBorder(Graphics g)
  • protected void paintChildren(Graphics g)

The API does nothing to prevent your code from overriding paintBorder and paintChildren, but generally speaking, there is no reason for you to do so. For all practical purposes paintComponent will be the only method that you will ever need to override.

As previously mentioned, most of the standard Swing components have their look and feel implemented by separate UI Delegates. This means that most (or all) of the painting for the standard Swing components proceeds as follows.

  1. paint() invokes paintComponent().
  2. If the ui property is non-null, paintComponent() invokes ui.update().
  3. If the component's opaque property is true, ui.udpate() fills the component's background with the background color and invokes ui.paint().
  4. ui.paint() renders the content of the component.
This is why our SwingPaintDemo code invokes super.paintComponent(g). We could add an additional comment to make this more clear:
public void paintComponent(Graphics g) {
        // Let UI Delegate paint first, which
        // includes background filling since
        // this component is opaque.

        super.paintComponent(g);
        g.drawString("This is my custom Panel!",10,20);
        redSquare.paintSquare(g);
}
If you have understood all of the demo code provided in this lesson, congratulations! You have enough practical knowledge to write efficient painting code in your own applications. If however you want a closer look "under the hood", please refer to the SDN article linked to from the first page of this lesson.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Refining the Design
Next page: Summary


Summary (The Java™ Tutorials > Creating a GUI with JFC/Swing > Performing Custom Painting)

Trail: Creating a GUI with JFC/Swing
Lesson: Performing Custom Painting
Performing Custom Painting
Creating the Demo Application (Step 1)
Creating the Demo Application (Step 2)
Creating the Demo Application (Step 3)
Refining the Design
A Closer Look at the Paint Mechanism
Summary
Solving Common Painting Problems
Home Page > Creating a GUI with JFC/Swing > Performing Custom Painting
« Previous • Trail • Next »
Summary

  • In Swing, painting begins with the paint method, which then invokes paintComponent, paintBorder, and paintChildren. The system will invoke this automatically when a component is first painted, is resized, or becomes exposed after being hidden by another window.

  • Programatic repaints are accomplished by invoking a component's repaint method; do not invoke its paintComponent directly. Invoking repaint causes the painting subsystem to take the necessary steps to ensure that your paintComponent method is invoked at an appropriate time.

  • The multi-arg version of repaint allows you to shrink the component's clip rectangle (the section of the screen that is affected by painting operations) so that painting can become more efficient. We utilized this technique in the moveSquare method to avoid repainting sections of the screen that have not changed. There is also a no-arg version of this method that will repaint the component's entire surface area.

  • Because we have shrunk the clip rectangle, our moveSquare method invokes repaint not once, but twice. The first invocation repaints the area of the component where the square previously was (the inherited behavior is to fill the area with the current background color.) The second invocation paints the area of the component where the square currently is.

  • You can invoke repaint multiple times from within the same event handler, but Swing will take that information and repaint the component in just one operation.

  • For components with a UI Delegate, you should pass the Graphics paramater with the line super.paintComponent(g) as the first line of code in your paintComponent override. If you do not, then your component will be responsible for manually painting its background. You can experiment with this by commenting out that line and recompiling to see that the background is no longer painted.

  • By factoring out our new code into a separate RedSquare class, the application maintains an object-oriented design, which keeps the paintComponent method of the MyPanel class free of clutter. Painting still works because we have passed the Graphics object off to the red square by invoking its paintSquare(Graphics g) method. Keep in mind that the name of this method is one that we have created from scratch; we are not overriding paintSquare from anywhere higher up in the Swing API.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: A Closer Look at the Paint Mechanism
Next page: Solving Common Painting Problems


Solving Common Painting Problems (The Java™ Tutorials > Creating a GUI with JFC/Swing > Performing Custom Painting)

Trail: Creating a GUI with JFC/Swing
Lesson: Performing Custom Painting
Performing Custom Painting
Creating the Demo Application (Step 1)
Creating the Demo Application (Step 2)
Creating the Demo Application (Step 3)
Refining the Design
A Closer Look at the Paint Mechanism
Summary
Solving Common Painting Problems
Home Page > Creating a GUI with JFC/Swing > Performing Custom Painting
« Previous • Trail • Next »
Solving Common Painting Problems
Problem: I don't know where to put my painting code.
  • Painting code belongs in the paintComponent method of any component descended from JComponent.
Problem: The stuff I paint doesn't show up.
  • Check whether your component is showing up at all. Solving Common Component Problems should help you with this.

  • Check whether repaint is invoked on your component whenever its appearance needs to be updated.
Problem: My component's foreground shows up, but its background is invisible. The result is that one or more components directly behind my component are unexpectedly visible.
  • Make sure your component is opaque. JPanels, for example, are opaque by default in many but not all look and feels. To make components such as JLabels and GTK+ JPanels opaque, you must invoke setOpaque(true) on them.

  • If your custom component extends JPanel or a more specialized JComponent descendant, then you can paint the background by invoking super.paintComponent before painting the contents of your component.

  • You can paint the background yourself using this code at the top of a custom component's paintComponent method:
    g.setColor(getBackground());
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(getForeground());

Problem: I used setBackground to set my component's background color, but it seemed to have no effect.

  • Most likely, your component isn't painting its background, either because it's not opaque or your custom painting code doesn't paint the background. If you set the background color for a JLabel, for example, you must also invoke setOpaque(true) on the label to make the label's background be painted.

Problem: I'm using the exact same code as a tutorial example, but it doesn't work. Why?

  • Is the code executed in the exact same method as the tutorial example? For example, if the tutorial example has the code in the example's paintComponent method, then this method might be the only place where the code is guaranteed to work.
Problem: How do I paint thick lines? patterns?
  • The JavaTM 2D API provides extensive support for implementing line widths and styles, as well as patterns for use in filling and stroking shapes. See the 2D Graphics trail for more information on using the Java 2D API.
Problem: The edges of a particular component look odd.
  • Because components often update their borders to reflect component state, you generally should avoid invoking setBorder except on JPanels and custom subclasses of JComponent.

  • Is the component painted by a look and feel such as GTK+ or Windows XP that uses UI-painted borders instead of Border objects? If so, don't invoke setBorder on the component.

  • Does the component have custom painting code? If so, does the painting code take the component's insets into account?
Problem: Visual artifacts appear in my GUI.
  • If you set the background color of a component, be sure the color has no transparency if the component is supposed to be opaque.

  • Use the setOpaque method to set component opacity if necessary. For example, the content pane must be opaque, but components with transparent backgrounds must not be opaque.

  • Make sure your custom component fills its painting area completely if it's opaque.
Problem: The performance of my custom painting code is poor.
  • If you can paint part of your component, use the getClip or getClipBounds method of Graphics to determine which area you need to paint. The less you paint, the faster it will be.

  • If only part of your component needs to be updated, make paint requests using a version of repaint that specifies the painting region.

  • For help on choosing efficient painting techniques, look for the string "performance" in the Java 2D API home page.
Problem: The same transforms applied to seemingly identical Graphics objects sometimes have slightly different effects.
  • Because the Swing painting code sets the transform (using the Graphics method translate) before invoking paintComponent, any transforms that you apply have a cumulative effect. This doesn't matter when doing a simple translation, but a more complex AffineTransform, for example, might have unexpected results.

If you don't see your problem in this list, see Solving Common Component Problems and Solving Common Layout Problems.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary
Next page: End of Trail


Trail: Collections (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Collections

by Josh Bloch

This chapter describes the Java Collections Framework. Here you will learn what collections are and how they can make your job easier and programs better. You'll learn about the core elements — interfaces, implementations, and algorithms — that comprise the Java Collections Framework.

Introduction tells you what collections are, and how they'll make your job easier and your programs better. You'll learn about the core elements that comprise the Collections Framework: interfaces, implementations and algorithms.

Interfaces describes the core collection interfaces, which are the heart and soul of the Java Collections Framework. You'll learn general guidelines for effective use of these interfaces, including when to use which interface. You'll also learn idioms for each interface that will help you get the most out of the interfaces.

Implementations describes the JDK's general-purpose collection implementations and tells you when to use which implementation. You'll also learn about the wrapper implementations, which add functionality to general-purpose implementations.

Algorithms describes the polymorphic algorithms provided by the JDK to operate on collections. With any luck you'll never have to write your own sort routine again!

Custom Implementations tells you why you might want to write your own collection implementation (instead of using one of the general-purpose implementations provided by the JDK), and how you'd go about it. It's easy with the JDK's abstract collection implementations!

Interoperability tells you how the Collections Framework interoperates with older APIs that predate the addition of Collections to Java. Also, it tells you how to design new APIs so that they'll interoperate seamlessly with other new APIs.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Introduction to Collections


Lesson: Introduction to Collections (The Java™ Tutorials > Collections)

Trail: Collections
Home Page > Collections
« Previous • Trail • Next »
Lesson: Introduction to Collections
A collection — sometimes called a container — is simply an object that groups multiple elements into a single unit. Collections are used to store, retrieve, manipulate, and communicate aggregate data. Typically, they represent data items that form a natural group, such as a poker hand (a collection of cards), a mail folder (a collection of letters), or a telephone directory (a mapping of names to phone numbers).

If you've used the Java programming language — or just about any other programming language — you're already familiar with collections. Collection implementations in earlier (pre-1.2) versions of the Java platform included Vector, Hashtable, and array. However, those earlier versions did not contain a collections framework.

What Is a Collections Framework?

A collections framework is a unified architecture for representing and manipulating collections. All collections frameworks contain the following:
  • Interfaces: These are abstract data types that represent collections. Interfaces allow collections to be manipulated independently of the details of their representation. In object-oriented languages, interfaces generally form a hierarchy.
  • Implementations: These are the concrete implementations of the collection interfaces. In essence, they are reusable data structures.
  • Algorithms: These are the methods that perform useful computations, such as searching and sorting, on objects that implement collection interfaces. The algorithms are said to be polymorphic: that is, the same method can be used on many different implementations of the appropriate collection interface. In essence, algorithms are reusable functionality.

Apart from the Java Collections Framework, the best-known examples of collections frameworks are the C++ Standard Template Library (STL) and Smalltalk's collection hierarchy. Historically, collections frameworks have been quite complex, which gave them a reputation for having a steep learning curve. We believe that the Java Collections Framework breaks with this tradition, as you will learn for yourself in this chapter.

Benefits of the Java Collections Framework

The Java Collections Framework provides the following benefits:
  • Reduces programming effort: By providing useful data structures and algorithms, the Collections Framework frees you to concentrate on the important parts of your program rather than on the low-level "plumbing" required to make it work. By facilitating interoperability among unrelated APIs, the Java Collections Framework frees you from writing adapter objects or conversion code to connect APIs.
  • Increases program speed and quality: This Collections Framework provides high-performance, high-quality implementations of useful data structures and algorithms. The various implementations of each interface are interchangeable, so programs can be easily tuned by switching collection implementations. Because you're freed from the drudgery of writing your own data structures, you'll have more time to devote to improving programs' quality and performance.
  • Allows interoperability among unrelated APIs: The collection interfaces are the vernacular by which APIs pass collections back and forth. If my network administration API furnishes a collection of node names and if your GUI toolkit expects a collection of column headings, our APIs will interoperate seamlessly, even though they were written independently.
  • Reduces effort to learn and to use new APIs: Many APIs naturally take collections on input and furnish them as output. In the past, each such API had a small sub-API devoted to manipulating its collections. There was little consistency among these ad hoc collections sub-APIs, so you had to learn each one from scratch, and it was easy to make mistakes when using them. With the advent of standard collection interfaces, the problem went away.
  • Reduces effort to design new APIs: This is the flip side of the previous advantage. Designers and implementers don't have to reinvent the wheel each time they create an API that relies on collections; instead, they can use standard collection interfaces.
  • Fosters software reuse: New data structures that conform to the standard collection interfaces are by nature reusable. The same goes for new algorithms that operate on objects that implement these interfaces.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: Interfaces


Lesson: Interfaces (The Java™ Tutorials > Collections)

Interfaces
The Collection Interface
The Set Interface
The List Interface
The Queue Interface
The Map Interface
Object Ordering
The SortedSet Interface
The SortedMap Interface
Summary of Interfaces
Questions and Exercises
Trail: Collections
Home Page > Collections
« Previous • Trail • Next »
Lesson: Interfaces
The core collection interfaces encapsulate different types of collections, which are shown in the figure below. These interfaces allow collections to be manipulated independently of the details of their representation. Core collection interfaces are the foundation of the Java Collections Framework. As you can see in the following figure, the core collection interfaces form a hierarchy.

Two interface trees, one starting with Collection and including Set, SortedSet, List, and Queue, and the other starting with Map and including SortedMap.

The core collection interfaces.

A Set is a special kind of Collection, a SortedSet is a special kind of Set, and so forth. Note also that the hierarchy consists of two distinct trees — a Map is not a true Collection.

Note that all the core collection interfaces are generic. For example, this is the declaration of the Collection interface.

public interface Collection<E>...

The <E> syntax tells you that the interface is generic. When you declare a Collection instance you can and should specify the type of object contained in the collection. Specifying the type allows the compiler to verify (at compile-time) that the type of object you put into the collection is correct, thus reducing errors at runtime. For information on generic types, see the Generics lesson.

When you understand how to use these interfaces, you will know most of what there is to know about the Java Collections Framework. This chapter discusses general guidelines for effective use of the interfaces, including when to use which interface. You'll also learn programming idioms for each interface to help you get the most out of it.

To keep the number of core collection interfaces manageable, the Java platform doesn't provide separate interfaces for each variant of each collection type. (Such variants might include immutable, fixed-size, and append-only.) Instead, the modification operations in each interface are designated optional — a given implementation may elect not to support all operations. If an unsupported operation is invoked, a collection throws an UnsupportedOperationException. Implementations are responsible for documenting which of the optional operations they support. All of the Java platform's general-purpose implementations support all of the optional operations.

The following list describes the core collection interfaces:

  • Collection — the root of the collection hierarchy. A collection represents a group of objects known as its elements. The Collection interface is the least common denominator that all collections implement and is used to pass collections around and to manipulate them when maximum generality is desired. Some types of collections allow duplicate elements, and others do not. Some are ordered and others are unordered. The Java platform doesn't provide any direct implementations of this interface but provides implementations of more specific subinterfaces, such as Set and List. Also see The Collection Interface section.

  • Set — a collection that cannot contain duplicate elements. This interface models the mathematical set abstraction and is used to represent sets, such as the cards comprising a poker hand, the courses making up a student's schedule, or the processes running on a machine. See also The Set Interface section.

  • List — an ordered collection (sometimes called a sequence). Lists can contain duplicate elements. The user of a List generally has precise control over where in the list each element is inserted and can access elements by their integer index (position). If you've used Vector, you're familiar with the general flavor of List. Also see The List Interface section.

  • Queue — a collection used to hold multiple elements prior to processing. Besides basic Collection operations, a Queue provides additional insertion, extraction, and inspection operations.

    Queues typically, but do not necessarily, order elements in a FIFO (first-in, first-out) manner. Among the exceptions are priority queues, which order elements according to a supplied comparator or the elements' natural ordering. Whatever the ordering used, the head of the queue is the element that would be removed by a call to remove or poll. In a FIFO queue, all new elements are inserted at the tail of the queue. Other kinds of queues may use different placement rules. Every Queue implementation must specify its ordering properties. Also see The Queue Interface section.

  • Map — an object that maps keys to values. A Map cannot contain duplicate keys; each key can map to at most one value. If you've used Hashtable, you're already familiar with the basics of Map. Also see The Map Interface section.
The last two core collection interfaces are merely sorted versions of Set and Map:
  • SortedSet — a Set that maintains its elements in ascending order. Several additional operations are provided to take advantage of the ordering. Sorted sets are used for naturally ordered sets, such as word lists and membership rolls. Also see The SortedSet Interface section.

  • SortedMap — a Map that maintains its mappings in ascending key order. This is the Map analog of SortedSet. Sorted maps are used for naturally ordered collections of key/value pairs, such as dictionaries and telephone directories. Also see The SortedMap Interface section.
To understand how the sorted interfaces maintain the order of their elements, see the Object Ordering section.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: The Collection Interface


The Collection Interface (The Java™ Tutorials > Collections > Interfaces)

Trail: Collections
Lesson: Interfaces
Interfaces
The Collection Interface
The Set Interface
The List Interface
The Queue Interface
The Map Interface
Object Ordering
The SortedSet Interface
The SortedMap Interface
Summary of Interfaces
Questions and Exercises
Home Page > Collections > Interfaces
« Previous • Trail • Next »
The Collection Interface
A Collection represents a group of objects known as its elements. The Collection interface is used to pass around collections of objects where maximum generality is desired. For example, by convention all general-purpose collection implementations have a constructor that takes a Collection argument. This constructor, known as a conversion constructor, initializes the new collection to contain all of the elements in the specified collection, whatever the given collection's subinterface or implementation type. In other words, it allows you to convert the collection's type.

Suppose, for example, that you have a Collection<String> c, which may be a List, a Set, or another kind of Collection. This idiom creates a new ArrayList (an implementation of the List interface), initially containing all the elements in c.

List<String> list = new ArrayList<String>(c);
The following shows the Collection interface.
public interface Collection<E> extends Iterable<E> {
    // Basic operations
    int size();
    boolean isEmpty();
    boolean contains(Object element);
    boolean add(E element);         //optional
    boolean remove(Object element); //optional
    Iterator<E> iterator();

    // Bulk operations
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c); //optional
    boolean removeAll(Collection<?> c);        //optional
    boolean retainAll(Collection<?> c);        //optional
    void clear();                              //optional

    // Array operations
    Object[] toArray();
    <T> T[] toArray(T[] a);
}
The interface does about what you'd expect given that a Collection represents a group of objects. The interface has methods to tell you how many elements are in the collection (size, isEmpty), to check whether a given object is in the collection (contains), to add and remove an element from the collection (add, remove), and to provide an iterator over the collection (iterator).

The add method is defined generally enough so that it makes sense for collections that allow duplicates as well as those that don't. It guarantees that the Collection will contain the specified element after the call completes, and returns true if the Collection changes as a result of the call. Similarly, the remove method is designed to remove a single instance of the specified element from the Collection, assuming that it contains the element to start with, and to return true if the Collection was modified as a result.

Traversing Collections

There are two ways to traverse collections: (1) with the for-each construct and (2) by using Iterators.

for-each Construct

The for-each construct allows you to concisely traverse a collection or array using a for loop — see The for Statement. The following code uses the for-each construct to print out each element of a collection on a separate line.
for (Object o : collection)
    System.out.println(o);

Iterators

 An Iterator is an object that enables you to traverse through a collection and to remove elements from the collection selectively, if desired. You get an Iterator for a collection by calling its iterator method. The following is the Iterator interface.
public interface Iterator<E> {
    boolean hasNext();
    E next();
    void remove(); //optional
}
The hasNext method returns true if the iteration has more elements, and the next method returns the next element in the iteration. The remove method removes the last element that was returned by next from the underlying Collection. The remove method may be called only once per call to next and throws an exception if this rule is violated.

Note that Iterator.remove is the only safe way to modify a collection during iteration; the behavior is unspecified if the underlying collection is modified in any other way while the iteration is in progress.

Use Iterator instead of the for-each construct when you need to:

  • Remove the current element. The for-each construct hides the iterator, so you cannot call remove. Therefore, the for-each construct is not usable for filtering.
  • Iterate over multiple collections in parallel.
The following method shows you how to use an Iterator to filter an arbitrary Collection — that is, traverse the collection removing specific elements.
static void filter(Collection<?> c) {
    for (Iterator<?> it = c.iterator(); it.hasNext(); )
        if (!cond(it.next()))
            it.remove();
}
This simple piece of code is polymorphic, which means that it works for any Collection regardless of implementation. This example demonstrates how easy it is to write a polymorphic algorithm using the Java Collections Framework.

Collection Interface Bulk Operations

Bulk operations perform an operation on an entire Collection. You could implement these shorthand operations using the basic operations, though in most cases such implementations would be less efficient. The following are the bulk operations:
  • containsAll — returns true if the target Collection contains all of the elements in the specified Collection.
  • addAll — adds all of the elements in the specified Collection to the target Collection.
  • removeAll — removes from the target Collection all of its elements that are also contained in the specified Collection.
  • retainAll — removes from the target Collection all its elements that are not also contained in the specified Collection. That is, it retains only those elements in the target Collection that are also contained in the specified Collection.
  • clear — removes all elements from the Collection.
The addAll, removeAll, and retainAll methods all return true if the target Collection was modified in the process of executing the operation.

As a simple example of the power of bulk operations, consider the following idiom to remove all instances of a specified element, e, from a Collection, c.

c.removeAll(Collections.singleton(e));
More specifically, suppose you want to remove all of the null elements from a Collection.
c.removeAll(Collections.singleton(null));
This idiom uses Collections.singleton, which is a static factory method that returns an immutable Set containing only the specified element.

Collection Interface Array Operations

The toArray methods are provided as a bridge between collections and older APIs that expect arrays on input. The array operations allow the contents of a Collection to be translated into an array. The simple form with no arguments creates a new array of Object. The more complex form allows the caller to provide an array or to choose the runtime type of the output array.

For example, suppose that c is a Collection. The following snippet dumps the contents of c into a newly allocated array of Object whose length is identical to the number of elements in c.

Object[] a = c.toArray();
Suppose that c is known to contain only strings (perhaps because c is of type Collection<String>). The following snippet dumps the contents of c into a newly allocated array of String whose length is identical to the number of elements in c.
String[] a = c.toArray(new String[0]);
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Interfaces
Next page: The Set Interface


The Set Interface (The Java™ Tutorials > Collections > Interfaces)

Trail: Collections
Lesson: Interfaces
Interfaces
The Collection Interface
The Set Interface
The List Interface
The Queue Interface
The Map Interface
Object Ordering
The SortedSet Interface
The SortedMap Interface
Summary of Interfaces
Questions and Exercises
Home Page > Collections > Interfaces
« Previous • Trail • Next »
The Set Interface
A Set is a Collection that cannot contain duplicate elements. It models the mathematical set abstraction. The Set interface contains only methods inherited from Collection and adds the restriction that duplicate elements are prohibited. Set also adds a stronger contract on the behavior of the equals and hashCode operations, allowing Set instances to be compared meaningfully even if their implementation types differ. Two Set instances are equal if they contain the same elements.

The following is the Set interface.

public interface Set<E> extends Collection<E> {
    // Basic operations
    int size();
    boolean isEmpty();
    boolean contains(Object element);
    boolean add(E element);         //optional
    boolean remove(Object element); //optional
    Iterator<E> iterator();

    // Bulk operations
    boolean containsAll(Collection<?> c);
    boolean addAll(Collection<? extends E> c); //optional
    boolean removeAll(Collection<?> c);        //optional
    boolean retainAll(Collection<?> c);        //optional
    void clear();                              //optional

    // Array Operations
    Object[] toArray();
    <T> T[] toArray(T[] a);
}
The Java platform contains three general-purpose Set implementations: HashSet, TreeSet, and LinkedHashSet. HashSet, which stores its elements in a hash table, is the best-performing implementation; however it makes no guarantees concerning the order of iteration. TreeSet, which stores its elements in a red-black tree, orders its elements based on their values; it is substantially slower than HashSet. LinkedHashSet, which is implemented as a hash table with a linked list running through it, orders its elements based on the order in which they were inserted into the set (insertion-order). LinkedHashSet spares its clients from the unspecified, generally chaotic ordering provided by HashSet at a cost that is only slightly higher.

Here's a simple but useful Set idiom. Suppose you have a Collection, c, and you want to create another Collection containing the same elements but with all duplicates eliminated. The following one-liner does the trick.

Collection<Type> noDups = new HashSet<Type>(c);
It works by creating a Set (which, by definition, cannot contain a duplicate), initially containing all the elements in c. It uses the standard conversion constructor described in the The Collection Interface section.

Here is a minor variant of this idiom that preserves the order of the original collection while removing duplicate element.

Collection<Type> noDups = new LinkedHashSet<Type>(c);

The following is a generic method that encapsulates the preceding idiom, returning a Set of the same generic type as the one passed.

public static <E> Set<E> removeDups(Collection<E> c) {
    return new LinkedHashSet<E>(c);
}

Set Interface Basic Operations

The size operation returns the number of elements in the Set (its cardinality). The isEmpty method does exactly what you think it would. The add method adds the specified element to the Set if it's not already present and returns a boolean indicating whether the element was added. Similarly, the remove method removes the specified element from the Set if it's present and returns a boolean indicating whether the element was present. The iterator method returns an Iterator over the Set.

The following program takes the words in its argument list and prints out any duplicate words, the number of distinct words, and a list of the words with duplicates eliminated.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.*;

public class FindDups {
    public static void main(String[] args) {
        Set<String> s = new HashSet<String>();
        for (String a : args)
            if (!s.add(a))
                System.out.println("Duplicate detected: " + a);

        System.out.println(s.size() + " distinct words: " + s);
    }
}
Now run the program.
java FindDups i came i saw i left
The following output is produced.
Duplicate detected: i
Duplicate detected: i
4 distinct words: [i, left, saw, came]
Note that the code always refers to the Collection by its interface type (Set) rather than by its implementation type (HashSet). This is a strongly recommended programming practice because it gives you the flexibility to change implementations merely by changing the constructor. If either of the variables used to store a collection or the parameters used to pass it around are declared to be of the Collection's implementation type rather than its interface type, all such variables and parameters must be changed in order to change its implementation type.

Furthermore, there's no guarantee that the resulting program will work. If the program uses any nonstandard operations present in the original implementation type but not in the new one, the program will fail. Referring to collections only by their interface prevents you from using any nonstandard operations.

The implementation type of the Set in the preceding example is HashSet, which makes no guarantees as to the order of the elements in the Set. If you want the program to print the word list in alphabetical order, merely change the Set's implementation type from HashSet to TreeSet. Making this trivial one-line change causes the command line in the previous example to generate the following output.

java FindDups i came i saw i left
Duplicate detected: i
Duplicate detected: i
4 distinct words: [came, i, left, saw]

Set Interface Bulk Operations

Bulk operations are particularly well suited to Sets; when applied, they perform standard set-algebraic operations. Suppose s1 and s2 are sets. Here's what bulk operations do:
  • s1.containsAll(s2) — returns true if s2 is a subset of s1. (s2 is a subset of s1 if set s1 contains all of the elements in s2.)
  • s1.addAll(s2) — transforms s1 into the union of s1 and s2. (The union of two sets is the set containing all of the elements contained in either set.)
  • s1.retainAll(s2) — transforms s1 into the intersection of s1 and s2. (The intersection of two sets is the set containing only the elements common to both sets.)
  • s1.removeAll(s2) — transforms s1 into the (asymmetric) set difference of s1 and s2. (For example, the set difference of s1 minus s2 is the set containing all of the elements found in s1 but not in s2.)
To calculate the union, intersection, or set difference of two sets nondestructively (without modifying either set), the caller must copy one set before calling the appropriate bulk operation. The following are the resulting idioms.
Set<Type> union = new HashSet<Type>(s1);
union.addAll(s2);

Set<Type> intersection = new HashSet<Type>(s1);
intersection.retainAll(s2);

Set<Type> difference = new HashSet<Type>(s1);
difference.removeAll(s2);
The implementation type of the result Set in the preceding idioms is HashSet, which is, as already mentioned, the best all-around Set implementation in the Java platform. However, any general-purpose Set implementation could be substituted.

Let's revisit the FindDups program. Suppose you want to know which words in the argument list occur only once and which occur more than once, but you do not want any duplicates printed out repeatedly. This effect can be achieved by generating two sets — one containing every word in the argument list and the other containing only the duplicates. The words that occur only once are the set difference of these two sets, which we know how to compute. Here's how the resulting program looks.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.*;

public class FindDups2 {
    public static void main(String[] args) {
        Set<String> uniques = new HashSet<String>();
        Set<String> dups    = new HashSet<String>();

        for (String a : args)
            if (!uniques.add(a))
                dups.add(a);

    // Destructive set-difference
        uniques.removeAll(dups);

        System.out.println("Unique words:    " + uniques);
        System.out.println("Duplicate words: " + dups);
    }
}
When run with the same argument list used earlier (i came i saw i left), the program yields the following output.
Unique words:    [left, saw, came]
Duplicate words: [i]
A less common set-algebraic operation is the symmetric set difference — the set of elements contained in either of two specified sets but not in both. The following code calculates the symmetric set difference of two sets nondestructively.
Set<Type> symmetricDiff = new HashSet<Type>(s1);
symmetricDiff.addAll(s2);
Set<Type> tmp = new HashSet<Type>(s1);
tmp.retainAll(s2));
symmetricDiff.removeAll(tmp);

Set Interface Array Operations

The array operations don't do anything special for Sets beyond what they do for any other Collection. These operations are described in The Collection Interface section.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Collection Interface
Next page: The List Interface


The List Interface (The Java™ Tutorials > Collections > Interfaces)

Trail: Collections
Lesson: Interfaces
Interfaces
The Collection Interface
The Set Interface
The List Interface
The Queue Interface
The Map Interface
Object Ordering
The SortedSet Interface
The SortedMap Interface
Summary of Interfaces
Questions and Exercises
Home Page > Collections > Interfaces
« Previous • Trail • Next »
The List Interface
A List is an ordered Collection (sometimes called a sequence). Lists may contain duplicate elements. In addition to the operations inherited from Collection, the List interface includes operations for the following:
  • Positional access — manipulates elements based on their numerical position in the list
  • Search — searches for a specified object in the list and returns its numerical position
  • Iteration — extends Iterator semantics to take advantage of the list's sequential nature
  • Range-view — performs arbitrary range operations on the list.

The List interface follows.

public interface List<E> extends Collection<E> {
    // Positional access
    E get(int index);
    E set(int index, E element);    //optional
    boolean add(E element);         //optional
    void add(int index, E element); //optional
    E remove(int index);            //optional
    boolean addAll(int index,
        Collection<? extends E> c); //optional

    // Search
    int indexOf(Object o);
    int lastIndexOf(Object o);

    // Iteration
    ListIterator<E> listIterator();
    ListIterator<E> listIterator(int index);

    // Range-view
    List<E> subList(int from, int to);
}
The Java platform contains two general-purpose List implementations. ArrayList, which is usually the better-performing implementation, and LinkedList which offers better performance under certain circumstances. Also, Vector has been retrofitted to implement List.

Comparison to Vector

If you've used Vector, you're already familiar with the general basics of List. (Of course, List is an interface, while Vector is a concrete implementation.) List fixes several minor API deficiencies in Vector. Commonly used Vector operations, such as elementAt and setElementAt, have been given much shorter names. When you consider that these two operations are the List analog of square brackets for arrays, it becomes apparent that shorter names are highly desirable. Consider the following assignment statement.
a[i] = a[j].times(a[k]);
The Vector equivalent is:
v.setElementAt(v.elementAt(j).times(v.elementAt(k)), i);
The List equivalent is:
v.set(i, v.get(j).times(v.get(k)));
You may already have noticed that the set method, which replaces the Vector method setElementAt, reverses the order of the arguments so that they match the corresponding array operation. Consider the following assignment statement.
gift[5] = "golden rings";
The Vector equivalent is:
gift.setElementAt("golden rings", 5);
The List equivalent is:
gift.set(5, "golden rings");
For consistency's sake, the method add(int, E), which replaces insertElementAt(Object, int), also reverses the order of the arguments.

The three range operations in Vector (indexOf, lastIndexOf, and setSize) have been replaced by a single range-view operation (subList), which is far more powerful and consistent.

Collection Operations

The operations inherited from Collection all do about what you'd expect them to do, assuming you're already familiar with them. If you're not familiar with them from Collection, now would be a good time to read The Collection Interface section. The remove operation always removes the first occurrence of the specified element from the list. The add and addAll operations always append the new element(s) to the end of the list. Thus, the following idiom concatenates one list to another.
list1.addAll(list2);
Here's a nondestructive form of this idiom, which produces a third List consisting of the second list appended to the first.
List<Type> list3 = new ArrayList<Type>(list1);
list3.addAll(list2);
Note that the idiom, in its nondestructive form, takes advantage of ArrayList's standard conversion constructor.

Like the Set interface, List strengthens the requirements on the equals and hashCode methods so that two List objects can be compared for logical equality without regard to their implementation classes. Two List objects are equal if they contain the same elements in the same order.

Positional Access and Search Operations

The basic positional access operations (get, set, add and remove) behave just like their longer-named counterparts in Vector (elementAt, setElementAt, insertElementAt, and removeElementAt) with one noteworthy exception: The set and remove operations return the old value that is being overwritten or removed; the Vector counterparts (setElementAt and removeElementAt) return nothing (void). The search operations indexOf and lastIndexOf behave exactly like the identically named operations in Vector.

The addAll operation inserts all the elements of the specified Collection starting at the specified position. The elements are inserted in the order they are returned by the specified Collection's iterator. This call is the positional access analog of Collection's addAll operation.

Here's a little method to swap two indexed values in a List. It should look familiar from Programming 101.

public static <E> void swap(List<E> a, int i, int j) {
    E tmp = a.get(i);
    a.set(i, a.get(j));
    a.set(j, tmp);
}
Of course, there's one big difference. This is a polymorphic algorithm: It swaps two elements in any List, regardless of its implementation type. Here's another polymorphic algorithm that uses the preceding swap method.
public static void shuffle(List<?> list, Random rnd) {
    for (int i = list.size(); i > 1; i--)
        swap(list, i - 1, rnd.nextInt(i));
}
This algorithm, which is included in the Java platform's Collections class, randomly permutes the specified list using the specified source of randomness. It's a bit subtle: It runs up the list from the bottom, repeatedly swapping a randomly selected element into the current position. Unlike most naive attempts at shuffling, it's fair (all permutations occur with equal likelihood, assuming an unbiased source of randomness) and fast (requiring exactly list.size()-1 swaps). The following program uses this algorithm to print the words in its argument list in random order.
import java.util.*;

public class Shuffle {
    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();
        for (String a : args)
            list.add(a);
        Collections.shuffle(list, new Random());
        System.out.println(list);
    }
}
In fact, this program can be made even shorter and faster. The Arrays class has a static factory method called asList, which allows an array to be viewed as a List. This method does not copy the array. Changes in the List write through to the array and vice versa. The resulting List is not a general-purpose List implementation, because it doesn't implement the (optional) add and remove operations: Arrays are not resizable. Taking advantage of Arrays.asList and calling the library version of shuffle, which uses a default source of randomness, you get the following tiny program whose behavior is identical to the previous program.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.*;

public class Shuffle {
    public static void main(String[] args) {
        List<String> list = Arrays.asList(args);
        Collections.shuffle(list);
        System.out.println(list);
    }
}

Iterators
As you'd expect, the Iterator returned by List's iterator operation returns the elements of the list in proper sequence. List also provides a richer iterator, called a ListIterator, which allows you to traverse the list in either direction, modify the list during iteration, and obtain the current position of the iterator. The ListIterator interface follows.
public interface ListIterator<E> extends Iterator<E> {
    boolean hasNext();
    E next();
    boolean hasPrevious();
    E previous();
    int nextIndex();
    int previousIndex();
    void remove(); //optional
    void set(E e); //optional
    void add(E e); //optional
}
The three methods that ListIterator inherits from Iterator (hasNext, next, and remove) do exactly the same thing in both interfaces. The hasPrevious and the previous operations are exact analogues of hasNext and next. The former operations refer to the element before the (implicit) cursor, whereas the latter refer to the element after the cursor. The previous operation moves the cursor backward, whereas next moves it forward.

Here's the standard idiom for iterating backward through a list.

for (ListIterator<Type> it = list.listIterator(list.size());
     it.hasPrevious(); ) {
    Type t = it.previous();
    ...
}
Note the argument to listIterator in the preceding idiom. The List interface has two forms of the listIterator method. The form with no arguments returns a ListIterator positioned at the beginning of the list; the form with an int argument returns a ListIterator positioned at the specified index. The index refers to the element that would be returned by an initial call to next. An initial call to previous would return the element whose index was index-1. In a list of length n, there are n+1 valid values for index, from 0 to n, inclusive.

Intuitively speaking, the cursor is always between two elements — the one that would be returned by a call to previous and the one that would be returned by a call to next. The n+1 valid index values correspond to the n+1 gaps between elements, from the gap before the first element to the gap after the last one. The following figure shows the five possible cursor positions in a list containing four elements.

Five arrows representing five cursor positions, from 0 to 4, with four elements, one between each arrow.

The five possible cursor positions.

Calls to next and previous can be intermixed, but you have to be a bit careful. The first call to previous returns the same element as the last call to next. Similarly, the first call to next after a sequence of calls to previous returns the same element as the last call to previous.

It should come as no surprise that the nextIndex method returns the index of the element that would be returned by a subsequent call to next, and previousIndex returns the index of the element that would be returned by a subsequent call to previous. These calls are typically used either to report the position where something was found or to record the position of the ListIterator so that another ListIterator with identical position can be created.

It should also come as no surprise that the number returned by nextIndex is always one greater than the number returned by previousIndex. This implies the behavior of the two boundary cases: (1) a call to previousIndex when the cursor is before the initial element returns -1 and (2) a call to nextIndex when the cursor is after the final element returns list.size(). To make all this concrete, the following is a possible implementation of List.indexOf.

public int indexOf(E e) {
    for (ListIterator<E> it = listIterator(); it.hasNext(); )
        if (e == null ? it.next() == null : e.equals(it.next()))
            return it.previousIndex();
    return -1;  // Element not found
}
Note that the indexOf method returns it.previousIndex() even though it is traversing the list in the forward direction. The reason is that it.nextIndex() would return the index of the element we are about to examine, and we want to return the index of the element we just examined.

The Iterator interface provides the remove operation to remove the last element returned by next from the Collection. For ListIterator, this operation removes the last element returned by next or previous. The ListIterator interface provides two additional operations to modify the list — set and add. The set method overwrites the last element returned by next or previous with the specified element. The following polymorphic algorithm uses set to replace all occurrences of one specified value with another.

public static <E> void replace(List<E> list, E val, E newVal) {
    for (ListIterator<E> it = list.listIterator(); it.hasNext(); )
        if (val == null ? it.next() == null : val.equals(it.next()))
            it.set(newVal);
}
The only bit of trickiness in this example is the equality test between val and it.next. You need to special-case a val value of null to prevent a NullPointerException.

The add method inserts a new element into the list immediately before the current cursor position. This method is illustrated in the following polymorphic algorithm to replace all occurrences of a specified value with the sequence of values contained in the specified list.

public static <E> void replace(List<E> list, E val,
                               List<? extends E> newVals) {
    for (ListIterator<E> it = list.listIterator(); it.hasNext(); ){
        if (val == null ? it.next() == null : val.equals(it.next())) {
            it.remove();
            for (E e : newVals)
                it.add(e);
        }
    }
}

Range-View Operation

The range-view operation, subList(int fromIndex, int toIndex), returns a List view of the portion of this list whose indices range from fromIndex, inclusive, to toIndex, exclusive. This half-open range mirrors the typical for loop.
for (int i = fromIndex; i < toIndex; i++) {
    ...
}
As the term view implies, the returned List is backed up by the List on which subList was called, so changes in the former are reflected in the latter.

This method eliminates the need for explicit range operations (of the sort that commonly exist for arrays). Any operation that expects a List can be used as a range operation by passing a subList view instead of a whole List. For example, the following idiom removes a range of elements from a List.

list.subList(fromIndex, toIndex).clear();
Similar idioms can be constructed to search for an element in a range.
int i = list.subList(fromIndex, toIndex).indexOf(o);
int j = list.subList(fromIndex, toIndex).lastIndexOf(o);
Note that the preceding idioms return the index of the found element in the subList, not the index in the backing List.

Any polymorphic algorithm that operates on a List, such as the replace and shuffle examples, works with the List returned by subList.

Here's a polymorphic algorithm whose implementation uses subList to deal a hand from a deck. That is, it returns a new List (the "hand") containing the specified number of elements taken from the end of the specified List (the "deck"). The elements returned in the hand are removed from the deck.

public static <E> List<E> dealHand(List<E> deck, int n) {
    int deckSize = deck.size();
    List<E> handView = deck.subList(deckSize - n, deckSize);
    List<E> hand = new ArrayList<E>(handView);
    handView.clear();
    return hand;
}
Note that this algorithm removes the hand from the end of the deck. For many common List implementations, such as ArrayList, the performance of removing elements from the end of the list is substantially better than that of removing elements from the beginning.

The following is a program that uses the dealHand method in combination with Collections.shuffle to generate hands from a normal 52-card deck. The program takes two command-line arguments: (1) the number of hands to deal and (2) the number of cards in each hand.

import java.util.*;

class Deal {
    public static void main(String[] args) {
        int numHands = Integer.parseInt(args[0]);
        int cardsPerHand = Integer.parseInt(args[1]);

        // Make a normal 52-card deck.
        String[] suit = new String[]
            {"spades", "hearts", "diamonds", "clubs"};
        String[] rank = new String[]
            {"ace","2","3","4","5","6","7","8",
             "9","10","jack","queen","king"};
        List<String> deck = new ArrayList<String>();
        for (int i = 0; i < suit.length; i++)
            for (int j = 0; j < rank.length; j++)
                deck.add(rank[j] + " of " + suit[i]);

        Collections.shuffle(deck);

        for (int i=0; i < numHands; i++)
            System.out.println(dealHand(deck, cardsPerHand));
    }
}
Running the program produces the following output.
% java Deal 4 5

[8 of hearts, jack of spades, 3 of spades, 4 of spades,
    king of diamonds]
[4 of diamonds, ace of clubs, 6 of clubs, jack of hearts,
    queen of hearts]
[7 of spades, 5 of spades, 2 of diamonds, queen of diamonds,
    9 of clubs]
[8 of spades, 6 of diamonds, ace of spades, 3 of hearts,
    ace of hearts]

Although the subList operation is extremely powerful, some care must be exercised when using it. The semantics of the List returned by subList become undefined if elements are added to or removed from the backing List in any way other than via the returned List. Thus, it's highly recommended that you use the List returned by subList only as a transient object — to perform one or a sequence of range operations on the backing List. The longer you use the subList instance, the greater the probability that you'll compromise it by modifying the backing List directly or through another subList object. Note that it is legal to modify a sublist of a sublist and to continue using the original sublist (though not concurrently).

List Algorithms

Most polymorphic algorithms in the Collections class apply specifically to List. Having all these algorithms at your disposal makes it very easy to manipulate lists. Here's a summary of these algorithms, which are described in more detail in the Algorithms section.
  • sort — sorts a List using a merge sort algorithm, which provides a fast, stable sort. (A stable sort is one that does not reorder equal elements.)
  • shuffle — randomly permutes the elements in a List.
  • reverse — reverses the order of the elements in a List.
  • rotate — rotates all the elements in a List by a specified distance.
  • swap — swaps the elements at specified positions in a List.
  • replaceAll — replaces all occurrences of one specified value with another.
  • fill — overwrites every element in a List with the specified value.
  • copy — copies the source List into the destination List.
  • binarySearch — searches for an element in an ordered List using the binary search algorithm.
  • indexOfSubList — returns the index of the first sublist of one List that is equal to another.
  • lastIndexOfSubList — returns the index of the last sublist of one List that is equal to another.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Set Interface
Next page: The Queue Interface


The Queue Interface (The Java™ Tutorials > Collections > Interfaces)

Trail: Collections
Lesson: Interfaces
Interfaces
The Collection Interface
The Set Interface
The List Interface
The Queue Interface
The Map Interface
Object Ordering
The SortedSet Interface
The SortedMap Interface
Summary of Interfaces
Questions and Exercises
Home Page > Collections > Interfaces
« Previous • Trail • Next »
The Queue Interface
A Queue is a collection for holding elements prior to processing. Besides basic Collection operations, queues provide additional insertion, removal, and inspection operations. The Queue interface follows.
public interface Queue<E> extends Collection<E> {
    E element();
    boolean offer(E e);
    E peek();
    E poll();
    E remove();
}
Each Queue method exists in two forms: (1) one throws an exception if the operation fails, and (2) the other returns a special value if the operation fails (either null or false, depending on the operation). The regular structure of the interface is illustrated in the following table.
Queue Interface Structure
Throws exception | Returns special value
Insert | add(e) | offer(e)
Remove | remove() | poll()
Examine | element() | peek()

Queues typically, but not necessarily, order elements in a FIFO (first-in-first-out) manner. Among the exceptions are priority queues, which order elements according to their values — see the Object Ordering section for details). Whatever ordering is used, the head of the queue is the element that would be removed by a call to remove or poll. In a FIFO queue, all new elements are inserted at the tail of the queue. Other kinds of queues may use different placement rules. Every Queue implementation must specify its ordering properties.

It is possible for a Queue implementation to restrict the number of elements that it holds; such queues are known as bounded. Some Queue implementations in java.util.concurrent are bounded, but the implementations in java.util are not.

The add method, which Queue inherits from Collection, inserts an element unless it would violate the queue's capacity restrictions, in which case it throws IllegalStateException. The offer method, which is intended solely for use on bounded queues, differs from add only in that it indicates failure to insert an element by returning false.

The remove and poll methods both remove and return the head of the queue. Exactly which element gets removed is a function of the queue's ordering policy. The remove and poll methods differ in their behavior only when the queue is empty. Under these circumstances, remove throws NoSuchElementException, while poll returns null.

The element and peek methods return, but do not remove, the head of the queue. They differ from one another in precisely the same fashion as remove and poll: If the queue is empty, element throws NoSuchElementException, while peek returns null.

Queue implementations generally do not allow insertion of null elements. The LinkedList implementation, which was retrofitted to implement Queue, is an exception. For historical reasons, it permits null elements, but you should refrain from taking advantage of this, because null is used as a special return value by the poll and peek methods.

Queue implementations generally do not define element-based versions of the equals and hashCode methods but instead inherit the identity-based versions from Object.

The Queue interface does not define the blocking queue methods, which are common in concurrent programming. These methods, which wait for elements to appear or for space to become available, are defined in the interface java.util.concurrent.BlockingQueue, which extends Queue.

In the following example program, a queue is used to implement a countdown timer. The queue is preloaded with all the integer values from a number specified on the command line to zero, in descending order. Then, the values are removed from the queue and printed at one-second intervals. The program is artificial in that it would be more natural to do the same thing without using a queue, but it illustrates the use of a queue to store elements prior to subsequent processing.

import java.util.*;

public class Countdown {
    public static void main(String[] args)
            throws InterruptedException {
        int time = Integer.parseInt(args[0]);
        Queue<Integer> queue = new LinkedList<Integer>();
        for (int i = time; i >= 0; i--)
            queue.add(i);
        while (!queue.isEmpty()) {
            System.out.println(queue.remove());
            Thread.sleep(1000);
        }
    }
}
In the following example, a priority queue is used to sort a collection of elements. Again this program is artificial in that there is no reason to use it in favor of the sort method provided in Collections, but it illustrates the behavior of priority queues.
static <E> List<E> heapSort(Collection<E> c) {
    Queue<E> queue = new PriorityQueue<E>(c);
    List<E> result = new ArrayList<E>();
    while (!queue.isEmpty())
        result.add(queue.remove());
    return result;
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The List Interface
Next page: The Map Interface


The Map Interface (The Java™ Tutorials > Collections > Interfaces)

Trail: Collections
Lesson: Interfaces
Interfaces
The Collection Interface
The Set Interface
The List Interface
The Queue Interface
The Map Interface
Object Ordering
The SortedSet Interface
The SortedMap Interface
Summary of Interfaces
Questions and Exercises
Home Page > Collections > Interfaces
« Previous • Trail • Next »
The Map Interface
A Map is an object that maps keys to values. A map cannot contain duplicate keys: Each key can map to at most one value. It models the mathematical function abstraction. The Map interface follows.
public interface Map<K,V> {

    // Basic operations
    V put(K key, V value);
    V get(Object key);
    V remove(Object key);
    boolean containsKey(Object key);
    boolean containsValue(Object value);
    int size();
    boolean isEmpty();

    // Bulk operations
    void putAll(Map<? extends K, ? extends V> m);
    void clear();

    // Collection Views
    public Set<K> keySet();
    public Collection<V> values();
    public Set<Map.Entry<K,V>> entrySet();

    // Interface for entrySet elements
    public interface Entry {
        K getKey();
        V getValue();
        V setValue(V value);
    }
}
The Java platform contains three general-purpose Map implementations: HashMap, TreeMap, and LinkedHashMap. Their behavior and performance are precisely analogous to HashSet, TreeSet, and LinkedHashSet, as described in The Set Interface section. Also, Hashtable was retrofitted to implement Map.

Comparison to Hashtable

If you've used Hashtable, you're already familiar with the general basics of Map. (Of course, Map is an interface, while Hashtable is a concrete implementation.) The following are the major differences:
  • Map provides Collection views instead of direct support for iteration via Enumeration objects. Collection views greatly enhance the expressiveness of the interface, as discussed later in this section.
  • Map allows you to iterate over keys, values, or key-value pairs; Hashtable does not provide the third option.
  • Map provides a safe way to remove entries in the midst of iteration; Hashtable did not.
Finally, Map fixes a minor deficiency in the Hashtable interface. Hashtable has a method called contains, which returns true if the Hashtable contains a given value. Given its name, you'd expect this method to return true if the Hashtable contained a given key, because the key is the primary access mechanism for a Hashtable. The Map interface eliminates this source of confusion by renaming the method containsValue. Also, this improves the interface's consistency — containsValue parallels containsKey.

Map Interface Basic Operations

The basic operations of Map (put, get, containsKey, containsValue, size, and isEmpty) behave exactly like their counterparts in Hashtable. The following program generates a frequency table of the words found in its argument list. The frequency table maps each word to the number of times it occurs in the argument list.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.*;

public class Freq {
    public static void main(String[] args) {
        Map<String, Integer> m = new HashMap<String, Integer>();

        // Initialize frequency table from command line
        for (String a : args) {
            Integer freq = m.get(a);
            m.put(a, (freq == null) ? 1 : freq + 1);
        }

        System.out.println(m.size() + " distinct words:");
        System.out.println(m);
    }
}
The only tricky thing about this program is the second argument of the put statement. That argument is a conditional expression that has the effect of setting the frequency to one if the word has never been seen before or one more than its current value if the word has already been seen. Try running this program with the command:
java Freq if it is to be it is up to me to delegate
The program yields the following output.
8 distinct words:
{to=3, delegate=1, be=1, it=2, up=1, if=1, me=1, is=2}
Suppose you'd prefer to see the frequency table in alphabetical order. All you have to do is change the implementation type of the Map from HashMap to TreeMap. Making this four-character change causes the program to generate the following output from the same command line.
8 distinct words:
{be=1, delegate=1, if=1, is=2, it=2, me=1, to=3, up=1}
Similarly, you could make the program print the frequency table in the order the words first appear on the command line simply by changing the implementation type of the map to LinkedHashMap. Doing so results in the following output.
8 distinct words:
{if=1, it=2, is=2, to=3, be=1, up=1, me=1, delegate=1}
This flexibility provides a potent illustration of the power of an interface-based framework.

Like the Setand Listinterfaces, Map strengthens the requirements on the equals and hashCode methods so that two Map objects can be compared for logical equality without regard to their implementation types. Two Map instances are equal if they represent the same key-value mappings.

By convention, all general-purpose Map implementations provide constructors that take a Map object and initialize the new Map to contain all the key-value mappings in the specified Map. This standard Map conversion constructor is entirely analogous to the standard Collection constructor: It allows the caller to create a Map of a desired implementation type that initially contains all of the mappings in another Map, regardless of the other Map's implementation type. For example, suppose you have a Map, named m. The following one-liner creates a new HashMap initially containing all of the same key-value mappings as m.

Map<K, V> copy = new HashMap<K, V>(m);

Map Interface Bulk Operations

The clear operation does exactly what you would think it could do: It removes all the mappings from the Map. The putAll operation is the Map analogue of the Collection interface's addAll operation. In addition to its obvious use of dumping one Map into another, it has a second, more subtle use. Suppose a Map is used to represent a collection of attribute-value pairs; the putAll operation, in combination with the Map conversion constructor, provides a neat way to implement attribute map creation with default values. The following is a static factory method that demonstrates this technique.
static <K, V> Map<K, V> newAttributeMap(
        Map<K, V>defaults, Map<K, V> overrides) {
    Map<K, V> result = new HashMap<K, V>(defaults);
    result.putAll(overrides);
    return result;
}

Collection Views

The Collection view methods allow a Map to be viewed as a Collection in these three ways:
  • keySet — the Set of keys contained in the Map.
  • values — The Collection of values contained in the Map. This Collection is not a Set, because multiple keys can map to the same value.
  • entrySet — the Set of key-value pairs contained in the Map. The Map interface provides a small nested interface called Map.Entry, the type of the elements in this Set.
The Collection views provide the only means to iterate over a Map. This example illustrates the standard idiom for iterating over the keys in a Map with a for-each construct:
for (KeyType key : m.keySet())
    System.out.println(key);
and with an iterator:
// Filter a map based on some property of its keys.
for (Iterator<Type> it = m.keySet().iterator(); it.hasNext(); )
    if (it.next().isBogus())
        it.remove();
The idiom for iterating over values is analogous. Following is the idiom for iterating over key-value pairs.
for (Map.Entry<KeyType, ValType> e : m.entrySet())
    System.out.println(e.getKey() + ": " + e.getValue());

At first, many people worry that these idioms may be slow because the Map has to create a new Collection instance each time a Collection view operation is called. Rest easy: There's no reason that a Map cannot always return the same object each time it is asked for a given Collection view. This is precisely what all the Map implementations in java.util do.

With all three Collection views, calling an Iterator's remove operation removes the associated entry from the backing Map, assuming that the backing Map supports element removal to begin with. This is illustrated by the preceding filtering idiom.

With the entrySet view, it is also possible to change the value associated with a key by calling a Map.Entry's setValue method during iteration (again, assuming the Map supports value modification to begin with). Note that these are the only safe ways to modify a Map during iteration; the behavior is unspecified if the underlying Map is modified in any other way while the iteration is in progress.

The Collection views support element removal in all its many forms — remove, removeAll, retainAll, and clear operations, as well as the Iterator.remove operation. (Yet again, this assumes that the backing Map supports element removal.)

The Collection views do not support element addition under any circumstances. It would make no sense for the keySet and values views, and it's unnecessary for the entrySet view, because the backing Map's put and putAll methods provide the same functionality.

Fancy Uses of Collection Views: Map Algebra

When applied to the Collection views, bulk operations (containsAll, removeAll, and retainAll) are surprisingly potent tools. For starters, suppose you want to know whether one Map is a submap of another — that is, whether the first Map contains all the key-value mappings in the second. The following idiom does the trick.
if (m1.entrySet().containsAll(m2.entrySet())) {
    ...
}
Along similar lines, suppose you want to know whether two Map objects contain mappings for all of the same keys.
if (m1.keySet().equals(m2.keySet())) {
    ...
}
Suppose you have a Map that represents a collection of attribute-value pairs, and two Sets representing required attributes and permissible attributes. (The permissible attributes include the required attributes.) The following snippet determines whether the attribute map conforms to these constraints and prints a detailed error message if it doesn't.
static <K, V> boolean validate(Map<K, V> attrMap,
        Set<K> requiredAttrs, Set<K>permittedAttrs) {
    boolean valid = true;
    Set<K> attrs = attrMap.keySet();
    if(!attrs.containsAll(requiredAttrs)) {
        Set<K> missing = new HashSet<K>(requiredAttrs);
        missing.removeAll(attrs);
        System.out.println("Missing attributes: " + missing);
        valid = false;
    }
    if (!permittedAttrs.containsAll(attrs)) {
        Set<K> illegal = new HashSet<K>(attrs);
        illegal.removeAll(permittedAttrs);
        System.out.println("Illegal attributes: " + illegal);
        valid = false;
    }
    return valid;
}
Suppose you want to know all the keys common to two Map objects.
Set<KeyType>commonKeys = new HashSet<KeyType>(m1.keySet());
commonKeys.retainAll(m2.keySet());
A similar idiom gets you the common values.

All the idioms presented thus far have been nondestructive; that is, they don't modify the backing Map. Here are a few that do. Suppose you want to remove all of the key-value pairs that one Map has in common with another.

m1.entrySet().removeAll(m2.entrySet());
Suppose you want to remove from one Map all of the keys that have mappings in another.
m1.keySet().removeAll(m2.keySet());
What happens when you start mixing keys and values in the same bulk operation? Suppose you have a Map, managers, that maps each employee in a company to the employee's manager. We'll be deliberately vague about the types of the key and the value objects. It doesn't matter, as long as they're the same. Now suppose you want to know who all the "individual contributors" (or nonmanagers) are. The following snippet tells you exactly what you want to know.
Set<Employee> individualContributors =
    new HashSet<Employee>(managers.keySet());
individualContributors.removeAll(managers.values());
Suppose you want to fire all the employees who report directly to some manager, Simon.
Employee simon = ... ;
managers.values().removeAll(Collections.singleton(simon));
Note that this idiom makes use of Collections.singleton, a static factory method that returns an immutable Set with the single, specified element.

Once you've done this, you may have a bunch of employees whose managers no longer work for the company (if any of Simon's direct-reports were themselves managers). The following code will tell you which employees have managers who no longer works for the company.

Map<Employee, Employee> m =
    new HashMap<Employee, Employee>(managers);
m.values().removeAll(managers.keySet());
Set<Employee> slackers = m.keySet();
This example is a bit tricky. First, it makes a temporary copy of the Map, and it removes from the temporary copy all entries whose (manager) value is a key in the original Map. Remember that the original Map has an entry for each employee. Thus, the remaining entries in the temporary Map comprise all the entries from the original Map whose (manager) values are no longer employees. The keys in the temporary copy, then, represent precisely the employees that we're looking for.

There are many more idioms like the ones contained in this section, but it would be impractical and tedious to list them all. Once you get the hang of it, it's not that difficult to come up with the right one when you need it.

Multimaps

A multimap is like a Map but it can map each key to multiple values. The Java Collections Framework doesn't include an interface for multimaps because they aren't used all that commonly. It's a fairly simple matter to use a Map whose values are List instances as a multimap. This technique is demonstrated in the next code example, which reads a word list containing one word per line (all lowercase) and prints out all the anagram groups that meet a size criterion. An anagram group is a bunch of words, all of which contain exactly the same letters but in a different order. The program takes two arguments on the command line: (1) the name of the dictionary file and (2) the minimum size of anagram group to print out. Anagram groups containing fewer words than the specified minimum are not printed.

There is a standard trick for finding anagram groups: For each word in the dictionary, alphabetize the letters in the word (that is, reorder the word's letters into alphabetical order) and put an entry into a multimap, mapping the alphabetized word to the original word. For example, the word bad causes an entry mapping abd into bad to be put into the multimap. A moment's reflection will show that all the words to which any given key maps form an anagram group. It's a simple matter to iterate over the keys in the multimap, printing out each anagram group that meets the size constraint.

The following program is a straightforward implementation of this technique.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.*;
import java.io.*;

public class Anagrams {
    public static void main(String[] args) {
        int minGroupSize = Integer.parseInt(args[1]);

        // Read words from file and put into a simulated multimap
        Map<String, List<String>> m
        = new HashMap<String, List<String>>();
        try {
        Scanner s = new Scanner(new File(args[0]));
            while (s.hasNext()) {
        String word = s.next();
                String alpha = alphabetize(word);
                List<String> l = m.get(alpha);
                if (l == null)
                    m.put(alpha, l=new ArrayList<String>());
                l.add(word);
            }
        } catch (IOException e) {
            System.err.println(e);
            System.exit(1);
        }

        // Print all permutation groups above size threshold
        for (List<String> l : m.values())
            if (l.size() >= minGroupSize)
                System.out.println(l.size() + ": " + l);
    }

    private static String alphabetize(String s) {
    char[] a = s.toCharArray();
    Arrays.sort(a);
    return new String(a);
    }
}
Running this program on a 173,000-word dictionary file with a minimum anagram group size of eight produces the following output.
9: [estrin, inerts, insert, inters, niters, nitres, sinter,
     triens, trines]
8: [lapse, leaps, pales, peals, pleas, salep, sepal, spale]
8: [aspers, parses, passer, prases, repass, spares, sparse,
     spears]
10: [least, setal, slate, stale, steal, stela, taels, tales,
      teals, tesla]
8: [enters, nester, renest, rentes, resent, tenser, ternes,
     treens]
8: [arles, earls, lares, laser, lears, rales, reals, seral]
8: [earings, erasing, gainers, reagins, regains, reginas,
     searing, seringa]
8: [peris, piers, pries, prise, ripes, speir, spier, spire]
12: [apers, apres, asper, pares, parse, pears, prase, presa,
      rapes, reaps, spare, spear]
11: [alerts, alters, artels, estral, laster, ratels, salter,
      slater, staler, stelar, talers]
9: [capers, crapes, escarp, pacers, parsec, recaps, scrape,
     secpar, spacer]
9: [palest, palets, pastel, petals, plates, pleats, septal,
     staple, tepals]
9: [anestri, antsier, nastier, ratines, retains, retinas,
     retsina, stainer, stearin]
8: [ates, east, eats, etas, sate, seat, seta, teas]
8: [carets, cartes, caster, caters, crates, reacts, recast,
     traces]
Many of these words seem a bit bogus, but that's not the program's fault; they're in the dictionary file. Here's the dictionary file we used. It is derived from the Public Domain ENABLE benchmark reference word list, at http://personal.riverusers.com/~thegrendel/
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Queue Interface
Next page: Object Ordering


Object Ordering (The Java™ Tutorials > Collections > Interfaces)

Trail: Collections
Lesson: Interfaces
Interfaces
The Collection Interface
The Set Interface
The List Interface
The Queue Interface
The Map Interface
Object Ordering
The SortedSet Interface
The SortedMap Interface
Summary of Interfaces
Questions and Exercises
Home Page > Collections > Interfaces
« Previous • Trail • Next »
Object Ordering
A List l may be sorted as follows.
Collections.sort(l);
If the List consists of String elements, it will be sorted into alphabetical order. If it consists of Date elements, it will be sorted into chronological order. How does this happen? String and Date both implement the Comparable interface. Comparable implementations provide a natural ordering for a class, which allows objects of that class to be sorted automatically. The following table summarizes some of the more important Java platform classes that implement Comparable.
Classes Implementing Comparable
Class | Natural Ordering
Byte | Signed numerical
Character | Unsigned numerical
Long | Signed numerical
Integer | Signed numerical
Short | Signed numerical
Double | Signed numerical
Float | Signed numerical
BigInteger | Signed numerical
BigDecimal | Signed numerical
Boolean | Boolean.FALSE < Boolean.TRUE
File | System-dependent lexicographic on path name
String | Lexicographic
Date | Chronological
CollationKey | Locale-specific lexicographic

If you try to sort a list, the elements of which do not implement Comparable, Collections.sort(list) will throw a ClassCastException. Similarly, Collections.sort(list, comparator) will throw a ClassCastException if you try to sort a list whose elements cannot be compared to one another using the comparator. Elements that can be compared to one another are called mutually comparable. Although elements of different types may be mutually comparable, none of the classes listed here permit interclass comparison.

This is all you really need to know about the Comparable interface if you just want to sort lists of comparable elements or to create sorted collections of them. The next section will be of interest to you if you want to implement your own Comparable type.

Writing Your Own Comparable Types

The Comparable interface consists of the following method.
public interface Comparable<T> {
    public int compareTo(T o);
}
The compareTo method compares the receiving object with the specified object and returns a negative integer, 0, or a positive integer depending on whether the receiving object is less than, equal to, or greater than the specified object. If the specified object cannot be compared to the receiving object, the method throws a ClassCastException.

The following class representing a person's name implements Comparable.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.*;

public class Name implements Comparable<Name> {
    private final String firstName, lastName;

    public Name(String firstName, String lastName) {
        if (firstName == null || lastName == null)
            throw new NullPointerException();
    this.firstName = firstName;
        this.lastName = lastName;
    }

    public String firstName() { return firstName; }
    public String lastName()  { return lastName;  }

    public boolean equals(Object o) {
        if (!(o instanceof Name))
            return false;
        Name n = (Name)o;
        return n.firstName.equals(firstName) &&
               n.lastName.equals(lastName);
    }

    public int hashCode() {
        return 31*firstName.hashCode() + lastName.hashCode();
    }

    public String toString() {
    return firstName + " " + lastName;
    }

    public int compareTo(Name n) {
        int lastCmp = lastName.compareTo(n.lastName);
        return (lastCmp != 0 ? lastCmp :
                firstName.compareTo(n.firstName));
    }
}
To keep the preceding example short, the class is somewhat limited: It doesn't support middle names, it demands both a first and a last name, and it is not internationalized in any way. Nonetheless, it illustrates the following important points:
  • Name objects are immutable. All other things being equal, immutable types are the way to go, especially for objects that will be used as elements in Sets or as keys in Maps. These collections will break if you modify their elements or keys while they're in the collection.
  • The constructor checks its arguments for null. This ensures that all Name objects are well formed so that none of the other methods will ever throw a NullPointerException.
  • The hashCode method is redefined. This is essential for any class that redefines the equals method. (Equal objects must have equal hash codes.)
  • The equals method returns false if the specified object is null or of an inappropriate type. The compareTo method throws a runtime exception under these circumstances. Both of these behaviors are required by the general contracts of the respective methods.
  • The toString method has been redefined so it prints the Name in human-readable form. This is always a good idea, especially for objects that are going to get put into collections. The various collection types' toString methods depend on the toString methods of their elements, keys, and values.
Since this section is about element ordering, let's talk a bit more about Name's compareTo method. It implements the standard name-ordering algorithm, where last names take precedence over first names. This is exactly what you want in a natural ordering. It would be very confusing indeed if the natural ordering were unnatural!

Take a look at how compareTo is implemented, because it's quite typical. First, you compare the most significant part of the object (in this case, the last name). Often, you can just use the natural ordering of the part's type. In this case, the part is a String and the natural (lexicographic) ordering is exactly what's called for. If the comparison results in anything other than zero, which represents equality, you're done: You just return the result. If the most significant parts are equal, you go on to compare the next most-significant parts. In this case, there are only two parts — first name and last name. If there were more parts, you'd proceed in the obvious fashion, comparing parts until you found two that weren't equal or you were comparing the least-significant parts, at which point you'd return the result of the comparison.

Just to show that it all works, here's a program that builds a list of names and sorts them.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.*;

public class NameSort {
    public static void main(String[] args) {
        Name nameArray[] = {
            new Name("John", "Lennon"),
            new Name("Karl", "Marx"),
            new Name("Groucho", "Marx"),
            new Name("Oscar", "Grouch")
        };
        List<Name> names = Arrays.asList(nameArray);
        Collections.sort(names);
        System.out.println(names);
    }
}
If you run this program, here's what it prints.
[Oscar Grouch, John Lennon, Groucho Marx, Karl Marx]
There are four restrictions on the behavior of the compareTo method, which we won't go into now because they're fairly technical and boring and are better left in the API documentation. It's really important that all classes that implement Comparable obey these restrictions, so read the documentation for Comparable if you're writing a class that implements it. Attempting to sort a list of objects that violate the restrictions has undefined behavior. Technically speaking, these restrictions ensure that the natural ordering is a total order on the objects of a class that implements it; this is necessary to ensure that sorting is well defined.

Comparators

What if you want to sort some objects in an order other than their natural ordering? Or what if you want to sort some objects that don't implement Comparable? To do either of these things, you'll need to provide a Comparator — an object that encapsulates an ordering. Like the Comparable interface, the Comparator interface consists of a single method.
public interface Comparator<T> {
    int compare(T o1, T o2);
}
The compare method compares its two arguments, returning a negative integer, 0, or a positive integer depending on whether the first argument is less than, equal to, or greater than the second. If either of the arguments has an inappropriate type for the Comparator, the compare method throws a ClassCastException.

Much of what was said about Comparable applies to Comparator as well. Writing a compare method is nearly identical to writing a compareTo method, except that the former gets both objects passed in as arguments. The compare method has to obey the same four technical restrictions as Comparable's compareTo method for the same reason — a Comparator must induce a total order on the objects it compares.

Suppose you have a class called Employee, as follows.

public class Employee implements Comparable<Employee> {
    public Name name()     { ... }
    public int number()    { ... }
    public Date hireDate() { ... }
       ...
}
Let's assume that the natural ordering of Employee instances is Name ordering (as defined in the previous example) on employee name. Unfortunately, the boss has asked for a list of employees in order of seniority. This means we have to do some work, but not much. The following program will produce the required list.
import java.util.*;
public class EmpSort {
    static final Comparator<Employee> SENIORITY_ORDER =
                                 new Comparator<Employee>() {
        public int compare(Employee e1, Employee e2) {
            return e2.hireDate().compareTo(e1.hireDate());
        }
    };

    // Employee database
    static final Collection<Employee> employees = ... ;

    public static void main(String[] args) {
        List<Employee>e = new ArrayList<Employee>(employees);
        Collections.sort(e, SENIORITY_ORDER);
        System.out.println(e);
    }
}
The Comparator in the program is reasonably straightforward. It relies on the natural ordering of Date applied to the values returned by the hireDate accessor method. Note that the Comparator passes the hire date of its second argument to its first rather than vice versa. The reason is that the employee who was hired most recently is the least senior; sorting in the order of hire date would put the list in reverse seniority order. Another technique people sometimes use to achieve this effect is to maintain the argument order but to negate the result of the comparison.
// Don't do this!!
return -r1.hireDate().compareTo(r2.hireDate());
You should always use the former technique in favor of the latter because the latter is not guaranteed to work. The reason for this is that the compareTo method can return any negative int if its argument is less than the object on which it is invoked. There is one negative int that remains negative when negated, strange as it may seem.
-Integer.MIN_VALUE == Integer.MIN_VALUE
The Comparator in the preceding program works fine for sorting a List, but it does have one deficiency: It cannot be used to order a sorted collection, such as TreeSet, because it generates an ordering that is not compatible with equals. This means that this Comparator equates objects that the equals method does not. In particular, any two employees who were hired on the same date will compare as equal. When you're sorting a List, this doesn't matter; but when you're using the Comparator to order a sorted collection, it's fatal. If you use this Comparator to insert multiple employees hired on the same date into a TreeSet, only the first one will be added to the set; the second will be seen as a duplicate element and will be ignored.

To fix this problem, simply tweak the Comparator so that it produces an ordering that is compatible with equals. In other words, tweak it so that the only elements seen as equal when using compare are those that are also seen as equal when compared using equals. The way to do this is to perform a two-part comparison (as for Name), where the first part is the one we're interested in — in this case, the hire date — and the second part is an attribute that uniquely identifies the object. Here the employee number is the obvious attribute. This is the Comparator that results.

static final Comparator<Employee> SENIORITY_ORDER =
                               new Comparator<Employee>() {
    public int compare(Employee e1, Employee e2) {
        int dateCmp = e2.hireDate().compareTo(e1.hireDate());
        if (dateCmp != 0)
            return dateCmp;
        return (e1.number() < e2.number() ? -1 :
                (e1.number() == e2.number() ? 0 : 1));
    }
};
One last note: You might be tempted to replace the final return statement in the Comparator with the simpler:
return e1.number() - e2.number();
Don't do it unless you're absolutely sure no one will ever have a negative employee number! This trick does not work in general because the signed integer type is not big enough to represent the difference of two arbitrary signed integers. If i is a large positive integer and j is a large negative integer, i - j will overflow and will return a negative integer. The resulting comparator violates one of the four technical restrictions we keep talking about (transitivity) and produces horrible, subtle bugs. This is not a purely theoretical concern; people get burned by it.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Map Interface
Next page: The SortedSet Interface


The SortedSet Interface (The Java™ Tutorials > Collections > Interfaces)

Trail: Collections
Lesson: Interfaces
Interfaces
The Collection Interface
The Set Interface
The List Interface
The Queue Interface
The Map Interface
Object Ordering
The SortedSet Interface
The SortedMap Interface
Summary of Interfaces
Questions and Exercises
Home Page > Collections > Interfaces
« Previous • Trail • Next »
The SortedSet Interface
A SortedSet is a Set that maintains its elements in ascending order, sorted according to the elements' natural ordering or according to a Comparator provided at SortedSet creation time. In addition to the normal Set operations, the SortedSet interface provides operations for the following:
  • Range view — allows arbitrary range operations on the sorted set
  • Endpoints — returns the first or last element in the sorted set
  • Comparator access — returns the Comparator, if any, used to sort the set
The code for the SortedSet interface follows.
public interface SortedSet<E> extends Set<E> {
    // Range-view
    SortedSet<E> subSet(E fromElement, E toElement);
    SortedSet<E> headSet(E toElement);
    SortedSet<E> tailSet(E fromElement);

    // Endpoints
    E first();
    E last();

    // Comparator access
    Comparator<? super E> comparator();
}

Set Operations

The operations that SortedSet inherits from Set behave identically on sorted sets and normal sets with two exceptions:
  • The Iterator returned by the iterator operation traverses the sorted set in order.
  • The array returned by toArray contains the sorted set's elements in order.
Although the interface doesn't guarantee it, the toString method of the Java platform's SortedSet implementations returns a string containing all the elements of the sorted set, in order.

Standard Constructors
By convention, all general-purpose Collection implementations provide a standard conversion constructor that takes a Collection; SortedSet implementations are no exception. In TreeSet, this constructor creates an instance that sorts its elements according to their natural ordering. This was probably a mistake. It would have been better to check dynamically to see whether the specified collection was a SortedSet instance and, if so, to sort the new TreeSet according to the same criterion (comparator or natural ordering). Because TreeSet took the approach that it did, it also provides a constructor that takes a SortedSet and returns a new TreeSet containing the same elements sorted according to the same criterion. Note that it is the compile-time type of the argument, not its runtime type, that determines which of these two constructors is invoked (and whether the sorting criterion is preserved).

SortedSet implementations also provide, by convention, a constructor that takes a Comparator and returns an empty set sorted according to the specified Comparator. If null is passed to this constructor, it returns a set that sorts its elements according to their natural ordering.

Range-view Operations

The range-view operations are somewhat analogous to those provided by the List interface, but there is one big difference. Range views of a sorted set remain valid even if the backing sorted set is modified directly. This is feasible because the endpoints of a range view of a sorted set are absolute points in the element space rather than specific elements in the backing collection, as is the case for lists. A range-view of a sorted set is really just a window onto whatever portion of the set lies in the designated part of the element space. Changes to the range-view write back to the backing sorted set and vice versa. Thus, it's okay to use range-views on sorted sets for long periods of time, unlike range-views on lists.

Sorted sets provide three range-view operations. The first, subSet, takes two endpoints, like subList. Rather than indices, the endpoints are objects and must be comparable to the elements in the sorted set, using the Set's Comparator or the natural ordering of its elements, whichever the Set uses to order itself. Like subList, the range is half open, including its low endpoint but excluding the high one.

Thus, the following line of code tells you how many words between "doorbell" and "pickle", including "doorbell" but excluding "pickle", are contained in a SortedSet of strings called dictionary:

int count = dictionary.subSet("doorbell", "pickle").size();
In like manner, the following one-liner removes all the elements beginning with the letter f.
dictionary.subSet("f", "g").clear();
A similar trick can be used to print a table telling you how many words begin with each letter.
for (char ch = 'a'; ch <= 'z'; ) {
    String from = String.valueOf(ch++);
    String to = String.valueOf(ch);
    System.out.println(from + ": " +
        dictionary.subSet(from, to).size());
}
Suppose you want to view a closed interval, which contains both of its endpoints, instead of an open interval. If the element type allows for the calculation of the successor of a given value in the element space, merely request the subSet from lowEndpoint to successor(highEndpoint). Although it isn't entirely obvious, the successor of a string s in String's natural ordering is s + "\0" — that is, s with a null character appended.

Thus, the following one-liner tells you how many words between "doorbell" and "pickle", including doorbell and pickle, are contained in the dictionary.

count = dictionary.subSet("doorbell", "pickle\0").size();
A similar technique can be used to view an open interval, which contains neither endpoint. The open-interval view from lowEndpoint to highEndpoint is the half-open interval from successor(lowEndpoint) to highEndpoint. Use the following to calculate the number of words between "doorbell" and "pickle", excluding both.
count = dictionary.subSet("doorbell\0", "pickle").size();
The SortedSet interface contains two more range-view operations — headSet and tailSet, both of which take a single Object argument. The former returns a view of the initial portion of the backing SortedSet, up to but not including the specified object. The latter returns a view of the final portion of the backing SortedSet, beginning with the specified object and continuing to the end of the backing SortedSet. Thus, the following code allows you to view the dictionary as two disjoint volumes (a-m and n-z).
SortedSet<String> volume1 = dictionary.headSet("n");
SortedSet<String> volume2 = dictionary.tailSet("n");

Endpoint Operations

The SortedSet interface contains operations to return the first and last elements in the sorted set, not surprisingly called first and last. In addition to their obvious uses, last allows a workaround for a deficiency in the SortedSet interface. One thing you'd like to do with a SortedSet is to go into the interior of the Set and iterate forward or backward. It's easy enough to go forward from the interior: Just get a tailSet and iterate over it. Unfortunately, there's no easy way to go backward.

The following idiom obtains the first element that is less than a specified object o in the element space.

Object predecessor = ss.headSet(o).last();
This is a fine way to go one element backward from a point in the interior of a sorted set. It could be applied repeatedly to iterate backward, but this is very inefficient, requiring a lookup for each element returned.

Comparator Accessor

The SortedSet interface contains an accessor method called comparator that returns the Comparator used to sort the set, or null if the set is sorted according to the natural ordering of its elements. This method is provided so that sorted sets can be copied into new sorted sets with the same ordering. It is used by the SortedSet constructor described previously.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Object Ordering
Next page: The SortedMap Interface


The SortedMap Interface (The Java™ Tutorials > Collections > Interfaces)

Trail: Collections
Lesson: Interfaces
Interfaces
The Collection Interface
The Set Interface
The List Interface
The Queue Interface
The Map Interface
Object Ordering
The SortedSet Interface
The SortedMap Interface
Summary of Interfaces
Questions and Exercises
Home Page > Collections > Interfaces
« Previous • Trail • Next »
The SortedMap Interface
A SortedMap is a Map that maintains its entries in ascending order, sorted according to the keys' natural ordering, or according to a Comparator provided at the time of the SortedMap creation. Natural ordering and Comparators are discussed in the Object Ordering section. The SortedMap interface provides operations for normal Map operations and for the following:
  • Range view — performs arbitrary range operations on the sorted map
  • Endpoints — returns the first or the last key in the sorted map
  • Comparator access — returns the Comparator, if any, used to sort the map
The following interface is the Map analog of SortedSet.
public interface SortedMap<K, V> extends Map<K, V>{
    Comparator<? super K> comparator();
    SortedMap<K, V> subMap(K fromKey, K toKey);
    SortedMap<K, V> headMap(K toKey);
    SortedMap<K, V> tailMap(K fromKey);
    K firstKey();
    K lastKey();
}

Map Operations

The operations SortedMap inherits from Map behave identically on sorted maps and normal maps with two exceptions:
  • The Iterator returned by the iterator operation on any of the sorted map's Collection views traverse the collections in order.
  • The arrays returned by the Collection views' toArray operations contain the keys, values, or entries in order.
Although it isn't guaranteed by the interface, the toString method of the Collection views in all the Java platform's SortedMap implementations returns a string containing all the elements of the view, in order.

Standard Constructors

By convention, all general-purpose Map implementations provide a standard conversion constructor that takes a Map; SortedMap implementations are no exception. In TreeMap, this constructor creates an instance that orders its entries according to their keys' natural ordering. This was probably a mistake. It would have been better to check dynamically to see whether the specified Map instance was a SortedMap and, if so, to sort the new map according to the same criterion (comparator or natural ordering). Because TreeMap took the approach it did, it also provides a constructor that takes a SortedMap and returns a new TreeMap containing the same mappings as the given SortedMap, sorted according to the same criterion. Note that it is the compile-time type of the argument, not its runtime type, that determines whether the SortedMap constructor is invoked in preference to the ordinary map constructor.

SortedMap implementations also provide, by convention, a constructor that takes a Comparator and returns an empty map sorted according to the specified Comparator. If null is passed to this constructor, it returns a Map that sorts its mappings according to their keys' natural ordering.

Comparison to SortedSet

Because this interface is a precise Map analog of SortedSet, all the idioms and code examples in The SortedSet Interface section apply to SortedMap with only trivial modifications.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The SortedSet Interface
Next page: Summary of Interfaces


Summary of Interfaces (The Java™ Tutorials > Collections > Interfaces)

Trail: Collections
Lesson: Interfaces
Interfaces
The Collection Interface
The Set Interface
The List Interface
The Queue Interface
The Map Interface
Object Ordering
The SortedSet Interface
The SortedMap Interface
Summary of Interfaces
Questions and Exercises
Home Page > Collections > Interfaces
« Previous • Trail • Next »
Summary of Interfaces
The core collection interfaces are the foundation of the Java Collections Framework.

The Java Collections Framework hierarchy consists of two distinct interface trees:

  • The first tree starts with the Collection interface, which provides for the basic functionality used by all collections, such as add and remove methods. Its subinterfaces — Set, List, and Queue — provide for more specialized collections.

    The Set interface does not allow duplicate elements. This can be useful for storing collections such as a deck of cards or student records. The Set interface has a subinterface, SortedSet, that provides for ordering of elements in the set.

    The List interface provides for an ordered collection, for situations in which you need precise control over where each element is inserted. You can retrieve elements from a List by their exact position.

    The Queue interface enables additional insertion, extraction, and inspection operations. Elements in a Queue are typically ordered in on a FIFO basis.

  • The second tree starts with the Map interface, which maps keys and values similar to a Hashtable.

    Map's subinterface, SortedMap, maintains its key-value pairs in ascending order or in an order specified by a Comparator.

These interfaces allow collections to be manipulated independently of the details of their representation.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The SortedMap Interface
Next page: Questions and Exercises: Interfaces


Questions and Exercises: Interfaces (The Java™ Tutorials > Collections > Interfaces)

Trail: Collections
Lesson: Interfaces
Interfaces
The Collection Interface
The Set Interface
The List Interface
The Queue Interface
The Map Interface
Object Ordering
The SortedSet Interface
The SortedMap Interface
Summary of Interfaces
Questions and Exercises
Home Page > Collections > Interfaces
« Previous • Trail • Next »
Questions and Exercises: Interfaces

Questions

  1. This lesson mentions three ways to traverse a List. Describe them, and note the limitations of each.
  2. Consider the four core interfaces, Set, List, Queue, and Map. For each of the following four assignments, specify which of the four core interfaces is best suited, and explain how to use it to implement the assignment.
    • Whimsical Toys Inc (WTI) needs to record the names of all its employees. Every month, an employee will be chosen at random from these records to receive a free toy.
    • WTI has decided that each new product will be named after an employee — but only first names will be used, and each name will be used only once. Prepare a list of unique first names.
    • WTI decides that it only wants to use the most popular names for its toys. Count the number of employees who have each first name.
    • WTI acquires season tickets for the local lacrosse team, to be shared by employees. Create a waiting list for this popular sport.
  3. The following program is supposed to print the string "Blue". Instead, it throws an error. Why?
    import java.util.*;

public class SortMe {
    public static void main(String args[]) {
        SortedSet<StringBuffer> s = new TreeSet<StringBuffer>();
        s.add(new StringBuffer("Red"));
        s.add(new StringBuffer("White"));
        s.add(new StringBuffer("Blue"));
        System.out.println(s.first());
    }
}

Exercises

  1. Write a program that prints its arguments in random order. Do not make a copy of the argument array.
  2. Take the FindDups example and modify it to use a SortedSet instead of a Set. Specify a Comparator so that case is ignored when sorting and identifying set elements.
  3. Write a method that takes a List<String> and applies String.trim to each element. To do this, you'll need to pick one of the three iteration idioms that you described in Question 1. Two of these will not give the result you want, so be sure to write a program that demonstrates that the method actually works!
Check your answers.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary of Interfaces
Next page: Implementations


Lesson: Implementations (The Java™ Tutorials > Collections)

Implementations
Set Implementations
List Implementations
Map Implementations
Queue Implementations
Wrapper Implementations
Convenience Implementations
Summary of Implementations
Questions and Exercises
Trail: Collections
Home Page > Collections
« Previous • Trail • Next »
Lesson: Implementations
Implementations are the data objects used to store collections, which implement the interfaces described in the Interfaces section.. This lesson describes the following kinds of implementations:
  • General-purpose implementations are the most commonly used implementations, designed for everyday use.
    • They are summarized in the table below.
  • Special-purpose implementations are designed for use in special situations and display nonstandard performance characteristics, usage restrictions, or behavior.
  • Concurrent implementations are designed to support high concurrency, typically at the expense of single-threaded performance. These implementations are part of the java.util.concurrent package.
  • Wrapper implementations are used in combination with other types of implementations, often the general-purpose ones, to provide added or restricted functionality.
  • Convenience implementations are mini-implementations, typically made available via static factory methods, that provide convenient, efficient alternatives to general-purpose implementations for special collections (for example, singleton sets).
  • Abstract implementations are skeletal implementations that facilitate the construction of custom implementations — described later in the Custom Collection Implementations section. An advanced topic, it's not particularly difficult, but relatively few people will need to do it.
The general-purpose implementations are summarized in the following table.
General-purpose Implementations
Interfaces | Implementations
Hash table | Resizable array | Tree | Linked list | Hash table + Linked list
Set | HashSet | TreeSet | LinkedHashSet
List | ArrayList | LinkedList
Queue
Map | HashMap | TreeMap | LinkedHashMap

As you can see from the table, the Java Collections Framework provides several general-purpose implementations of the Set, List , and Map interfaces. In each case, one implementation — HashSet, ArrayList, and HashMap — is clearly the one to use for most applications, all other things being equal. Note that the SortedSet and the SortedMap interfaces do not have rows in the table. Each of those interfaces has one implementation ( TreeSet and TreeMap) and is listed in the Set and the Map rows. There are two general-purpose Queue implementations — LinkedList, which is also a List implementation, and PriorityQueue, which is omitted from the table. These two implementations provide very different semantics: LinkedList provides FIFO semantics, while PriorityQueue orders its elements according to their values.

Each of the general-purpose implementations provides all optional operations contained in its interface. All permit null elements, keys, and values. None are synchronized (thread-safe). All have fail-fast iterators, which detect illegal concurrent modification during iteration and fail quickly and cleanly rather than risking arbitrary, nondeterministic behavior at an undetermined time in the future. All are Serializable and all support a public clone method.

The fact that these implementations are unsynchronized represents a break with the past: The legacy collections Vector and Hashtable are synchronized. The present approach was taken because collections are frequently used when the synchronization is of no benefit. Such uses include single-threaded use, read-only use, and use as part of a larger data object that does its own synchronization. In general, it is good API design practice not to make users pay for a feature they don't use. Furthermore, unnecessary synchronization can result in deadlock under certain circumstances.

If you need thread-safe collections, the synchronization wrappers, described in the Wrapper Implementations section, allow any collection to be transformed into a synchronized collection. Thus, synchronization is optional for general-purpose implementations, whereas it is mandatory for legacy implementations. Moreover, the java.util.concurrent package provides concurrent implementations of the BlockingQueue interface, which extends Queue, and of the ConcurrentMap interface, which extends Map. These implementations offer much higher concurrency than mere synchronized implementations.

As a rule, you should be thinking about the interfaces, not the implementations. That is why there are no programming examples in this section. For the most part, the choice of implementation affects only performance. The preferred style, as mentioned in the Interfaces section, is to choose an implementation when a Collection is created and to immediately assign the new collection to a variable of the corresponding interface type (or to pass the collection to a method expecting an argument of the interface type). In this way, the program does not become dependent on any added methods in a given implementation, leaving the programmer free to change implementations anytime that it is warranted by performance concerns or behavioral details.

The sections that follow briefly discuss the implementations. The performance of the implementations is described using words such as constant-time, log, linear, n log(n), and quadratic to refer to the asymptotic upper-bound on the time complexity of performing the operation. All this is quite a mouthful, and it doesn't matter much if you don't know what it means. If you're interested in knowing more, refer to any good algorithms textbook. One thing to keep in mind is that this sort of performance metric has its limitations. Sometimes, the nominally slower implementation may be faster. When in doubt, measure the performance!

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Set Implementations


Set Implementations (The Java™ Tutorials > Collections > Implementations)

Trail: Collections
Lesson: Implementations
Implementations
Set Implementations
List Implementations
Map Implementations
Queue Implementations
Wrapper Implementations
Convenience Implementations
Summary of Implementations
Questions and Exercises
Home Page > Collections > Implementations
« Previous • Trail • Next »
Set Implementations
The Set implementations are grouped into general-purpose and special-purpose implementations.

General-Purpose Set Implementations

There are three general-purpose Set implementations — HashSet, TreeSet, and LinkedHashSet. Which of these three to use is generally straightforward. HashSet is much faster than TreeSet (constant-time versus log-time for most operations) but offers no ordering guarantees. If you need to use the operations in the SortedSet interface, or if value-ordered iteration is required, use TreeSet; otherwise, use HashSet. It's a fair bet that you'll end up using HashSet most of the time.

LinkedHashSet is in some sense intermediate between HashSet and TreeSet. Implemented as a hash table with a linked list running through it, it provides insertion-ordered iteration (least recently inserted to most recently) and runs nearly as fast as HashSet. The LinkedHashSet implementation spares its clients from the unspecified, generally chaotic ordering provided by HashSet without incurring the increased cost associated with TreeSet.

One thing worth keeping in mind about HashSet is that iteration is linear in the sum of the number of entries and the number of buckets (the capacity). Thus, choosing an initial capacity that's too high can waste both space and time. On the other hand, choosing an initial capacity that's too low wastes time by copying the data structure each time it's forced to increase its capacity. If you don't specify an initial capacity, the default is 16. In the past, there was some advantage to choosing a prime number as the initial capacity. This is no longer true. Internally, the capacity is always rounded up to a power of two. The initial capacity is specified by using the int constructor. The following line of code allocates a HashSet whose initial capacity is 64.

Set<String> s = new HashSet<String>(64);
The HashSet class has one other tuning parameter called the load factor. If you care a lot about the space consumption of your HashSet, read the HashSet documentation for more information. Otherwise, just accept the default; it's almost always the right thing to do.

If you accept the default load factor but want to specify an initial capacity, pick a number that's about twice the size to which you expect the set to grow. If your guess is way off, you may waste a bit of space, time, or both, but it's unlikely to be a big problem.

LinkedHashSet has the same tuning parameters as HashSet, but iteration time is not affected by capacity. TreeSet has no tuning parameters.

Special-Purpose Set Implementations

There are two special-purpose Set implementations — EnumSet and CopyOnWriteArraySet.

EnumSet is a high-performance Set implementation for enum types. All of the members of an enum set must be of the same enum type. Internally, it is represented by a bit-vector, typically a single long. Enum sets support iteration over ranges of enum types. For example, given the enum declaration for the days of the week, you can iterate over the weekdays. The EnumSet class provides a static factory that makes it easy.

    for (Day d : EnumSet.range(Day.MONDAY, Day.FRIDAY))
        System.out.println(d);
Enum sets also provide a rich, typesafe replacement for traditional bit flags.
    EnumSet.of(Style.BOLD, Style.ITALIC)
CopyOnWriteArraySet is a Set implementation backed up by a copy-on-write array. All mutative operations, such as add, set, and remove, are implemented by making a new copy of the array; no locking is ever required. Even iteration may safely proceed concurrently with element insertion and deletion. Unlike most Set implementations, the add, remove, and contains methods require time proportional to the size of the set. This implementation is only appropriate for sets that are rarely modified but frequently iterated. It is well suited to maintaining event-handler lists that must prevent duplicates.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Implementations
Next page: List Implementations


List Implementations (The Java™ Tutorials > Collections > Implementations)

Trail: Collections
Lesson: Implementations
Implementations
Set Implementations
List Implementations
Map Implementations
Queue Implementations
Wrapper Implementations
Convenience Implementations
Summary of Implementations
Questions and Exercises
Home Page > Collections > Implementations
« Previous • Trail • Next »
List Implementations
List implementations are grouped into general-purpose and special-purpose implementations.

General-Purpose List Implementations

There are two general-purpose List implementations — ArrayList and LinkedList. Most of the time, you'll probably use ArrayList, which offers constant-time positional access and is just plain fast. It does not have to allocate a node object for each element in the List, and it can take advantage of System.arraycopy when it has to move multiple elements at the same time. Think of ArrayList as Vector without the synchronization overhead.

If you frequently add elements to the beginning of the List or iterate over the List to delete elements from its interior, you should consider using LinkedList. These operations require constant-time in a LinkedList and linear-time in an ArrayList. But you pay a big price in performance. Positional access requires linear-time in a LinkedList and constant-time in an ArrayList. Furthermore, the constant factor for LinkedList is much worse. If you think you want to use a LinkedList, measure the performance of your application with both LinkedList and ArrayList before making your choice; ArrayList is usually faster.

ArrayList has one tuning parameter — the initial capacity, which refers to the number of elements the ArrayList can hold before it has to grow. LinkedList has no tuning parameters and seven optional operations, one of which is clone. The other six are addFirst, getFirst, removeFirst, addLast, getLast, and removeLast. LinkedList also implements the Queue interface.

Special-Purpose List Implementations

CopyOnWriteArrayList is a List implementation backed up by a copy-on-write array. This implementation is similar in nature to CopyOnWriteArraySet. No synchronization is necessary, even during iteration, and iterators are guaranteed never to throw ConcurrentModificationException. This implementation is well suited to maintaining event-handler lists, in which change is infrequent, and traversal is frequent and potentially time-consuming.

If you need synchronization, a Vector will be slightly faster than an ArrayList synchronized with Collections.synchronizedList. But Vector has loads of legacy operations, so be careful to always manipulate the Vector with the List interface or else you won't be able to replace the implementation at a later time.

If your List is fixed in size — that is, you'll never use remove, add, or any of the bulk operations other than containsAll — you have a third option that's definitely worth considering. See Arrays.asList in the Convenience Implementations section for more information.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Set Implementations
Next page: Map Implementations


Map Implementations (The Java™ Tutorials > Collections > Implementations)

Trail: Collections
Lesson: Implementations
Implementations
Set Implementations
List Implementations
Map Implementations
Queue Implementations
Wrapper Implementations
Convenience Implementations
Summary of Implementations
Questions and Exercises
Home Page > Collections > Implementations
« Previous • Trail • Next »
Map Implementations
Map implementations are grouped into general-purpose, special-purpose, and concurrent implementations.

General-Purpose Map Implementations

The three general-purpose Map implementations are HashMap, TreeMap and LinkedHashMap. If you need SortedMap operations or key-ordered Collection-view iteration, use TreeMap; if you want maximum speed and don't care about iteration order, use HashMap; if you want near-HashMap performance and insertion-order iteration, use LinkedHashMap. In this respect, the situation for Map is analogous to Set. Likewise, everything else in the Set Implementations section also applies to Map implementations.

LinkedHashMap provides two capabilities that are not available with LinkedHashSet. When you create a LinkedHashMap, you can order it based on key access rather than insertion. In other words, merely looking up the value associated with a key brings that key to the end of the map. Also, LinkedHashMap provides the removeEldestEntry method, which may be overridden to impose a policy for removing stale mappings automatically when new mappings are added to the map. This makes it very easy to implement a custom cache.

For example, this override will allow the map to grow up to as many as 100 entries and then it will delete the eldest entry each time a new entry is added, maintaining a steady state of 100 entries.

private static final int MAX_ENTRIES = 100;

protected boolean removeEldestEntry(Map.Entry eldest) {
    return size() > MAX_ENTRIES;
}

Special-Purpose Map Implementations

There are three special-purpose Map implementations — EnumMap, WeakHashMap and IdentityHashMap. EnumMap, which is internally implemented as an array, is a high-performance Map implementation for use with enum keys. This implementation combines the richness and safety of the Map interface with a speed approaching that of an array. If you want to map an enum to a value, you should always use an EnumMap in preference to an array.

WeakHashMap is an implementation of the Map interface that stores only weak references to its keys. Storing only weak references allows a key-value pair to be garbage-collected when its key is no longer referenced outside of the WeakHashMap. This class provides the easiest way to harness the power of weak references. It is useful for implementing "registry-like" data structures, where the utility of an entry vanishes when its key is no longer reachable by any thread.

IdentityHashMap is an identity-based Map implementation based on a hash table. This class is useful for topology-preserving object graph transformations, such as serialization or deep-copying. To perform such transformations, you need to maintain an identity-based "node table" that keeps track of which objects have already been seen. Identity-based maps are also used to maintain object-to-meta-information mappings in dynamic debuggers and similar systems. Finally, identity-based maps are useful in thwarting "spoof attacks" that are a result of intentionally perverse equals methods because IdentityHashMap never invokes the equals method on its keys. An added benefit of this implementation is that it is fast.

Concurrent Map Implementations

The java.util.concurrent package contains the ConcurrentMap interface, which extends Map with atomic putIfAbsent, remove, and replace methods, and the ConcurrentHashMap implementation of that interface.

ConcurrentHashMap is a highly concurrent, high-performance implementation backed up by a hash table. This implementation never blocks when performing retrievals and allows the client to select the concurrency level for updates. It is intended as a drop-in replacement for Hashtable: in addition to implementing ConcurrentMap, it supports all the legacy methods peculiar to Hashtable. Again, if you don't need the legacy operations, be careful to manipulate it with the ConcurrentMap interface.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: List Implementations
Next page: Queue Implementations


Queue Implementations (The Java™ Tutorials > Collections > Implementations)

Trail: Collections
Lesson: Implementations
Implementations
Set Implementations
List Implementations
Map Implementations
Queue Implementations
Wrapper Implementations
Convenience Implementations
Summary of Implementations
Questions and Exercises
Home Page > Collections > Implementations
« Previous • Trail • Next »
Queue Implementations
The Queue implementations are grouped into general-purpose and concurrent implementations.

General-Purpose Queue Implementations

As mentioned in the previous section, LinkedList implements the Queue interface, providing FIFO queue operations for add, poll, and so on.

The PriorityQueue class is a priority queue based on the heap data structure. This queue orders elements according to an order specified at construction time, which can be the elements' natural ordering or the ordering imposed by an explicit Comparator.

The queue retrieval operations — poll, remove, peek, and element — access the element at the head of the queue. The head of the queue is the least element with respect to the specified ordering. If multiple elements are tied for least value, the head is one of those elements; ties are broken arbitrarily.

PriorityQueue and its iterator implement all of the optional methods of the Collection and Iterator interfaces. The iterator provided in method iterator is not guaranteed to traverse the elements of the PriorityQueue in any particular order. If you need ordered traversal, consider using Arrays.sort(pq.toArray()).

Concurrent Queue Implementations

The java.util.concurrent package contains a set of synchronized Queue interfaces and classes. BlockingQueue extends Queue with operations that wait for the queue to become nonempty when retrieving an element and for space to become available in the queue when storing an element. This interface is implemented by the following classes:
  • LinkedBlockingQueue — an optionally bounded FIFO blocking queue backed by linked nodes
  • ArrayBlockingQueue — a bounded FIFO blocking queue backed by an array
  • PriorityBlockingQueue — an unbounded blocking priority queue backed by a heap
  • DelayQueue — a time-based scheduling queue backed by a heap
  • SynchronousQueue — a simple rendezvous mechanism that uses the BlockingQueue interface
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Map Implementations
Next page: Wrapper Implementations


Wrapper Implementations (The Java™ Tutorials > Collections > Implementations)

Trail: Collections
Lesson: Implementations
Implementations
Set Implementations
List Implementations
Map Implementations
Queue Implementations
Wrapper Implementations
Convenience Implementations
Summary of Implementations
Questions and Exercises
Home Page > Collections > Implementations
« Previous • Trail • Next »
Wrapper Implementations
Wrapper implementations delegate all their real work to a specified collection but add extra functionality on top of what this collection offers. For design pattern fans, this is an example of the decorator pattern. Although it may seem a bit exotic, it's really pretty straightforward.

These implementations are anonymous; rather than providing a public class, the library provides a static factory method. All these implementations are found in the Collections class, which consists solely of static methods.

Synchronization Wrappers

The synchronization wrappers add automatic synchronization (thread-safety) to an arbitrary collection. Each of the six core collection interfaces — Collection, Set, List, Map, SortedSet, and SortedMap — has one static factory method.
public static <T> Collection<T>
    synchronizedCollection(Collection<T> c);
public static <T> Set<T>
    synchronizedSet(Set<T> s);
public static <T> List<T>
    synchronizedList(List<T> list);
public static <K,V> Map<K,V>
    synchronizedMap(Map<K,V> m);
public static <T> SortedSet<T>
    synchronizedSortedSet(SortedSet<T> s);
public static <K,V> SortedMap<K,V>
    synchronizedSortedMap(SortedMap<K,V> m);
Each of these methods returns a synchronized (thread-safe) Collection backed up by the specified collection. To guarantee serial access, all access to the backing collection must be accomplished through the returned collection. The easy way to guarantee this is not to keep a reference to the backing collection. Create the synchronized collection with the following trick.
List<Type> list =
    Collections.synchronizedList(new ArrayList<Type>());
A collection created in this fashion is every bit as thread-safe as a normally synchronized collection, such as a Vector.

In the face of concurrent access, it is imperative that the user manually synchronize on the returned collection when iterating over it. The reason is that iteration is accomplished via multiple calls into the collection, which must be composed into a single atomic operation. The following is the idiom to iterate over a wrapper-synchronized collection.

Collection<Type> c =
    Collections.synchronizedCollection(myCollection);
synchronized(c) {
    for (Type e : c)
        foo(e);
}
If an explicit iterator is used, the iterator method must be called from within the synchronized block. Failure to follow this advice may result in nondeterministic behavior. The idiom for iterating over a Collection view of a synchronized Map is similar. It is imperative that the user synchronize on the synchronized Map when iterating over any of its Collection views rather than synchronizing on the Collection view itself, as shown in the following example.
Map<KeyType, ValType> m =
    Collections.synchronizedMap(new HashMap<KeyType, ValType>());
    ...
Set<KeyType> s = m.keySet();
    ...
synchronized(m) {  // Synchronizing on m, not s!
    while (KeyType k : s)
        foo(k);
}
One minor downside of using wrapper implementations is that you do not have the ability to execute any noninterface operations of a wrapped implementation. So, for instance, in the preceding List example, you cannot call ArrayList's ensureCapacity operation on the wrapped ArrayList.

Unmodifiable Wrappers

Unlike synchronization wrappers, which add functionality to the wrapped collection, the unmodifiable wrappers take functionality away. In particular, they take away the ability to modify the collection by intercepting all the operations that would modify the collection and throwing an UnsupportedOperationException. Unmodifiable wrappers have two main uses, as follows:
  • To make a collection immutable once it has been built. In this case, it's good practice not to maintain a reference to the backing collection. This absolutely guarantees immutability.
  • To allow certain clients read-only access to your data structures. You keep a reference to the backing collection but hand out a reference to the wrapper. In this way, clients can look but not modify, while you maintain full access.
Like synchronization wrappers, each of the six core Collection interfaces has one static factory method.
public static <T> Collection<T>
    unmodifiableCollection(Collection<? extends T> c);
public static <T> Set<T>
    unmodifiableSet(Set<? extends T> s);
public static <T> List<T>
    unmodifiableList(List<? extends T> list);
public static <K,V> Map<K, V>
    unmodifiableMap(Map<? extends K, ? extends V> m);
public static <T> SortedSet<T>
    unmodifiableSortedSet(SortedSet<? extends T> s);
public static <K,V> SortedMap<K, V>
    unmodifiableSortedMap(SortedMap<K, ? extends V> m);

Checked Interface Wrappers

The Collections.checked interface wrappers are provided for use with generic collections. These implementations return a dynamically type-safe view of the specified collection, which throws a ClassCastException if a client attempts to add an element of the wrong type. The generics mechanism in the language provides compile-time (static) type-checking, but it is possible to defeat this mechanism. Dynamically type-safe views eliminate this possibility entirely.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Queue Implementations
Next page: Convenience Implementations


Convenience Implementations (The Java™ Tutorials > Collections > Implementations)

Trail: Collections
Lesson: Implementations
Implementations
Set Implementations
List Implementations
Map Implementations
Queue Implementations
Wrapper Implementations
Convenience Implementations
Summary of Implementations
Questions and Exercises
Home Page > Collections > Implementations
« Previous • Trail • Next »
Convenience Implementations
This section describes several mini-implementations that can be more convenient and more efficient than general-purpose implementations when you don't need their full power. All the implementations in this section are made available via static factory methods rather than public classes.

List View of an Array

The Arrays.asList method returns a List view of its array argument. Changes to the List write through to the array and vice versa. The size of the collection is that of the array and cannot be changed. If the add or the remove method is called on the List, an UnsupportedOperationException will result.

The normal use of this implementation is as a bridge between array-based and collection-based APIs. It allows you to pass an array to a method expecting a Collection or a List. However, this implementation also has another use. If you need a fixed-size List, it's more efficient than any general-purpose List implementation. This is the idiom.

List<String> list = Arrays.asList(new String[size]);
Note that a reference to the backing array is not retained.

Immutable Multiple-Copy List

Occasionally you'll need an immutable List consisting of multiple copies of the same element. The Collections.nCopies method returns such a list. This implementation has two main uses. The first is to initialize a newly created List; for example, suppose you want an ArrayList initially consisting of 1,000 null elements. The following incantation does the trick.
List<Type> list =
    new ArrayList<Type>(Collections.nCopies(1000, (Type)null);
Of course, the initial value of each element need not be null. The second main use is to grow an existing List. For example, suppose you want to add 69 copies of the string "fruit bat" to the end of a List<String>. It's not clear why you'd want to do such a thing, but let's just suppose you did. The following is how you'd do it.
lovablePets.addAll(Collections.nCopies(69, "fruit bat"));
By using the form of addAll that takes both an index and a Collection, you can add the new elements to the middle of a List instead of to the end of it.

Immutable Singleton Set

Sometimes you'll need an immutable singleton Set, which consists of a single, specified element. The Collections.singleton method returns such a Set. One use of this implementation is to remove all occurrences of a specified element from a Collection.
c.removeAll(Collections.singleton(e));
A related idiom removes all elements that map to a specified value from a Map. For example, suppose you have a Map — job — that maps people to their line of work and suppose you want to eliminate all the lawyers. The following one-liner will do the deed.
job.values().removeAll(Collections.singleton(LAWYER));
One more use of this implementation is to provide a single input value to a method that is written to accept a collection of values.

Empty Set, List, and Map Constants

The Collections class provides methods to return the empty Set, List, and Map — emptySet, emptyList, and emptyMap. The main use of these constants is as input to methods that take a Collection of values when you don't want to provide any values at all, as in this example.
tourist.declarePurchases(Collections.emptySet());
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Wrapper Implementations
Next page: Summary of Implementations


Summary of Implementations (The Java™ Tutorials > Collections > Implementations)

Trail: Collections
Lesson: Implementations
Implementations
Set Implementations
List Implementations
Map Implementations
Queue Implementations
Wrapper Implementations
Convenience Implementations
Summary of Implementations
Questions and Exercises
Home Page > Collections > Implementations
« Previous • Trail • Next »
Summary of Implementations
Implementations are the data objects used to store collections, which implement the interfaces described in the Interfaces lesson.

The Java Collections Framework provides several general-purpose implementations of the core interfaces:

  • For the Set interface, HashSet is the most commonly used implementation.
  • For the List interface, ArrayList is the most commonly used implementation.
  • For the Map interface, HashMap is the most commonly used implementation.
  • For the Queue interface, LinkedList is the most commonly used implementation.
Each of the general-purpose implementations provides all optional operations contained in its interface.

The Java Collections Framework also provides several special-purpose implementations for situations that require nonstandard performance, usage restrictions, or other unusual behavior.

The java.util.concurrent package contains several collections implementations, which are thread-safe but not governed by a single exclusion lock.

The Collections class (as opposed to the Collection interface), provides static methods that operate on or return collections, which are known as Wrapper implementations.

Finally, there are several Convenience implementations, which can be more efficient than general-purpose implementations when you don't need their full power. The Convenience implementations are made available through static factory methods.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Convenience Implementations
Next page: Questions and Exercises: Implementations


Questions and Exercises: Implementations (The Java™ Tutorials > Collections > Implementations)

Trail: Collections
Lesson: Implementations
Implementations
Set Implementations
List Implementations
Map Implementations
Queue Implementations
Wrapper Implementations
Convenience Implementations
Summary of Implementations
Questions and Exercises
Home Page > Collections > Implementations
« Previous • Trail • Next »
Questions and Exercises: Implementations

Questions

  1. You plan to write a program that uses several basic collection interfaces: Set, List, Queue, and Map. You're not sure which implementations will work best, so you decide to use general-purpose implementations until you get a better idea how your program will work in the real world. Which implementations are these?

  2. If you need a Set implementation that provides value-ordered iteration, which class should you use?

  3. Which class do you use to access wrapper implementations?

Exercises

  1. Write a program that reads a text file, specified by the first command line argument, into a List. The program should then print random lines from the file, the number of lines printed to be specified by the second command line argument. Write the program so that a correctly-sized collection is allocated all at once, instead of being gradually expanded as the file is read in. Hint: To determine the number of lines in the file, use java.io.File.length to obtain the size of the file, then divide by an assumed size of an average line.
Check your answers.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Summary of Implementations
Next page: Algorithms


Lesson: Algorithms (The Java™ Tutorials > Collections)

Trail: Collections
Home Page > Collections
« Previous • Trail • Next »
Lesson: Algorithms
The polymorphic algorithms described here are pieces of reusable functionality provided by the Java platform. All of them come from the Collections class, and all take the form of static methods whose first argument is the collection on which the operation is to be performed. The great majority of the algorithms provided by the Java platform operate on List instances, but a few of them operate on arbitrary Collection instances. This section briefly describes the following algorithms:
  • Sorting
  • Shuffling
  • Routine Data Manipulation
  • Searching
  • Composition
  • Finding Extreme Values

Sorting

The sort algorithm reorders a List so that its elements are in ascending order according to an ordering relationship. Two forms of the operation are provided. The simple form takes a List and sorts it according to its elements' natural ordering. If you're unfamiliar with the concept of natural ordering, read the Object Ordering section.

The sort operation uses a slightly optimized merge sort algorithm that is fast and stable:

  • Fast: It is guaranteed to run in n log(n) time and runs substantially faster on nearly sorted lists. Empirical tests showed it to be as fast as a highly optimized quicksort. A quicksort is generally considered to be faster than a merge sort but isn't stable and doesn't guarantee n log(n) performance.
  • Stable: It doesn't reorder equal elements. This is important if you sort the same list repeatedly on different attributes. If a user of a mail program sorts the inbox by mailing date and then sorts it by sender, the user naturally expects that the now-contiguous list of messages from a given sender will (still) be sorted by mailing date. This is guaranteed only if the second sort was stable.
The following trivial program prints out its arguments in lexicographic (alphabetical) order.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.*;

public class Sort {
    public static void main(String[] args) {
        List<String> list = Arrays.asList(args);
        Collections.sort(list);
        System.out.println(list);
    }
}
Let's run the program.
% java Sort i walk the line
The following output is produced.
[i, line, the, walk]
The program was included only to show you that algorithms really are as easy to use as they appear to be.

The second form of sort takes a Comparator in addition to a List and sorts the elements with the Comparator. Suppose you want to print out the anagram groups from our earlier example in reverse order of size — largest anagram group first. The example that follows shows you how to achieve this with the help of the second form of the sort method.

Recall that the anagram groups are stored as values in a Map, in the form of List instances. The revised printing code iterates through the Map's values view, putting every List that passes the minimum-size test into a List of Lists. Then the code sorts this List, using a Comparator that expects List instances, and implements reverse size-ordering. Finally, the code iterates through the sorted List, printing its elements (the anagram groups). The following code replaces the printing code at the end of the main method in the Anagrams example.

// Make a List of all anagram groups above size threshold.
List<List<String>> winners = new ArrayList<List<String>>();
for (List<String> l : m.values())
    if (l.size() >= minGroupSize)
        winners.add(l);

// Sort anagram groups according to size
Collections.sort(winners, new Comparator<List<String>>() {
    public int compare(List<String> o1, List<String> o2) {
        return o2.size() - o1.size();
    }});

// Print anagram groups.
for (List<String> l : winners)
    System.out.println(l.size() + ": " + l);
Running the program on the same dictionary as in The Map Interface section, with the same minimum anagram group size (eight), produces the following output.

12: [apers, apres, asper, pares, parse, pears, prase,
       presa, rapes, reaps, spare, spear]
11: [alerts, alters, artels, estral, laster, ratels,
       salter, slater, staler, stelar, talers]
10: [least, setal, slate, stale, steal, stela, taels,
       tales, teals, tesla]
9: [estrin, inerts, insert, inters, niters, nitres,
       sinter, triens, trines]
9: [capers, crapes, escarp, pacers, parsec, recaps,
       scrape, secpar, spacer]
9: [palest, palets, pastel, petals, plates, pleats,
       septal, staple, tepals]
9: [anestri, antsier, nastier, ratines, retains, retinas,
       retsina, stainer, stearin]
8: [lapse, leaps, pales, peals, pleas, salep, sepal, spale]
8: [aspers, parses, passer, prases, repass, spares,
       sparse, spears]
8: [enters, nester, renest, rentes, resent, tenser,
       ternes, treens]
8: [arles, earls, lares, laser, lears, rales, reals, seral]
8: [earings, erasing, gainers, reagins, regains, reginas,
       searing, seringa]
8: [peris, piers, pries, prise, ripes, speir, spier, spire]
8: [ates, east, eats, etas, sate, seat, seta, teas]
8: [carets, cartes, caster, caters, crates, reacts,
       recast, traces]

Shuffling

The shuffle algorithm does the opposite of what sort does, destroying any trace of order that may have been present in a List. That is, this algorithm reorders the List based on input from a source of randomness such that all possible permutations occur with equal likelihood, assuming a fair source of randomness. This algorithm is useful in implementing games of chance. For example, it could be used to shuffle a List of Card objects representing a deck. Also, it's useful for generating test cases.

This operation has two forms: one takes a List and uses a default source of randomness, and the other requires the caller to provide a Random object to use as a source of randomness. The code for this algorithm is used as an example in the List section.

Routine Data Manipulation

The Collections class provides five algorithms for doing routine data manipulation on List objects, all of which are pretty straightforward:
  • reverse — reverses the order of the elements in a List.

  • fill — overwrites every element in a List with the specified value. This operation is useful for reinitializing a List.

  • copy — takes two arguments, a destination List and a source List, and copies the elements of the source into the destination, overwriting its contents. The destination List must be at least as long as the source. If it is longer, the remaining elements in the destination List are unaffected.

  • swap — swaps the elements at the specified positions in a List.

  • addAll — adds all the specified elements to a Collection. The elements to be added may be specified individually or as an array.

Searching

The binarySearch algorithm searches for a specified element in a sorted List. This algorithm has two forms. The first takes a List and an element to search for (the "search key"). This form assumes that the List is sorted in ascending order according to the natural ordering of its elements. The second form takes a Comparator in addition to the List and the search key, and assumes that the List is sorted into ascending order according to the specified Comparator. The sort algorithm can be used to sort the List prior to calling binarySearch.

The return value is the same for both forms. If the List contains the search key, its index is returned. If not, the return value is (-(insertion point) - 1), where the insertion point is the point at which the value would be inserted into the List, or the index of the first element greater than the value or list.size() if all elements in the List are less than the specified value. This admittedly ugly formula guarantees that the return value will be >= 0 if and only if the search key is found. It's basically a hack to combine a boolean (found) and an integer (index) into a single int return value.

The following idiom, usable with both forms of the binarySearch operation, looks for the specified search key and inserts it at the appropriate position if it's not already present.

    int pos = Collections.binarySearch(list, key);
    if (pos < 0)
       l.add(-pos-1);

Composition

The frequency and disjoint algorithms test some aspect of the composition of one or more Collections:
  • frequency — counts the number of times the specified element occurs in the specified collection
  • disjoint — determines whether two Collections are disjoint; that is, whether they contain no elements in common

Finding Extreme Values

The min and the max algorithms return, respectively, the minimum and maximum element contained in a specified Collection. Both of these operations come in two forms. The simple form takes only a Collection and returns the minimum (or maximum) element according to the elements' natural ordering. The second form takes a Comparator in addition to the Collection and returns the minimum (or maximum) element according to the specified Comparator.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Custom Collection Implementations


Lesson: Custom Collection Implementations (The Java™ Tutorials > Collections)

Trail: Collections
Home Page > Collections
« Previous • Trail • Next »
Lesson: Custom Collection Implementations
Many programmers will never need to implement their own Collections classes. You can go pretty far using the implementations described in the preceding sections of this chapter. However, someday you might want to write your own implementation. It is fairly easy to do this with the aid of the abstract implementations provided by the Java platform. Before we discuss how to write an implementation, let's discuss why you might want to write one.

Reasons to Write an Implementation

The following list illustrates the sort of custom Collections you might want to implement. It is not intended to be exhaustive:
  • Persistent: All of the built-in Collection implementations reside in main memory and vanish when the program exits. If you want a collection that will still be present the next time the program starts, you can implement it by building a veneer over an external database. Such a collection might be concurrently accessible by multiple programs.
  • Application-specific: This is a very broad category. One example is an unmodifiable Map containing real-time telemetry data. The keys could represent locations, and the values could be read from sensors at these locations in response to the get operation.
  • High-performance, special-purpose: Many data structures take advantage of restricted usage to offer better performance than is possible with general-purpose implementations. For instance, consider a List containing long runs of identical element values. Such lists, which occur frequently in text processing, can be run-length encoded — runs can be represented as a single object containing the repeated element and the number of consecutive repetitions. This example is interesting because it trades off two aspects of performance: It requires less space but more time than an ArrayList.
  • High-performance, general-purpose: The Java Collections Framework's designers tried to provide the best general-purpose implementations for each interface, but many, many data structures could have been used, and new ones are invented every day. Maybe you can come up with something faster!
  • Enhanced functionality: Suppose you need an efficient bag implementation (also known as a multiset): a Collection that offers constant-time containment checks while allowing duplicate elements. It's reasonably straightforward to implement such a collection atop a HashMap.
  • Convenience: You may want additional implementations that offer conveniences beyond those offered by the Java platform. For instance, you may frequently need List instances representing a contiguous range of Integers.
  • Adapter: Suppose you are using a legacy API that has its own ad hoc collections' API. You can write an adapter implementation that permits these collections to operate in the Java Collections Framework. An adapter implementation is a thin veneer that wraps objects of one type and makes them behave like objects of another type by translating operations on the latter type into operations on the former.

How to Write a Custom Implementation

Writing a custom implementation is surprisingly easy. The Java Collections Framework provides abstract implementations designed expressly to facilitate custom implementations. We'll start with the following example of an implementation of Arrays.asList.
public static <T> List<T> asList(T[] a) {
    return new MyArrayList<T>(a);
}

private static class MyArrayList<T> extends AbstractList<T> {

    private final T[] a;

    MyArrayList(T[] array) {
        a = array;
    }

    public T get(int index) {
        return a[index];
    }

    public T set(int index, T element) {
        T oldValue = a[index];
        a[index] = element;
        return oldValue;
    }

    public int size() {
        return a.length;
    }
}
Believe it or not, this is very close to the implementation that is contained in java.util.Arrays. It's that simple! You provide a constructor and the get, set, and size methods, and AbstractList does all the rest. You get the ListIterator, bulk operations, search operations, hash code computation, comparison, and string representation for free.

Suppose you want to make the implementation a bit faster. The API documentation for abstract implementations describes precisely how each method is implemented, so you'll know which methods to override to get the performance you want. The preceding implementation's performance is fine, but it can be improved a bit. In particular, the toArray method iterates over the List, copying one element at a time. Given the internal representation, it's a lot faster and more sensible just to clone the array.

public Object[] toArray() {
    return (Object[]) a.clone();
}
With the addition of this override and a few more like it, this implementation is exactly the one found in java.util.Arrays. In the interest of full disclosure, it's a bit tougher to use the other abstract implementations because you will have to write your own iterator, but it's still not that difficult.

The following list summarizes the abstract implementations:

  • AbstractCollection — a Collection that is neither a Set nor a List. At a minimum, you must provide the iterator and the size methods.
  • AbstractSet — a Set; use is identical to AbstractCollection.
  • AbstractList — a List backed up by a random-access data store, such as an array. At a minimum, you must provide the positional access methods (get and, optionally, set, remove, and add) and the size method. The abstract class takes care of listIterator (and iterator).
  • AbstractSequentialList — a List backed up by a sequential-access data store, such as a linked list. At a minimum, you must provide the listIterator and size methods. The abstract class takes care of the positional access methods. (This is the opposite of AbstractList.)
  • AbstractQueue — at a minimum, you must provide the offer, peek, poll, and size methods and an iterator supporting remove.
  • AbstractMap — a Map. At a minimum you must provide the entrySet view. This is typically implemented with the AbstractSet class. If the Map is modifiable, you must also provide the put method.
The process of writing a custom implementation follows:
  1. Choose the appropriate abstract implementation class from the preceding list.

  2. Provide implementations for all the class's abstract methods. If your custom collection is to be modifiable, you'll have to override one or more of the concrete methods as well. The API documentation for the abstract implementation class will tell you which methods to override.

  3. Test and, if necessary, debug the implementation. You now have a working custom collection implementation.

  4. If you're concerned about performance, read the abstract implementation class's API documentation for all the methods whose implementations you're inheriting. If any seem too slow, override them. If you override any methods, be sure to measure the performance of the method before and after the override. How much effort you put into tweaking performance should be a function of how much use the implementation will get and how critical to performance its use is. (Often this step is best omitted.)
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Interoperability


Lesson: Interoperability (The Java™ Tutorials > Collections)

Interoperability
Compatibility
API Design
Trail: Collections
Home Page > Collections
« Previous • Trail • Next »
Lesson: Interoperability
In this section, you'll learn about the following two aspects of interoperability:
  • Compatibility: This subsection describes how collections can be made to work with older APIs that predate the addition of Collections to the Java platform.
  • API Design: This subsection describes how to design new APIs so that they'll interoperate seamlessly with one another.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Compatibility


Compatibility (The Java™ Tutorials > Collections > Interoperability)

Trail: Collections
Lesson: Interoperability
Interoperability
Compatibility
API Design
Home Page > Collections > Interoperability
« Previous • Trail • Next »
Compatibility
The Java Collections Framework was designed to ensure complete interoperability between the core collection interfaces and the types that were used to represent collections in the early versions of the Java platform: Vector, Hashtable, array, and Enumeration. In this section, you'll learn how to transform old collections to the Java Collections Framework collections and vice versa.

Upward Compatibility

Suppose that you're using an API that returns legacy collections in tandem with another API that requires objects implementing the collection interfaces. To make the two APIs interoperate smoothly, you'll have to transform the legacy collections into modern collections. Luckily, the Java Collections Framework makes this easy.

Suppose the old API returns an array of objects and the new API requires a Collection. The Collections Framework has a convenience implementation that allows an array of objects to be viewed as a List. You use Arrays.asList to pass an array to any method requiring a Collection or a List.

Foo[] result = oldMethod(arg);
newMethod(Arrays.asList(result));
If the old API returns a Vector or a Hashtable, you have no work to do at all because Vector was retrofitted to implement the List interface, and Hashtable was retrofitted to implement Map. Therefore, a Vector may be passed directly to any method calling for a Collection or a List.
Vector result = oldMethod(arg);
newMethod(result);
Similarly, a Hashtable may be passed directly to any method calling for a Map.
Hashtable result = oldMethod(arg);
newMethod(result);
Less frequently, an API may return an Enumeration that represents a collection of objects. The Collections.list method translates an Enumeration into a Collection.
Enumeration e = oldMethod(arg);
newMethod(Collections.list(e));

Backward Compatibility

Suppose you're using an API that returns modern collections in tandem with another API that requires you to pass in legacy collections. To make the two APIs interoperate smoothly, you have to transform modern collections into old collections. Again, the Java Collections Framework makes this easy.

Suppose the new API returns a Collection, and the old API requires an array of Object. As you're probably aware, the Collection interface contains a toArray method designed expressly for this situation.

Collection c = newMethod();
oldMethod(c.toArray());
What if the old API requires an array of String (or another type) instead of an array of Object? You just use the other form of toArray — the one that takes an array on input.
Collection c = newMethod();
oldMethod((String[]) c.toArray(new String[0]));
If the old API requires a Vector, the standard collection constructor comes in handy.
Collection c = newMethod();
oldMethod(new Vector(c));
The case where the old API requires a Hashtable is handled analogously.
Map m = newMethod();
oldMethod(new Hashtable(m));
Finally, what do you do if the old API requires an Enumeration? This case isn't common, but it does happen from time to time, and the Collections.enumeration method was provided to handle it. This is a static factory method that takes a Collection and returns an Enumeration over the elements of the Collection.
Collection c = newMethod();
oldMethod(Collections.enumeration(c));
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Interoperability
Next page: API Design


API Design (The Java™ Tutorials > Collections > Interoperability)

Trail: Collections
Lesson: Interoperability
Interoperability
Compatibility
API Design
Home Page > Collections > Interoperability
« Previous • Trail • Next »
API Design
In this short but important section, you'll learn a few simple guidelines that will allow your API to interoperate seamlessly with all other APIs that follow these guidelines. In essence, these rules define what it takes to be a good "citizen" in the world of collections.

Parameters

If your API contains a method that requires a collection on input, it is of paramount importance that you declare the relevant parameter type to be one of the collection interface types. Never use an implementation type because this defeats the purpose of an interface-based Collections Framework, which is to allow collections to be manipulated without regard to implementation details.

Further, you should always use the least-specific type that makes sense. For example, don't require a List or a Set if a Collection would do. It's not that you should never require a List or a Set on input; it is correct to do so if a method depends on a property of one of these interfaces. For example, many of the algorithms provided by the Java platform require a List on input because they depend on the fact that lists are ordered. As a general rule, however, the best types to use on input are the most general: Collection and Map.

Caution: Never define your own ad hoc collection class and require objects of this class on input. By doing this, you'd lose all the benefits provided by the Java Collections Framework.

Return Values

You can afford to be much more flexible with return values than with input parameters. It's fine to return an object of any type that implements or extends one of the collection interfaces. This can be one of the interfaces or a special-purpose type that extends or implements one of these interfaces.

For example, one could imagine an image-processing package, called ImageList, that returned objects of a new class that implements List. In addition to the List operations, ImageList could support any application-specific operations that seemed desirable. For example, it might provide an indexImage operation that returned an image containing thumbnail images of each graphic in the ImageList. It's critical to note that even if the API furnishes ImageList instances on output, it should accept arbitrary Collection (or perhaps List) instances on input.

In one sense, return values should have the opposite behavior of input parameters: It's best to return the most specific applicable collection interface rather than the most general. For example, if you're sure that you'll always return a SortedMap, you should give the relevant method the return type of SortedMap rather than Map. SortedMap instances are more time-consuming to build than ordinary Map instances and are also more powerful. Given that your module has already invested the time to build a SortedMap, it makes good sense to give the user access to its increased power. Furthermore, the user will be able to pass the returned object to methods that demand a SortedMap, as well as those that accept any Map.

Legacy APIs

There are currently plenty of APIs out there that define their own ad hoc collection types. While this is unfortunate, it's a fact of life, given that there was no Collections Framework in the first two major releases of the Java platform. Suppose you own one of these APIs; here's what you can do about it.

If possible, retrofit your legacy collection type to implement one of the standard collection interfaces. Then all the collections you return will interoperate smoothly with other collection-based APIs. If this is impossible (for example, because one or more of the preexisting type signatures conflict with the standard collection interfaces), define an adapter class that wraps one of your legacy collections objects, allowing it to function as a standard collection. (The Adapter class is an example of a custom implementation.)

Retrofit your API with new calls that follow the input guidelines to accept objects of a standard collection interface, if possible. Such calls can coexist with the calls that take the legacy collection type. If this is impossible, provide a constructor or static factory for your legacy type that takes an object of one of the standard interfaces and returns a legacy collection containing the same elements (or mappings). Either of these approaches will allow users to pass arbitrary collections into your API.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Compatibility
Next page: End of Trail


Trail: Internationalization (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Internationalization

The lessons in this trail teach you how to internationalize Java applications. Internationalized applications are easy to tailor to the customs and languages of end users around the world.
Note: This tutorial trail covers core internationalization functionality, which is the foundation required by additional features provided for desktop, enterprise, and mobile applications. For additional information, see the Java Internationalization home page.

Introduction defines the term internationalization, gives a quick sample program, and provides a checklist you can use to internationalize an existing program.

Setting the Locale explains how to create and how to use Locale objects.

Isolating Locale-Specific Data shows how to dynamically access objects that vary with Locale.

Formatting explains how to format numbers, dates, and text messages according to Locale, and how to create customized formats with patterns.

Working with Text provides techniques for manipulating text in a locale-independent manner.

Internationalization of Network Resources explains how to provide internationalization for IDN's and IRI's

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Introduction


Lesson: Introduction (The Java™ Tutorials > Internationalization)

Introduction
A Quick Example
Before Internationalization
After Internationalization
Running the Sample Program
Internationalizing the Sample Program
Checklist
Trail: Internationalization
Home Page > Internationalization
« Previous • Trail • Next »
Lesson: Introduction
Internationalization is the process of designing an application so that it can be adapted to various languages and regions without engineering changes. Sometimes the term internationalization is abbreviated as i18n, because there are 18 letters between the first "i" and the last "n."

An internationalized program has the following characteristics:

  • With the addition of localized data, the same executable can run worldwide.
  • Textual elements, such as status messages and the GUI component labels, are not hardcoded in the program. Instead they are stored outside the source code and retrieved dynamically.
  • Support for new languages does not require recompilation.
  • Culturally-dependent data, such as dates and currencies, appear in formats that conform to the end user's region and language.
  • It can be localized quickly.

Localization is the process of adapting software for a specific region or language by adding locale-specific components and translating text. The term localization is often abbreviated as l10n, because there are 10 letters between the "l" and the "n."

The primary task of localization is translating the user interface elements and documentation. Localization involves not only changing the language interaction, but also other relevant changes such as display of numbers, dates, currency, and so on. Other types of data, such as sounds and images, may require localization if they are culturally sensitive. The better internationalized an application is, the easier it is to localize it for a particular language and character encoding scheme.

Internationalization may seem a bit daunting at first. Reading the following sections will help ease you into the subject.

A Quick Example

This section shows you how to internationalize a simple program, step by step.

Checklist

So you've inherited a program that needs to be internationalized or you are planning to determine the requirements for a newly-developed software. You probably don't know where to start? Check out this checklist. It summarizes the necessary internationalization tasks and provides links to the relevant lessons in this chapter.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: A Quick Example


A Quick Example (The Java™ Tutorials > Internationalization > Introduction)

Trail: Internationalization
Lesson: Introduction
Introduction
A Quick Example
Before Internationalization
After Internationalization
Running the Sample Program
Internationalizing the Sample Program
Checklist
Home Page > Internationalization > Introduction
« Previous • Trail • Next »
A Quick Example
If you're new to internationalizing software, this lesson is for you. This lesson uses a simple example to demonstrate how to internationalize a program so that it displays text messages in the appropriate language. You'll learn how Locale and ResourceBundle objects work together and how to use properties files.

Before Internationalization

The first version of the source code contained hardcoded English versions of the messages we want to display. This is NOT how you write internationalized software.

After Internationalization

This is a sneak preview of what our source code will look like after internationalization.

Running the Sample Program

To run the sample program, you specify the language and country on the command line. This section shows you a few examples.

Internationalizing the Sample Program

Internationalizing the program required just a few steps. You'll be surprised at how easy it was.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Introduction
Next page: Before Internationalization


Before Internationalization (The Java™ Tutorials > Internationalization > Introduction)

Trail: Internationalization
Lesson: Introduction
Section: A Quick Example
Introduction
A Quick Example
Before Internationalization
After Internationalization
Running the Sample Program
Internationalizing the Sample Program
Checklist
Home Page > Internationalization > Introduction
« Previous • Trail • Next »
Before Internationalization
Suppose that you've written a program that displays three messages, as follows:
public class NotI18N {

    static public void main(String[] args) {

        System.out.println("Hello.");
        System.out.println("How are you?");
        System.out.println("Goodbye.");
    }
}
You've decided that this program needs to display these same messages for people living in France and Germany. Unfortunately your programming staff is not multilingual, so you'll need help translating the messages into French and German. Since the translators aren't programmers, you'll have to move the messages out of the source code and into text files that the translators can edit. Also, the program must be flexible enough so that it can display the messages in other languages, but right now no one knows what those languages will be.

It looks like the program needs to be internationalized.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: A Quick Example
Next page: After Internationalization


After Internationalization (The Java™ Tutorials > Internationalization > Introduction)

Trail: Internationalization
Lesson: Introduction
Section: A Quick Example
Introduction
A Quick Example
Before Internationalization
After Internationalization
Running the Sample Program
Internationalizing the Sample Program
Checklist
Home Page > Internationalization > Introduction
« Previous • Trail • Next »
After Internationalization
The source code for the internationalized program follows. Notice that the text of the messages is not hardcoded.
import java.util.*;

public class I18NSample {

    static public void main(String[] args) {

        String language;
        String country;

        if (args.length != 2) {
            language = new String("en");
            country = new String("US");
        } else {
            language = new String(args[0]);
            country = new String(args[1]);
        }

        Locale currentLocale;
        ResourceBundle messages;

        currentLocale = new Locale(language, country);

        messages = ResourceBundle.getBundle("MessagesBundle",
                                           currentLocale);
        System.out.println(messages.getString("greetings"));
        System.out.println(messages.getString("inquiry"));
        System.out.println(messages.getString("farewell"));
    }
}
To compile and run this program, you need these source files:
  • I18NSample.java
  • MessagesBundle.properties
  • MessagesBundle_de_DE.properties
  • MessagesBundle_en_US.properties
  • MessagesBundle_fr_FR.properties
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Before Internationalization
Next page: Running the Sample Program


Running the Sample Program (The Java™ Tutorials > Internationalization > Introduction)

Trail: Internationalization
Lesson: Introduction
Section: A Quick Example
Introduction
A Quick Example
Before Internationalization
After Internationalization
Running the Sample Program
Internationalizing the Sample Program
Checklist
Home Page > Internationalization > Introduction
« Previous • Trail • Next »
Running the Sample Program
The internationalized program is flexible; it allows the end user to specify a language and a country on the command line. In the following example the language code is fr (French) and the country code is FR (France), so the program displays the messages in French:
% java I18NSample fr FR
Bonjour.
Comment allez-vous?
Au revoir.
In the next example the language code is en (English) and the country code is US (United States) so the program displays the messages in English:
% java I18NSample en US
Hello.
How are you?
Goodbye.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: After Internationalization
Next page: Internationalizing the Sample Program


Internationalizing the Sample Program (The Java™ Tutorials > Internationalization > Introduction)

Trail: Internationalization
Lesson: Introduction
Section: A Quick Example
Introduction
A Quick Example
Before Internationalization
After Internationalization
Running the Sample Program
Internationalizing the Sample Program
Checklist
Home Page > Internationalization > Introduction
« Previous • Trail • Next »
Internationalizing the Sample Program
If you look at the internationalized source code, you'll notice that the hardcoded English messages have been removed. Because the messages are no longer hardcoded and because the language code is specified at run time, the same executable can be distributed worldwide. No recompilation is required for localization. The program has been internationalized.

You may be wondering what happened to the text of the messages or what the language and country codes mean. Don't worry. You'll learn about these concepts as you step through the process of internationalizing the sample program.

1. Create the Properties Files

A properties file stores information about the characteristics of a program or environment. A properties file is in plain-text format. You can create the file with just about any text editor.

In the example the properties files store the translatable text of the messages to be displayed. Before the program was internationalized, the English version of this text was hardcoded in the System.out.println statements. The default properties file, which is called MessagesBundle.properties, contains the following lines:

greetings = Hello
farewell = Goodbye
inquiry = How are you?
Now that the messages are in a properties file, they can be translated into various languages. No changes to the source code are required. The French translator has created a properties file called MessagesBundle_fr_FR.properties, which contains these lines:
greetings = Bonjour.
farewell = Au revoir.
inquiry = Comment allez-vous?
Notice that the values to the right side of the equal sign have been translated but that the keys on the left side have not been changed. These keys must not change, because they will be referenced when your program fetches the translated text.

The name of the properties file is important. For example, the name of the MessagesBundle_fr_FR.properties file contains the fr language code and the FR country code. These codes are also used when creating a Locale object.

2. Define the Locale

The Locale object identifies a particular language and country. The following statement defines a Locale for which the language is English and the country is the United States:
aLocale = new Locale("en","US");

The next example creates Locale objects for the French language in Canada and in France:

caLocale = new Locale("fr","CA");
frLocale = new Locale("fr","FR");

The program is flexible. Instead of using hardcoded language and country codes, the program gets them from the command line at run time:

String language = new String(args[0]);
String country = new String(args[1]);
currentLocale = new Locale(language, country);

Locale objects are only identifiers. After defining a Locale, you pass it to other objects that perform useful tasks, such as formatting dates and numbers. These objects are locale-sensitive because their behavior varies according to Locale. A ResourceBundle is an example of a locale-sensitive object.

3. Create a ResourceBundle

ResourceBundle objects contain locale-specific objects. You use ResourceBundle objects to isolate locale-sensitive data, such as translatable text. In the sample program the ResourceBundle is backed by the properties files that contain the message text we want to display.

The ResourceBundle is created as follows:

messages = ResourceBundle.getBundle("MessagesBundle",
                                   currentLocale);

The arguments passed to the getBundle method identify which properties file will be accessed. The first argument, MessagesBundle, refers to this family of properties files:

MessagesBundle_en_US.properties
MessagesBundle_fr_FR.properties
MessagesBundle_de_DE.properties

The Locale, which is the second argument of getBundle, specifies which of the MessagesBundle files is chosen. When the Locale was created, the language code and the country code were passed to its constructor. Note that the language and country codes follow MessagesBundle in the names of the properties files.

Now all you have to do is get the translated messages from the ResourceBundle.

4. Fetch the Text from the ResourceBundle

The properties files contain key-value pairs. The values consist of the translated text that the program will display. You specify the keys when fetching the translated messages from the ResourceBundle with the getString method. For example, to retrieve the message identified by the greetings key, you invoke getString as follows:
String msg1 = messages.getString("greetings");
The sample program uses the key greetings because it reflects the content of the message, but it could have used another String, such as s1 or msg1. Just remember that the key is hardcoded in the program and it must be present in the properties files. If your translators accidentally modify the keys in the properties files, getString won't be able to find the messages.

Conclusion

That's it. As you can see, internationalizing a program isn't too difficult. It requires some planning and a little extra coding, but the benefits are enormous. To provide you with an overview of the internationalization process, the sample program in this lesson was intentionally kept simple. As you read the lessons that follow, you'll learn about the more advanced internationalization features of the Java programming language.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Running the Sample Program
Next page: Checklist


Checklist (The Java™ Tutorials > Internationalization > Introduction)

Trail: Internationalization
Lesson: Introduction
Introduction
A Quick Example
Before Internationalization
After Internationalization
Running the Sample Program
Internationalizing the Sample Program
Checklist
Home Page > Internationalization > Introduction
« Previous • Trail • Next »
Checklist
Many programs are not internationalized when first written. These programs may have started as prototypes, or perhaps they were not intended for international distribution. If you must internationalize an existing program, take the following steps:

Identify Culturally Dependent Data

Text messages are the most obvious form of data that varies with culture. However, other types of data may vary with region or language. The following list contains examples of culturally dependent data:
  • Messages
  • Labels on GUI components
  • Online help
  • Sounds
  • Colors
  • Graphics
  • Icons
  • Dates
  • Times
  • Numbers
  • Currencies
  • Measurements
  • Phone numbers
  • Honorifics and personal titles
  • Postal addresses
  • Page layouts

Isolate Translatable Text in Resource Bundles

Translation is costly. You can help reduce costs by isolating the text that must be translated in ResourceBundle objects. Translatable text includes status messages, error messages, log file entries, and GUI component labels. This text is hardcoded into programs that haven't been internationalized. You need to locate all occurrences of hardcoded text that is displayed to end users. For example, you should clean up code like this:
String buttonLabel = "OK";
...
JButton okButton = new JButton(buttonLabel);

See the section Isolating Locale-Specific Data for details.

Deal with Compound Messages

Compound messages contain variable data. In the message "The disk contains 1100 files." the integer 1100 may vary. This message is difficult to translate because the position of the integer in the sentence is not the same in all languages. The following message is not translatable, because the order of the sentence elements is hardcoded by concatenation:
Integer fileCount;
...
String diskStatus = "The disk contains " + fileCount.toString()
                    + " files.";
Whenever possible, you should avoid constructing compound messages, because they are difficult to translate. However, if your application requires compound messages, you can handle them with the techniques described in the section Messages.

Format Numbers and Currencies

If your application displays numbers and currencies, you must format them in a locale-independent manner. The following code is not yet internationalized, because it will not display the number correctly in all countries:
Double amount;
TextField amountField;
...
String displayAmount = amount.toString();
amountField.setText(displayAmount);

You should replace the preceding code with a routine that formats the number correctly. The Java programming language provides several classes that format numbers and currencies. These classes are discussed in the section Numbers and Currencies.

Format Dates and Times

Date and time formats differ with region and language. If your code contains statements like the following, you need to change it:
Date currentDate = new Date();
TextField dateField;
...
String dateString = currentDate.toString();
dateField.setText(dateString);

If you use the date-formatting classes, your application can display dates and times correctly around the world. For examples and instructions, see the section Dates and Times.

Use Unicode Character Properties

The following code tries to verify that a character is a letter:
char ch;
...
if ((ch >= 'a' && ch <= 'z') ||
    (ch >= 'A' && ch <= 'Z'))       // WRONG!
Watch out for code like this, because it won't work with languages other than English. For example, the if statement misses the character ü in the German word Grün.

The Character comparison methods use the Unicode standard to identify character properties. Thus you should replace the previous code with the following:

char ch;
...
if (Character.isLetter(ch))
For more information on the Character comparison methods, see the section Checking Character Properties.

Compare Strings Properly

When sorting text you often compare strings. If the text is displayed, you shouldn't use the comparison methods of the String class. A program that hasn't been internationalized might compare strings as follows:
String target;
String candidate;
...
if (target.equals(candidate)) {
...
if (target.compareTo(candidate) < 0) {
...

The String.equals and String.compareTo methods perform binary comparisons, which are ineffective when sorting in most languages. Instead you should use the Collator class, which is described in the section Comparing Strings.

Convert Non-Unicode Text

Characters in the Java programming language are encoded in Unicode. If your application handles non-Unicode text, you might need to translate it into Unicode. For more information, see the section Converting Non-Unicode Text.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Internationalizing the Sample Program
Next page: Setting the Locale


Lesson: Setting the Locale (The Java™ Tutorials > Internationalization)

Setting the Locale
Creating a Locale
Identifying Available Locales
The Scope of a Locale
Locale-Sensitive Services SPI
Trail: Internationalization
Home Page > Internationalization
« Previous • Trail • Next »
Lesson: Setting the Locale
An internationalized program can display information differently throughout the world. For example, the program will display different messages in Paris, Tokyo, and New York. If the localization process has been fine-tuned, the program will display different messages in New York and London to account for the differences between American and British English. How does an internationalized program identify the appropriate language and region of its end users? Easy. It references a Locale object.

A Locale object is an identifier for a particular combination of language and region. If a class varies its behavior according to Locale, it is said to be locale-sensitive. For example, the NumberFormat class is locale-sensitive; the format of the number it returns depends on the Locale. Thus NumberFormat may return a number as 902 300 (France), or 902.300 (Germany), or 902,300 (United States). Locale objects are only identifiers. The real work, such as formatting and detecting word boundaries, is performed by the methods of the locale-sensitive classes.

The following sections explain how to work with Locale objects:

Creating a Locale

When creating a Locale object, you usually specify a language code and a country code. A third parameter, the variant, is optional.

Identifying Available Locales

Locale-sensitive classes support only certain Locale definitions. This section shows you how to determine which Locale definitions are supported.

The Scope of a Locale

On the Java platform you do not specify a global Locale by setting an environment variable before running the application. Instead you either rely on the default Locale or assign a Locale to each locale-sensitive object.

Locale-Sensitive Services SPI

This section explains how to enable plug-in of locale-dependent data and services. These SPIs provides support of more locales in addition to the currently available locales.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Creating a Locale


Creating a Locale (The Java™ Tutorials > Internationalization > Setting the Locale)

Trail: Internationalization
Lesson: Setting the Locale
Setting the Locale
Creating a Locale
Identifying Available Locales
The Scope of a Locale
Locale-Sensitive Services SPI
Home Page > Internationalization > Setting the Locale
« Previous • Trail • Next »
Creating a Locale
To create a Locale object, you typically specify the language code and the country code. For example, to specify the French language and the country of Canada, you would invoke the constructor as follows:
aLocale = new Locale("fr", "CA");
The next example creates Locale objects for the English language in the United States and Great Britain:
bLocale = new Locale("en", "US");
cLocale = new Locale("en", "GB");
The first argument is the language code, a pair of lowercase letters that conform to ISO-639. You can find a full list of the ISO-639 codes at http://www.ics.uci.edu/pub/ietf/http/related/iso639.txt.

The following table lists just a few of the language codes.

Sample Language Codes
Language Code | Description
de | German
en | English
fr | French
ja | Japanese
jw | Javanese
ko | Korean
zh | Chinese

The second argument of the Locale constructor is the country code. It consists of two uppercase letters and conforms to ISO-3166. A copy of ISO-3166 can be found at http://www.chemie.fu-berlin.de/diverse/doc/ISO_3166.html.

The following table contains several sample country codes.

Sample Country Codes
Country Code | Description
CN | China
DE | Germany
FR | France
IN | India
US | United States

If you need to distinguish your Locale further, you can specify a third parameter, called the variant code. Usually you specify variant codes to identify differences caused by the computing platform. For example, font differences may force you to use different characters on Windows and UNIX. You could then define the Locale objects with the variant codes WINDOWS and UNIX as follows:

xLocale = new Locale("de", "DE", "UNIX");
yLocale = new Locale("de", "DE", "WINDOWS");
The variant codes conform to no standard. They are arbitrary and specific to your application. If you create Locale objects with variant codes only your application will know how to deal with them.

The country and variant codes are optional. When omitting the country code, you specify a null String. You may create a Locale for the English language as follows:

enLocale = new Locale("en", "");

For your convenience the Locale class provides constants for some languages and countries. For example, you can create Locale objects by specifying the JAPANESE or JAPAN constants. The Locale objects created by the following two statements are equivalent:

j1Locale = Locale.JAPAN;
j2Locale = new Locale("ja", "JP");

When you specify a language constant, the country portion of the Locale is undefined. The next two statements create equivalent Locale objects:

j3Locale = Locale.JAPANESE;
j4Locale = new Locale("ja", "");
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Setting the Locale
Next page: Identifying Available Locales


Identifying Available Locales (The Java™ Tutorials > Internationalization > Setting the Locale)

Trail: Internationalization
Lesson: Setting the Locale
Setting the Locale
Creating a Locale
Identifying Available Locales
The Scope of a Locale
Locale-Sensitive Services SPI
Home Page > Internationalization > Setting the Locale
« Previous • Trail • Next »
Identifying Available Locales
You can create a Locale with any combination of valid language and country codes, but that doesn't mean that you can use it. Remember, a Locale object is only an identifier. You pass the Locale object to other objects, which then do the real work. These other objects, which we call locale-sensitive, do not know how to deal with all possible Locale definitions.

To find out which types of Locale definitions a locale-sensitive class recognizes, you invoke the getAvailableLocales method. For example, to find out which Locale definitions are supported by the DateFormat class, you could write a routine such as the following:

import java.util.*;
import java.text.*;

public class Available {
    static public void main(String[] args) {
    Locale list[] = DateFormat.getAvailableLocales();
    for (Locale aLocale : list) {
        System.out.println(aLocale.toString());
    }
    }
}

Note that the String returned by toString contains the language and country codes, separated by an underscore:

ar_EG
be_BY
bg_BG
ca_ES
cs_CZ
da_DK
de_DE
.
.
.

If you want to display a list of Locale names to end users, you should show them something easier to understand than the language and country codes returned by toString. Instead you can invoke the Locale.getDisplayName method, which retrieves a localized String of a Locale object. For example, when toString is replaced by getDisplayName in the preceding code, the program prints the following lines:

Arabic (Egypt)
Belarussian (Belarus)
Bulgarian (Bulgaria)
Catalan (Spain)
Czech (Czech Republic)
Danish (Denmark)
German (Germany)
.
.
.

You may see different locale lists depending on the Java Platform implementations.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating a Locale
Next page: The Scope of a Locale


The Scope of a Locale (The Java™ Tutorials > Internationalization > Setting the Locale)

Trail: Internationalization
Lesson: Setting the Locale
Setting the Locale
Creating a Locale
Identifying Available Locales
The Scope of a Locale
Locale-Sensitive Services SPI
Home Page > Internationalization > Setting the Locale
« Previous • Trail • Next »
The Scope of a Locale
The Java platform does not require you to use the same Locale throughout your program. If you wish, you can assign a different Locale to every locale-sensitive object in your program. This flexibility allows you to develop multilingual applications, which can display information in multiple languages.

However, most applications are not multi-lingual and their locale-sensitive objects rely on the default Locale. Set by the Java Virtual Machine when it starts up, the default Locale corresponds to the locale of the host platform. To determine the default Locale of your Java Virtual Machine, invoke the Locale.getDefault method. You should not set the default Locale programmatically because it is shared by all locale-sensitive classes.

Distributed computing raises some interesting issues. For example, suppose you are designing an application server that will receive requests from clients in various countries. If the Locale for each client is different, what should be the Locale of the server? Perhaps the server is multithreaded, with each thread set to the Locale of the client it services. Or perhaps all data passed between the server and the clients should be locale-independent.

Which design approach should you take? If possible, the data passed between the server and the clients should be locale-independent. This simplifies the design of the server by making the clients responsible for displaying the data in a locale-sensitive manner. However, this approach won't work if the server must store the data in a locale-specific form. For example, the server might store Spanish, English, and French versions of the same data in different database columns. In this case, the server might want to query the client for its Locale, since the Locale may have changed since the last request.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Identifying Available Locales
Next page: Locale-Sensitive Services SPI


Locale-Sensitive Services SPI (The Java™ Tutorials > Internationalization > Setting the Locale)

Trail: Internationalization
Lesson: Setting the Locale
Setting the Locale
Creating a Locale
Identifying Available Locales
The Scope of a Locale
Locale-Sensitive Services SPI
Home Page > Internationalization > Setting the Locale
« Previous • Trail • Next »
Locale-Sensitive Services SPI

This feature enables the plug-in of locale-dependent data and services. In this way, third parties are able to provide implementations of most locale-sensitive classes in the java.text and java.util packages.

The implementation of SPIs (Service Provider Interface) is based on abstract classes and Java interfaces that are implemented by the service provider. At runtime the Java class loading mechanism is used to dynamically locate and load classes that implement the SPI.

You can use the locale-sensitive services SPI to provide the following locale sensitive implementations:

  • BreakIterator objects
  • Collator objects
  • Language code, Country code, and Variant name for the Locale class
  • Time Zone names
  • Currency symbols
  • DateFormat objects
  • DateFormatSymbol objects
  • NumberFormat objects
  • DecimalFormatSymbols objects
The corresponding SPIs are contained both in java.text.spi and in java.util.spi packages:

java.util.spi java.text.spi
  • CurrencyNameProvider
  • LocaleServiceProvider
  • TimeZoneNameProvider
  • BreakIteratorProvider
  • CollatorProvider
  • DateFormatProvider
  • DateFormatSymbolsProvider
  • DecimalFormatSymbolsProvider
  • NumberFormatProvider

For example, if you would like to provide a NumberFormat object for a new locale, you have to implement the java.text.spi.NumberFormatProvider class. You need to extend this class and implement its methods:

  • getCurrencyInstance(Locale locale)
  • getIntegerInstance(Locale locale)
  • getNumberInstance(Locale locale)
  • getPercentInstance(Locale locale)
  Locale loc = new Locale("da", "DK");
  NumberFormat nf = NumberFormatProvider.getNumberInstance(loc);

These methods first check whether the Java runtime environment supports the
requested locale; if so, they use that support.
Otherwise, the methods call the getAvailableLocales() methods of
installed providers for the appropriate interface to find a provider
that supports the requested locale.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Scope of a Locale
Next page: Isolating Locale-Specific Data


Lesson: Isolating Locale-Specific Data (The Java™ Tutorials > Internationalization)

Isolating Locale-Specific Data
About the ResourceBundle Class
Preparing to Use a ResourceBundle
Backing a ResourceBundle with Properties Files
Using a ListResourceBundle
Customizing Resource Bundle Loading
Trail: Internationalization
Home Page > Internationalization
« Previous • Trail • Next »
Lesson: Isolating Locale-Specific Data
Locale-specific data must be tailored according to the conventions of the end user's language and region. The text displayed by a user interface is the most obvious example of locale-specific data. For example, an application with a Cancel button in the U.S. will have an Abbrechen button in Germany. In other countries this button will have other labels. Obviously you don't want to hardcode this button label. Wouldn't it be nice if you could automatically get the correct label for a given Locale? Fortunately you can, provided that you isolate the locale-specific objects in a ResourceBundle.

In this lesson you'll learn how to create and access ResourceBundle objects. If you're in a hurry to examine some coding examples, go ahead and check out the last two sections in this lesson. Then you can come back to the first two sections to get some conceptual information about ResourceBundle objects.

About the ResourceBundle Class

ResourceBundle objects contain locale-specific objects. When you need a locale-specific object, you fetch it from a ResourceBundle, which returns the object that matches the end user's Locale. This section explains how a ResourceBundle is related to a Locale, and describes the ResourceBundle subclasses.

Preparing to Use a ResourceBundle

Before you create your ResourceBundle objects, you should do a little planning. First, identify the locale-specific objects in your program. Then organize them into categories and store them in different ResourceBundle objects accordingly.

Backing a ResourceBundle with Properties Files

If your application contains String objects that need to be translated into various languages, you can store these String objects in a PropertyResourceBundle, which is backed up by a set of properties files. Since the properties files are simple text files, they can be created and maintained by your translators. You don't have to change the source code. In this section you'll learn how to set up the properties files that back up a PropertyResourceBundle.

Using a ListResourceBundle

The ListResourceBundle class, which is a subclass of ResourceBundle, manages locale-specific objects with a list. A ListResourceBundle is backed by a class file, which means that you must code and compile a new source file each time support for an additional Locale is needed. However, ListResourceBundle objects are useful because unlike properties files, they can store any type of locale-specific object. By stepping through a sample program, this section demonstrates how to use a ListResourceBundle.

Customizing Resource Bundle Loading

This section represents new capabilities to improve the ResourceBundle.getBundle factory flexibility. The ResourceBundle.Control class collaborates with the factory methods for loading resource bundles. This allows to consider every substantial step of the resource bundle-loading process and its cache control as a separate method.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: About the ResourceBundle Class


About the ResourceBundle Class (The Java™ Tutorials > Internationalization > Isolating Locale-Specific Data)

Trail: Internationalization
Lesson: Isolating Locale-Specific Data
Isolating Locale-Specific Data
About the ResourceBundle Class
Preparing to Use a ResourceBundle
Backing a ResourceBundle with Properties Files
Using a ListResourceBundle
Customizing Resource Bundle Loading
Home Page > Internationalization > Isolating Locale-Specific Data
« Previous • Trail • Next »
About the ResourceBundle Class

How a ResourceBundle is Related to a Locale

Conceptually each ResourceBundle is a set of related subclasses that share the same base name. The list that follows shows a set of related subclasses. ButtonLabel is the base name. The characters following the base name indicate the language code, country code, and variant of a Locale. ButtonLabel_en_GB, for example, matches the Locale specified by the language code for English (en) and the country code for Great Britain (GB).
ButtonLabel
ButtonLabel_de
ButtonLabel_en_GB
ButtonLabel_fr_CA_UNIX

To select the appropriate ResourceBundle, invoke the ResourceBundle.getBundle method. The following example selects the ButtonLabel ResourceBundle for the Locale that matches the French language, the country of Canada, and the UNIX platform.

Locale currentLocale = new Locale("fr", "CA", "UNIX");
ResourceBundle introLabels =
    ResourceBundle.getBundle("ButtonLabel", currentLocale);

If a ResourceBundle class for the specified Locale does not exist, getBundle tries to find the closest match. For example, if ButtonLabel_fr_CA_UNIX is the desired class and the default Locale is en_US, getBundle will look for classes in the following order:

ButtonLabel_fr_CA_UNIX
ButtonLabel_fr_CA
ButtonLabel_fr
ButtonLabel_en_US
ButtonLabel_en
ButtonLabel

Note that getBundle looks for classes based on the default Locale before it selects the base class (ButtonLabel). If getBundle fails to find a match in the preceding list of classes, it throws a MissingResourceException. To avoid throwing this exception, you should always provide a base class with no suffixes.

The ListResourceBundle and PropertyResourceBundle Subclasses

The abstract class ResourceBundle has two subclasses: PropertyResourceBundle and ListResourceBundle.

A PropertyResourceBundle is backed by a properties file. A properties file is a plain-text file that contains translatable text. Properties files are not part of the Java source code, and they can contain values for String objects only. If you need to store other types of objects, use a ListResourceBundle instead. The section Backing a ResourceBundle with Properties Files shows you how to use a PropertyResourceBundle.

The ListResourceBundle class manages resources with a convenient list. Each ListResourceBundle is backed by a class file. You can store any locale-specific object in a ListResourceBundle. To add support for an additional Locale, you create another source file and compile it into a class file. The section Using a ListResource Bundle has a coding example you may find helpful.

The ResourceBundle class is flexible. If you first put your locale-specific String objects in a PropertyResourceBundle and then later decided to use ListResourceBundle instead, there is no impact on your code. For example, the following call to getBundle will retrieve a ResourceBundle for the appropriate Locale, whether ButtonLabel is backed up by a class or by a properties file:

ResourceBundle introLabels =
    ResourceBundle.getBundle("ButtonLabel", currentLocale);

Key-Value Pairs

ResourceBundle objects contain an array of key-value pairs. You specify the key, which must be a String, when you want to retrieve the value from the ResourceBundle. The value is the locale-specific object. The keys in the following example are the OkKey and CancelKey strings:
class ButtonLabel_en extends ListResourceBundle {
    // English version
    public Object[][] getContents() {
    return contents;
    }
    static final Object[][] contents = {
    {"OkKey", "OK"},
    {"CancelKey", "Cancel"},
    };
}

To retrieve the OK String from the ResourceBundle, you would specify the appropriate key when invoking getString:

String okLabel = ButtonLabel.getString("OkKey");

A properties file contains key-value pairs. The key is on the left side of the equal sign, and the value is on the right. Each pair is on a separate line. The values may represent String objects only. The following example shows the contents of a properties file named ButtonLabel.properties:

OkKey = OK
CancelKey = Cancel
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Isolating Locale-Specific Data
Next page: Preparing to Use a ResourceBundle


Preparing to Use a ResourceBundle (The Java™ Tutorials > Internationalization > Isolating Locale-Specific Data)

Trail: Internationalization
Lesson: Isolating Locale-Specific Data
Isolating Locale-Specific Data
About the ResourceBundle Class
Preparing to Use a ResourceBundle
Backing a ResourceBundle with Properties Files
Using a ListResourceBundle
Customizing Resource Bundle Loading
Home Page > Internationalization > Isolating Locale-Specific Data
« Previous • Trail • Next »
Preparing to Use a ResourceBundle

Identifying the Locale-Specific Objects

If your application has a user interface, it contains many locale-specific objects. To get started, you should go through your source code and look for objects that vary with Locale. Your list might include objects instantiated from the following classes:
  • String
  • Image
  • Color
  • AudioClip

You'll notice that this list doesn't contain objects representing numbers, dates, times, or currencies. The display format of these objects varies with Locale, but the objects themselves do not. For example, you format a Date according to Locale, but you use the same Date object regardless of Locale. Instead of isolating these objects in a ResourceBundle, you format them with special locale-sensitive formatting classes. You'll learn how to do this in the Dates and Times section of the Formatting lesson.

In general, the objects stored in a ResourceBundle are predefined and ship with the product. These objects are not modified while the program is running. For instance, you should store a Menu label in a ResourceBundle because it is locale-specific and will not change during the program session. However, you should not isolate in a ResourceBundle a String object the end user enters in a TextField. Data such as this String may vary from day to day. It is specific to the program session, not to the Locale in which the program runs.

Usually most of the objects you need to isolate in a ResourceBundle are String objects. However, not all String objects are locale-specific. For example, if a String is a protocol element used by interprocess communication, it doesn't need to be localized, because the end users never see it.

The decision whether to localize some String objects is not always clear. Log files are a good example. If a log file is written by one program and read by another, both programs are using the log file as a buffer for communication. Suppose that end users occasionally check the contents of this log file. Shouldn't the log file be localized? On the other hand, if end users rarely check the log file, the cost of translation may not be worthwhile. Your decision to localize this log file depends on a number of factors: program design, ease of use, cost of translation, and supportability.

Organizing ResourceBundle Objects

You can organize your ResourceBundle objects according to the category of objects they contain. For example, you might want to load all of the GUI labels for an order entry window into a ResourceBundle called OrderLabelsBundle. Using multiple ResourceBundle objects offers several advantages:
  • Your code is easier to read and to maintain.
  • You'll avoid huge ResourceBundle objects, which may take too long to load into memory.
  • You can reduce memory usage by loading each ResourceBundle only when needed.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: About the ResourceBundle Class
Next page: Backing a ResourceBundle with Properties Files


Backing a ResourceBundle with Properties Files (The Java™ Tutorials > Internationalization > Isolating Locale-Specific Data)

Trail: Internationalization
Lesson: Isolating Locale-Specific Data
Isolating Locale-Specific Data
About the ResourceBundle Class
Preparing to Use a ResourceBundle
Backing a ResourceBundle with Properties Files
Using a ListResourceBundle
Customizing Resource Bundle Loading
Home Page > Internationalization > Isolating Locale-Specific Data
« Previous • Trail • Next »
Backing a ResourceBundle with Properties Files
This section steps through a sample program named PropertiesDemo.

1. Create the Default Properties File

A properties file is a simple text file. You can create and maintain a properties file with just about any text editor.

You should always create a default properties file. The name of this file begins with the base name of your ResourceBundle and ends with the .properties suffix. In the PropertiesDemo program the base name is LabelsBundle. Therefore the default properties file is called LabelsBundle.properties. This file contains the following lines:

# This is the default LabelsBundle.properties file
s1 = computer
s2 = disk
s3 = monitor
s4 = keyboard
Note that in the preceding file the comment lines begin with a pound sign (#). The other lines contain key-value pairs. The key is on the left side of the equal sign and the value is on the right. For instance, s2 is the key that corresponds to the value disk. The key is arbitrary. We could have called s2 something else, like msg5 or diskID. Once defined, however, the key should not change because it is referenced in the source code. The values may be changed. In fact, when your localizers create new properties files to accommodate additional languages, they will translate the values into various languages.

2. Create Additional Properties Files as Needed

To support an additional Locale, your localizers will create a new properties file that contains the translated values. No changes to your source code are required, because your program references the keys, not the values.

For example, to add support for the German language, your localizers would translate the values in LabelsBundle.properties and place them in a file named LabelsBundle_de.properties. Notice that the name of this file, like that of the default file, begins with the base name LabelsBundle and ends with the .properties suffix. However, since this file is intended for a specific Locale, the base name is followed by the language code (de). The contents of LabelsBundle_de.properties are as follows:

# This is the LabelsBundle_de.properties file
s1 = Computer
s2 = Platte
s3 = Monitor
s4 = Tastatur
The PropertiesDemo sample program ships with three properties files:
LabelsBundle.properties
LabelsBundle_de.properties
LabelsBundle_fr.properties

3. Specify the Locale

The PropertiesDemo program creates the Locale objects as follows:
Locale[] supportedLocales = {
    Locale.FRENCH,
    Locale.GERMAN,
    Locale.ENGLISH
};
These Locale objects should match the properties files created in the previous two steps. For example, the Locale.FRENCH object corresponds to the LabelsBundle_fr.properties file. The Locale.ENGLISH has no matching LabelsBundle_en.properties file, so the default file will be used.

4. Create the ResourceBundle

This step shows how the Locale, the properties files, and the ResourceBundle are related. To create the ResourceBundle, invoke the getBundlemethod, specifying the base name and Locale:
ResourceBundle labels =
    ResourceBundle.getBundle("LabelsBundle", currentLocale);

The getBundle method first looks for a class file that matches the base name and the Locale. If it can't find a class file, it then checks for properties files. In the PropertiesDemo program we're backing the ResourceBundle with properties files instead of class files. When the getBundle method locates the correct properties file, it returns a PropertyResourceBundle object containing the key-value pairs from the properties file.

5. Fetch the Localized Text

To retrieve the translated value from the ResourceBundle, invoke the getString method as follows:
String value = labels.getString(key);

The String returned by getString corresponds to the key specified. The String is in the proper language, provided that a properties file exists for the specified Locale.

6. Iterate through All the Keys

This step is optional. When debugging your program, you might want to fetch values for all of the keys in a ResourceBundle. The getKeys method returns an Enumeration of all the keys in a ResourceBundle. You can iterate through the Enumeration and fetch each value with the getString method. The following lines of code, which are from the PropertiesDemo program, show how this is done:
ResourceBundle labels =
    ResourceBundle.getBundle("LabelsBundle", currentLocale);
Enumeration bundleKeys = labels.getKeys();

while (bundleKeys.hasMoreElements()) {
    String key = (String)bundleKeys.nextElement();
    String value = labels.getString(key);
    System.out.println("key = " + key + ", " +
               "value = " + value);
}

7. Run the Demo Program

Running the PropertiesDemo program generates the following output. The first three lines show the values returned by getString for various Locale objects. The program displays the last four lines when iterating through the keys with the getKeys method.
Locale = fr, key = s2, value = Disque dur
Locale = de, key = s2, value = Platte
Locale = en, key = s2, value = disk

key = s4, value = Clavier
key = s3, value = Moniteur
key = s2, value = Disque dur
key = s1, value = Ordinateur
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Preparing to Use a ResourceBundle
Next page: Using a ListResourceBundle


Using a ListResourceBundle (The Java™ Tutorials > Internationalization > Isolating Locale-Specific Data)

Trail: Internationalization
Lesson: Isolating Locale-Specific Data
Isolating Locale-Specific Data
About the ResourceBundle Class
Preparing to Use a ResourceBundle
Backing a ResourceBundle with Properties Files
Using a ListResourceBundle
Customizing Resource Bundle Loading
Home Page > Internationalization > Isolating Locale-Specific Data
« Previous • Trail • Next »
Using a ListResourceBundle
This section illustrates the use of a ListResourceBundle object with a sample program called ListDemo. The text that follows explains each step involved in creating the ListDemo program, along with the ListResourceBundle subclasses that support it.

1. Create the ListResourceBundle Subclasses

A ListResourceBundle is backed up by a class file. Therefore the first step is to create a class file for every supported Locale. In the ListDemo program the base name of the ListResourceBundle is StatsBundle. Since ListDemo supports three Locale objects, it requires the following three class files:
StatsBundle_en_CA.class
StatsBundle_fr_FR.class
StatsBundle_ja_JP.class

The StatsBundle class for Japan is defined in the source code that follows. Note that the class name is constructed by appending the language and country codes to the base name of the ListResourceBundle. Inside the class the two-dimensional contents array is initialized with the key-value pairs. The keys are the first element in each pair: GDP, Population, and Literacy. The keys must be String objects and they must be the same in every class in the StatsBundle set. The values can be any type of object. In this example the values are two Integer objects and a Double object.

import java.util.*;
public class StatsBundle_ja_JP extends ListResourceBundle {
    public Object[][] getContents() {
    return contents;
    }
    private Object[][] contents = {
    { "GDP", new Integer(21300) },
    { "Population", new Integer(125449703) },
    { "Literacy", new Double(0.99) },
    };
}

2. Specify the Locale

The ListDemo program defines the Locale objects as follows:
Locale[] supportedLocales = {
    new Locale("en", "CA"),
    new Locale("ja", "JP"),
    new Locale("fr", "FR")
};
Each Locale object corresponds to one of the StatsBundle classes. For example, the Japanese Locale, which was defined with the ja and JP codes, matches StatsBundle_ja_JP.class.

3. Create the ResourceBundle

To create the ListResourceBundle, invoke the getBundle method. The following line of code specifies the base name of the class (StatsBundle) and the Locale:
ResourceBundle stats =
        ResourceBundle.getBundle("StatsBundle", currentLocale);

The getBundle method searches for a class whose name begins with StatsBundle and is followed by the language and country codes of the specified Locale. If the currentLocale is created with the ja and JP codes, getBundle returns a ListResourceBundle corresponding to the class StatsBundle_ja_JP, for example.

4. Fetch the Localized Objects

Now that the program has a ListResourceBundle for the appropriate Locale, it can fetch the localized objects by their keys. The following line of code retrieves the literacy rate by invoking getObject with the Literacy key parameter. Since getObject returns an object, cast it to a Double:
Double lit = (Double)stats.getObject("Literacy");

5. Run the Demo Program

ListDemo program prints the data it fetched with the getBundle method:
Locale = en_CA
GDP = 24400
Population = 28802671
Literacy = 0.97

Locale = ja_JP
GDP = 21300
Population = 125449703
Literacy = 0.99

Locale = fr_FR
GDP = 20200
Population = 58317450
Literacy = 0.99
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Backing a ResourceBundle with Properties Files
Next page: Customizing Resource Bundle Loading


Customizing Resource Bundle Loading (The Java™ Tutorials > Internationalization > Isolating Locale-Specific Data)

Trail: Internationalization
Lesson: Isolating Locale-Specific Data
Isolating Locale-Specific Data
About the ResourceBundle Class
Preparing to Use a ResourceBundle
Backing a ResourceBundle with Properties Files
Using a ListResourceBundle
Customizing Resource Bundle Loading
Home Page > Internationalization > Isolating Locale-Specific Data
« Previous • Trail • Next »
Customizing Resource Bundle Loading

Earlier in this lesson you have learned how to create and access objects of the ResourceBundle class. This section extents your knowledge and explains how to take an advantage from the ResourceBundle.Controlclass capabilities.

The ResourceBundle.Control was created to specify how to locate and instantiate resource bundles. It defines a set of callback methods that are invoked by the ResourceBundle.getBundlefactory methods during the bundle loading process.

Unlike a ResourceBundle.getBundlemethod described earlier, this ResourceBundle.getBundle method defines a resource bundle using the specified base name, the default locale and the specified control.

public static final ResourceBundle getBundle(String baseName,
                           ResourceBundle.Control cont
                           ...

The specified control provide information for the resource bundle loading process.

The following sample program called RBControl.javaillustrates how to define your own search paths for Chinese locales.

1. Create the properties Files.

As it was described before you can load your resources either from classes or from properties files. These files contain descriptions for the following locales:

  • RBControl.properties – Global
  • RBControl_zh.properties – Language only: Simplified Chineese
  • RBControl_zh_cn.properties – Region only: China
  • RBControl_zh_hk.properties – Region only: Hong Kong
  • RBControl_zh_tw.properties – Taiwan

In this example an application creates a new locale for the Hong Kong region.

2. Create a ResourceBundle instance.

As in the example in the previous section, this application creates a ResourceBundle instance by invoking the getBundle method:

   private static void test(Locale locale) {
       ResourceBundle rb = ResourceBundle.getBundle("RBControl", locale,
            new ResourceBundle.Control() {
        ...

The getBundle method searches for properties files with the RBControl prefix. However, this method contains a Control parameter, which drives the process of searching the Chineese locales.

3. Invoke the getCandidateLocales method

The getCandidateLocales method returns a list of the Locales objects as candidate locales for the base name and locale.

  new ResourceBundle.Control() {
         @Override
         public List<Locale> getCandidateLocales(String baseName,
                                                 Locale locale) {
         ...

The default implementation returns a list of the Locale objects as follows: Locale(language, country).

However, this method is overriden to implement the following specific behavior:

                     {
                     if (baseName == null)
             throw new NullPointerException();
             if (locale.equals(new Locale("zh", "HK"))) {
             return Arrays.asList(
                 locale,
                 Locale.TAIWAN,
                 // no Locale.CHINESE here
                 Locale.ROOT);
             } else if (locale.equals(Locale.TAIWAN)) {
             return Arrays.asList(
                 locale,
                 // no Locale.CHINESE here
                 Locale.ROOT);
             }
Note, that the last element of the sequence of candidate locales must be a root locale.

4. Call the test class

Call the test class for the following four different locales:

   public static void main(String[] args) {
    test(Locale.CHINA);
    test(new Locale("zh", "HK"));
    test(Locale.TAIWAN);
    test(Locale.CANADA);
    }

5. Run the Sample Program

You will see the program output as follows:
locale: zh_CN
    region: China
    language: Simplified Chinese
locale: zh_HK
    region: Hong Kong
    language: Traditional Chinese
locale: zh_TW
    region: Taiwan
    language: Traditional Chinese
locale: en_CA
    region: global
    language: English

Note that the newly created was assigned the Hong Kong region, because it was specified in an appropriate properties file. Traditional Chinese was assigned as the language for the Taiwan locale.

Two other interesting methods of the ResourceBundle.Control class were not used in the RBControl example, but they deserved to be mentioned. The getTimeToLive method is used to determine how long the resource bundle can exist in the cache. If the time limit for a resource bundle in the cache has expired, the needsReload method is invoked to determine whether the resource bundle needs to be reloaded.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using a ListResourceBundle
Next page: Formatting


Lesson: Formatting (The Java™ Tutorials > Internationalization)

Formatting
Numbers and Currencies
Using Predefined Formats
Customizing Formats
Dates and Times
Using Predefined Formats
Customizing Formats
Changing Date Format Symbols
Messages
Dealing with Compound Messages
Handling Plurals
Trail: Internationalization
Home Page > Internationalization
« Previous • Trail • Next »
Lesson: Formatting
This lesson explains how to format numbers, currencies, dates, times, and text messages. Because end users can see these data elements, their format must conform to various cultural conventions. Following the examples in this lesson will teach you how to:
  • Format data elements in a locale-sensitive manner
  • Keep your code locale-independent
  • Avoid the need to write formatting routines for specific locales

Numbers and Currencies

This section explains how to use the NumberFormat, DecimalFormat, and DecimalFormatSymbols classes.

Dates and Times

This section focuses on the DateFormat, SimpleDateFormat, and DateFormatSymbols classes.

Messages

This section shows how the MessageFormat and ChoiceFormat classes can help you solve some of the problems you might encounter when formatting text messages.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Numbers and Currencies


Numbers and Currencies (The Java™ Tutorials > Internationalization > Formatting)

Trail: Internationalization
Lesson: Formatting
Formatting
Numbers and Currencies
Using Predefined Formats
Customizing Formats
Dates and Times
Using Predefined Formats
Customizing Formats
Changing Date Format Symbols
Messages
Dealing with Compound Messages
Handling Plurals
Home Page > Internationalization > Formatting
« Previous • Trail • Next »
Numbers and Currencies
Programs store and operate on numbers in a locale-independent way. Before displaying or printing a number, a program must convert it to a String that is in a locale-sensitive format. For example, in France the number 123456.78 should be formatted as 123 456,78, and in Germany it should appear as 123.456,78. In this section, you will learn how to make your programs independent of the locale conventions for decimal points, thousands-separators, and other formatting properties.

Using Predefined Formats

Using the factory methods provided by the NumberFormat class, you can get locale-specific formats for numbers, currencies, and percentages.

Formatting with Patterns

With the DecimalFormat class you specify a number's format with a String pattern. The DecimalFormatSymbols class allows you to modify formatting symbols such as decimal separators and minus signs.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Formatting
Next page: Using Predefined Formats


Using Predefined Formats (The Java™ Tutorials > Internationalization > Formatting)

Trail: Internationalization
Lesson: Formatting
Section: Numbers and Currencies
Formatting
Numbers and Currencies
Using Predefined Formats
Customizing Formats
Dates and Times
Using Predefined Formats
Customizing Formats
Changing Date Format Symbols
Messages
Dealing with Compound Messages
Handling Plurals
Home Page > Internationalization > Formatting
« Previous • Trail • Next »
Using Predefined Formats
By invoking the methods provided by the NumberFormat class, you can format numbers, currencies, and percentages according to Locale. The material that follows demonstrates formatting techniques with a sample program called NumberFormatDemo.

Numbers

You can use the NumberFormat methods to format primitive-type numbers, such as double, and their corresponding wrapper objects, such as Double.

The following code example formats a Double according to Locale. Invoking the getNumberInstance method returns a locale-specific instance of NumberFormat. The format method accepts the Double as an argument and returns the formatted number in a String.

Double amount = new Double(345987.246);
NumberFormat numberFormatter;
String amountOut;

numberFormatter = NumberFormat.getNumberInstance(currentLocale);
amountOut = numberFormatter.format(amount);
System.out.println(amountOut + " " +
                   currentLocale.toString());

The output from this example shows how the format of the same number varies with Locale:

345 987,246	 fr_FR
345.987,246	 de_DE
345,987.246	 en_US

Currencies

If you're writing business applications, you'll probably need to format and to display currencies. You format currencies in the same manner as numbers, except that you call getCurrencyInstance to create a formatter. When you invoke the format method, it returns a String that includes the formatted number and the appropriate currency sign.

This code example shows how to format currency in a locale-specific manner:

Double currency = new Double(9876543.21);
NumberFormat currencyFormatter;
String currencyOut;

currencyFormatter = NumberFormat.getCurrencyInstance(currentLocale);
currencyOut = currencyFormatter.format(currency);
System.out.println(currencyOut + " " +
                   currentLocale.toString());

The output generated by the preceding lines of code is as follows:

9 876 543,21 F	 fr_FR
9.876.543,21 DM	 de_DE
$9,876,543.21	 en_US

At first glance this output may look wrong to you, because the numeric values are all the same. Of course, 9 876 543,21 F is not equivalent to 9.876.543,21 DM. However, bear in mind that the NumberFormat class is unaware of exchange rates. The methods belonging to the NumberFormat class format currencies but do not convert them.

Percentages

You can also use the methods of the NumberFormat class to format percentages. To get the locale-specific formatter, invoke the getPercentInstance method. With this formatter, a decimal fraction such as 0.75 is displayed as 75%.

The following code sample shows how to format a percentage.

Double percent = new Double(0.75);
NumberFormat percentFormatter;
String percentOut;

percentFormatter = NumberFormat.getPercentInstance(currentLocale);
percentOut = percentFormatter.format(percent);
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Numbers and Currencies
Next page: Customizing Formats


Customizing Formats (The Java™ Tutorials > Internationalization > Formatting)

Trail: Internationalization
Lesson: Formatting
Section: Numbers and Currencies
Formatting
Numbers and Currencies
Using Predefined Formats
Customizing Formats
Dates and Times
Using Predefined Formats
Customizing Formats
Changing Date Format Symbols
Messages
Dealing with Compound Messages
Handling Plurals
Home Page > Internationalization > Formatting
« Previous • Trail • Next »
Customizing Formats
You can use the DecimalFormat class to format decimal numbers into locale-specific strings. This class allows you to control the display of leading and trailing zeros, prefixes and suffixes, grouping (thousands) separators, and the decimal separator. If you want to change formatting symbols, such as the decimal separator, you can use the DecimalFormatSymbols in conjunction with the DecimalFormat class. These classes offer a great deal of flexibility in the formatting of numbers, but they can make your code more complex.

The text that follows uses examples that demonstrate the DecimalFormat and DecimalFormatSymbols classes. The code examples in this material are from a sample program called DecimalFormatDemo.

Constructing Patterns

You specify the formatting properties of DecimalFormat with a pattern String. The pattern determines what the formatted number looks like. For a full description of the pattern syntax, see Number Format Pattern Syntax.

The example that follows creates a formatter by passing a pattern String to the DecimalFormat constructor. The format method accepts a double value as an argument and returns the formatted number in a String:

DecimalFormat myFormatter = new DecimalFormat(pattern);
String output = myFormatter.format(value);
System.out.println(value + " " + pattern + " " + output);
The output for the preceding lines of code is described in the following table. The value is the number, a double , that is to be formatted. The pattern is the String that specifies the formatting properties. The output, which is a String, represents the formatted number.

Output from DecimalFormatDemo Program
value | pattern | output | Explanation
123456.789 ###,###.### 123,456.789 The pound sign (#) denotes a digit, the comma is a placeholder for the grouping separator, and the period is a placeholder for the decimal separator.
123456.789 ###.## 123456.79 The value has three digits to the right of the decimal point, but the pattern has only two. The format method handles this by rounding up.
123.78 | 000000.000 | 000123.780 | The pattern specifies leading and trailing zeros, because the 0 character is used instead of the pound sign (#).
12345.67 $###,###.### $12,345.67 The first character in the pattern is the dollar sign ($). Note that it immediately precedes the leftmost digit in the formatted output.
12345.67 | \u00A5###,###.### | ¥12,345.67 | The pattern specifies the currency sign for Japanese yen (¥) with the Unicode value 00A5.

Locale-Sensitive Formatting

The preceding example created a DecimalFormat object for the default Locale. If you want a DecimalFormat object for a nondefault Locale, you instantiate a NumberFormat and then cast it to DecimalFormat. Here's an example:
NumberFormat nf = NumberFormat.getNumberInstance(loc);
DecimalFormat df = (DecimalFormat)nf;
df.applyPattern(pattern);
String output = df.format(value);
System.out.println(pattern + " " + output + " " +
               loc.toString());

Running the previous code example results in the output that follows. The formatted number, which is in the second column, varies with Locale:

###,###.###	 123,456.789	 en_US
###,###.###	 123.456,789	 de_DE
###,###.###	 123 456,789	 fr_FR

So far the formatting patterns discussed here follow the conventions of U.S. English. For example, in the pattern ###,###.## the comma is the thousands-separator and the period represents the decimal point. This convention is fine, provided that your end users aren't exposed to it. However, some applications, such as spreadsheets and report generators, allow the end users to define their own formatting patterns. For these applications the formatting patterns specified by the end users should use localized notation. In these cases you'll want to invoke the applyLocalizedPattern method on the DecimalFormat object.

Altering the Formatting Symbols

You can use the DecimalFormatSymbols class to change the symbols that appear in the formatted numbers produced by the format method. These symbols include the decimal separator, the grouping separator, the minus sign, and the percent sign, among others.

The next example demonstrates the DecimalFormatSymbols class by applying a strange format to a number. The unusual format is the result of the calls to the setDecimalSeparator, setGroupingSeparator, and setGroupingSize methods.

DecimalFormatSymbols unusualSymbols =
    new DecimalFormatSymbols(currentLocale);
unusualSymbols.setDecimalSeparator('|');
unusualSymbols.setGroupingSeparator('^');

String strange = "#,##0.###";
DecimalFormat weirdFormatter =
               new DecimalFormat(strange, unusualSymbols);
weirdFormatter.setGroupingSize(4);

String bizarre = weirdFormatter.format(12345.678);
System.out.println(bizarre);

When run, this example prints the number in a bizarre format:

1^2345|678

Number Format Pattern Syntax

You can design your own format patterns for numbers by following the rules specified by the following BNF diagram:
pattern    := subpattern{;subpattern}
subpattern := {prefix}integer{.fraction}{suffix}
prefix     := '\\u0000'..'\\uFFFD' - specialCharacters
suffix     := '\\u0000'..'\\uFFFD' - specialCharacters
integer    := '#'* '0'* '0'
fraction   := '0'* '#'*
The notation used in the preceding diagram is explained in the following table:
Notation Description
X*
 0 or more instances of X
(X | Y)
 either X or Y
X..Y
 any character from X up to Y, inclusive
S - T
 characters in S, except those in T
{X}
 X is optional
In the preceding BNF diagram, the first subpattern specifies the format for positive numbers. The second subpattern, which is optional, specifies the format for negative numbers.

Although not noted in the BNF diagram, a comma may appear within the integer portion.

Within the subpatterns, you specify formatting with special symbols. These symbols are described in the following table:

Symbol | Description
0 | a digit
# a digit, zero shows as absent
. placeholder for decimal separator
, placeholder for grouping separator
E | separates mantissa and exponent for exponential formats
; separates formats
- default negative prefix
% multiply by 100 and show as percentage
? multiply by 1000 and show as per mille
¤ currency sign; replaced by currency symbol; if doubled, replaced by international currency symbol; if present in a pattern, the monetary decimal separator is used instead of the decimal separator
X | any other characters can be used in the prefix or suffix
' used to quote special characters in a prefix or suffix
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Predefined Formats
Next page: Dates and Times


Dates and Times (The Java™ Tutorials > Internationalization > Formatting)

Trail: Internationalization
Lesson: Formatting
Formatting
Numbers and Currencies
Using Predefined Formats
Customizing Formats
Dates and Times
Using Predefined Formats
Customizing Formats
Changing Date Format Symbols
Messages
Dealing with Compound Messages
Handling Plurals
Home Page > Internationalization > Formatting
« Previous • Trail • Next »
Dates and Times
Date objects represent dates and times. You cannot display or print a Date object without first converting it to a String that is in the proper format. Just what is the "proper" format? First, the format should conform to the conventions of the end user's Locale. For example, Germans recognize 20.4.98 as a valid date, but Americans expect that same date to appear as 4/20/98. Second, the format should include the necessary information. For instance, a program that measures network performance may report on elapsed milliseconds. An online appointment calendar probably won't display milliseconds, but it will show the days of the week.

This section explains how to format dates and times in various ways and in a locale-sensitive manner. If you follow these techniques your programs will display dates and times in the appropriate Locale, but your source code will remain independent of any specific Locale.

Using Predefined Formats

The DateFormat class provides predefined formatting styles that are locale-specific and easy to use.

Customizing Formats

With the SimpleDateFormat class, you can create customized, locale-specific formats.

Changing Date Format Symbols

Using the DateFormatSymbols class, you can change the symbols that represent the names of months, days of the week, and other formatting elements.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Customizing Formats
Next page: Using Predefined Formats


Using Predefined Formats (The Java™ Tutorials > Internationalization > Formatting)

Trail: Internationalization
Lesson: Formatting
Section: Dates and Times
Formatting
Numbers and Currencies
Using Predefined Formats
Customizing Formats
Dates and Times
Using Predefined Formats
Customizing Formats
Changing Date Format Symbols
Messages
Dealing with Compound Messages
Handling Plurals
Home Page > Internationalization > Formatting
« Previous • Trail • Next »
Using Predefined Formats
The DateFormat class allows you to format dates and times with predefined styles in a locale-sensitive manner. The sections that follow demonstrate how to use the DateFormat class with a program called DateFormatDemo.java.

Dates

Formatting dates with the DateFormat class is a two-step process. First, you create a formatter with the getDateInstance method. Second, you invoke the format method, which returns a String containing the formatted date. The following example formats today's date by calling these two methods:
Date today;
String dateOut;
DateFormat dateFormatter;

dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT,
                       currentLocale);
today = new Date();
dateOut = dateFormatter.format(today);

System.out.println(dateOut + " " + currentLocale.toString());

The output generated by this code follows. Notice that the formats of the dates vary with Locale. Since DateFormat is locale-sensitive, it takes care of the formatting details for each Locale.

9 avr 98	 fr_FR
9.4.1998	 de_DE
09-Apr-98	 en_US

The preceding code example specified the DEFAULT formatting style. The DEFAULT style is just one of the predefined formatting styles that the DateFormat class provides, as follows:

  • DEFAULT
  • SHORT
  • MEDIUM
  • LONG
  • FULL

The following table shows how dates are formatted for each style with the U.S. and French locales:

Sample Date Formats
Style | U.S. Locale | French Locale
DEFAULT | 10-Apr-98 | 10 avr 98
SHORT | 4/10/98 | 10/04/98
MEDIUM | 10-Apr-98 | 10 avr 98
LONG | April 10, 1998 | 10 avril 1998
FULL | Friday, April 10, 1998 | vendredi, 10 avril 1998

Times

Date objects represent both dates and times. Formatting times with the DateFormat class is similar to formatting dates, except that you create the formatter with the getTimeInstance method, as follows:
DateFormat timeFormatter =
    DateFormat.getTimeInstance(DateFormat.DEFAULT,
                               currentLocale);

The table that follows shows the various predefined format styles for the U.S. and German locales:

Sample Time Formats
Style | U.S. Locale | German Locale
DEFAULT | 3:58:45 PM | 15:58:45
SHORT | 3:58 PM | 15:58
MEDIUM | 3:58:45 PM | 15:58:45
LONG | 3:58:45 PM PDT | 15:58:45 GMT+02:00
FULL | 3:58:45 oclock PM PDT | 15.58 Uhr GMT+02:00

Both Dates and Times

To display a date and time in the same String, create the formatter with the getDateTimeInstance method. The first parameter is the date style, and the second is the time style. The third parameter is the Locale . Here's a quick example:
DateFormat formatter =
    DateFormat.getDateTimeInstance(DateFormat.LONG,
                                   DateFormat.LONG,
                                   currentLocale);

The following table shows the date and time formatting styles for the U.S. and French locales:

Sample Date and Time Formats
Style | U.S. Locale | French Locale
DEFAULT | 25-Jun-98 1:32:19 PM | 25 jun 98 22:32:20
SHORT | 6/25/98 1:32 PM | 25/06/98 22:32
MEDIUM | 25-Jun-98 1:32:19 PM | 25 jun 98 22:32:20
LONG | June 25, 1998 1:32:19 PM PDT | 25 juin 1998 22:32:20 GMT+02:00
FULL | Thursday, June 25, 1998 1:32:19 o'clock PM PDT | jeudi, 25 juin 1998 22 h 32 GMT+02:00

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Dates and Times
Next page: Customizing Formats


Customizing Formats (The Java™ Tutorials > Internationalization > Formatting)

Trail: Internationalization
Lesson: Formatting
Section: Dates and Times
Formatting
Numbers and Currencies
Using Predefined Formats
Customizing Formats
Dates and Times
Using Predefined Formats
Customizing Formats
Changing Date Format Symbols
Messages
Dealing with Compound Messages
Handling Plurals
Home Page > Internationalization > Formatting
« Previous • Trail • Next »
Customizing Formats
The previous section, Using Predefined Formats, described the formatting styles provided by the DateFormat class. In most cases these predefined formats are adequate. However, if you want to create your own customized formats, you can use the SimpleDateFormat class.

The code examples that follow demonstrate the methods of the SimpleDateFormat class. You can find the full source code for the examples in the file named SimpleDateFormatDemo.

About Patterns

When you create a SimpleDateFormat object, you specify a pattern String. The contents of the pattern String determine the format of the date and time. For a full description of the pattern's syntax, see the tables in Date Format Pattern Syntax.

The following code formats a date and time according to the pattern String passed to the SimpleDateFormat constructor. The String returned by the format method contains the formatted date and time that are to be displayed.

Date today;
String output;
SimpleDateFormat formatter;

formatter = new SimpleDateFormat(pattern, currentLocale);
today = new Date();
output = formatter.format(today);
System.out.println(pattern + " " + output);

The following table shows the output generated by the previous code example when the U.S. Locale is specified:

Customized Date and Time Formats
Pattern | Output
dd.MM.yy | 09.04.98
yyyy.MM.dd G 'at' hh:mm:ss z | 1998.04.09 AD at 06:15:55 PDT
EEE, MMM d, ''yy | Thu, Apr 9, '98
h:mm a | 6:15 PM
H:mm | 18:15
H:mm:ss:SSS | 18:15:55:624
K:mm a,z | 6:15 PM,PDT
yyyy.MMMMM.dd GGG hh:mm aaa | 1998.April.09 AD 06:15 PM

Patterns and Locale

The SimpleDateFormat class is locale-sensitive. If you instantiate SimpleDateFormat without a Locale parameter, it will format the date and time according to the default Locale. Both the pattern and the Locale determine the format. For the same pattern, SimpleDateFormat may format a date and time differently if the Locale varies.

In the example code that follows, the pattern is hardcoded in the statement that creates the SimpleDateFormat object:

Date today;
String result;
SimpleDateFormat formatter;

formatter = new SimpleDateFormat("EEE d MMM yy",
                 currentLocale);
today = new Date();
result = formatter.format(today);
System.out.println("Locale: " + currentLocale.toString());
System.out.println("Result: " + result);

When the currentLocale is set to different values, the preceding code example generates this output:

Locale: fr_FR
Result: ven 10 avr 98
Locale: de_DE
Result: Fr 10 Apr 98
Locale: en_US
Result: Thu 9 Apr 98

Date Format Pattern Syntax

You can design your own format patterns for dates and times from the list of symbols in the following table:
Symbol | Meaning | Presentation | Example
G | era designator | Text | AD
y | year | Number | 1996
M | month in year | Text & Number | July & 07
d | day in month | Number | 10
h | hour in am/pm (1-12) | Number | 12
H | hour in day (0-23) | Number | 0
m | minute in hour | Number | 30
s | second in minute | Number | 55
S | millisecond | Number | 978
E | day in week | Text | Tuesday
D | day in year | Number | 189
F | day of week in month | Number | 2 (2nd Wed in July)
w | week in year | Number | 27
W | week in month | Number | 2
a | am/pm marker | Text | PM
k | hour in day (1-24) | Number | 24
K | hour in am/pm (0-11) | Number | 0
z | time zone | Text | Pacific Standard Time
' escape for text Delimiter (none)
' single quote Literal '
Characters that are not letters are treated as quoted text. That is, they will appear in the formatted text even if they are not enclosed within single quotes.

The number of symbol letters you specify also determines the format. For example, if the "zz" pattern results in "PDT," then the "zzzz" pattern generates "Pacific Daylight Time." The following table summarizes these rules:

Presentation | Number of Symbols | Result
Text | 1 - 3 | abbreviated form, if one exists
Text | >= 4 | full form
Number | minimum number of digits is required | shorter numbers are padded with zeros (for a year, if the count of 'y' is 2, then the year is truncated to 2 digits)
Text & Number | 1 - 2 | number form
Text & Number | 3 | text form
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Predefined Formats
Next page: Changing Date Format Symbols


Changing Date Format Symbols (The Java™ Tutorials > Internationalization > Formatting)

Trail: Internationalization
Lesson: Formatting
Section: Dates and Times
Formatting
Numbers and Currencies
Using Predefined Formats
Customizing Formats
Dates and Times
Using Predefined Formats
Customizing Formats
Changing Date Format Symbols
Messages
Dealing with Compound Messages
Handling Plurals
Home Page > Internationalization > Formatting
« Previous • Trail • Next »
Changing Date Format Symbols
The format method of the SimpleDateFormat class returns a String composed of digits and symbols. For example, in the String "Friday, April 10, 1998," the symbols are "Friday" and "April." If the symbols encapsulated in SimpleDateFormat don't meet your needs, you can change them with the DateFormatSymbols. You can change symbols that represent names for months, days of the week, and time zones, among others. The following table lists the DateFormatSymbols methods that allow you to modify the symbols:

DateFormatSymbol Methods
Setter Method | Example of a Symbol the Method Modifies
setAmPmStrings | PM
setEras | AD
setMonths | December
setShortMonths | Dec
setShortWeekdays | Tue
setWeekdays | Tuesday
setZoneStrings | PST

The following example invokes setShortWeekdays to change the short names of the days of the week from lowercase to uppercase characters. The full source code for this example is in DateFormatSymbolsDemo. The first element in the array argument of setShortWeekdays is a null String. Therefore the array is one-based rather than zero-based. The SimpleDateFormat constructor accepts the modified DateFormatSymbols object as an argument. Here is the source code:

Date today;
String result;
SimpleDateFormat formatter;
DateFormatSymbols symbols;
String[] defaultDays;
String[] modifiedDays;

symbols = new DateFormatSymbols(new Locale("en","US"));
defaultDays = symbols.getShortWeekdays();

for (int i = 0; i < defaultDays.length; i++) {
    System.out.print(defaultDays[i] + " ");
}
System.out.println();

String[] capitalDays = {
            "", "SUN", "MON", "TUE", "WED", "THU", "FRI", "SAT"};
symbols.setShortWeekdays(capitalDays);

modifiedDays = symbols.getShortWeekdays();
for (int i = 0; i < modifiedDays.length; i++) {
    System.out.print(modifiedDays[i] + " ");
}
System.out.println();
System.out.println();

formatter = new SimpleDateFormat("E", symbols);
today = new Date();
result = formatter.format(today);
System.out.println(result);

The preceding code generates this output:

   Sun	 Mon	 Tue	 Wed	 Thu	 Fri	 Sat
   SUN	 MON	 TUE	 WED	 THU	 FRI	 SAT
WED
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Customizing Formats
Next page: Messages


Messages (The Java™ Tutorials > Internationalization > Formatting)

Trail: Internationalization
Lesson: Formatting
Formatting
Numbers and Currencies
Using Predefined Formats
Customizing Formats
Dates and Times
Using Predefined Formats
Customizing Formats
Changing Date Format Symbols
Messages
Dealing with Compound Messages
Handling Plurals
Home Page > Internationalization > Formatting
« Previous • Trail • Next »
Messages
We all like to use programs that let us know what's going on. Programs that keep us informed often do so by displaying status and error messages. Of course, these messages need to be translated so they can be understood by end users around the world. The section Isolating Locale-Specific Data discusses translatable text messages. Usually, you're done after you move a message String into a ResourceBundle. However, if you've embedded variable data in a message, you'll have to take some extra steps to prepare it for translation.

A compound message contains variable data. In the following list of compound messages, the variable data is underlined:

The disk named MyDisk contains 300 files.
The current balance of account #34-98-222 is $2,745.72.
405,390 people have visited your website since January 1, 1998.
Delete all files older than 120 days.

You might be tempted to construct the last message in the preceding list by concatenating phrases and variables as follows: double numDays;

ResourceBundle msgBundle;
...
String message = msgBundle.getString("deleteolder"
                     + numDays.toString()
                     + msgBundle.getString("days"));

This approach works fine in English, but it won't work for languages in which the verb appears at the end of the sentence. Because the word order of this message is hardcoded, your localizers won't be able to create grammatically correct translations for all languages.

How can you make your program localizable if you need to use compound messages? You can do so by using the MessageFormat class, which is the topic of this section.

Caution: Compound messages are difficult to translate because the message text is fragmented. If you use compound messages, localization will take longer and cost more. Therefore you should use compound messages only when necessary.

Dealing with Compound Messages

A compound message may contain several kinds of variables: dates, times, strings, numbers, currencies, and percentages. To format a compound message in a locale-independent manner, you construct a pattern that you apply to a MessageFormat object.

Handling Plurals

The words in a message usually vary if both plural and singular word forms are possible. With the ChoiceFormat class, you can map a number to a word or phrase, allowing you to construct messages that are grammatically correct.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Changing Date Format Symbols
Next page: Dealing with Compound Messages


Dealing with Compound Messages (The Java™ Tutorials > Internationalization > Formatting)

Trail: Internationalization
Lesson: Formatting
Section: Messages
Formatting
Numbers and Currencies
Using Predefined Formats
Customizing Formats
Dates and Times
Using Predefined Formats
Customizing Formats
Changing Date Format Symbols
Messages
Dealing with Compound Messages
Handling Plurals
Home Page > Internationalization > Formatting
« Previous • Trail • Next »
Dealing with Compound Messages
A compound message may contain several kinds of variables: dates, times, strings, numbers, currencies, and percentages. To format a compound message in a locale-independent manner, you construct a pattern that you apply to a MessageFormat object, and store this pattern in a ResourceBundle.

By stepping through a sample program, this section demonstrates how to internationalize a compound message. The sample program makes use of the MessageFormat class. The full source code for this program is in the file called MessageFormatDemo.java. The German locale properties are in the file called MessageBundle_en_US.properties.

1. Identify the Variables in the Message

Suppose that you want to internationalize the following message:

Notice that we've underlined the variable data and have identified what kind of objects will represent this data.

2. Isolate the Message Pattern in a ResourceBundle

Store the message in a ResourceBundle named MessageBundle, as follows:
ResourceBundle messages =
   ResourceBundle.getBundle("MessageBundle", currentLocale);

This ResourceBundle is backed by a properties file for each Locale. Since the ResourceBundle is called MessageBundle, the properties file for U.S. English is named MessageBundle_en_US.properties. The contents of this file is as follows:

template = At {2,time,short} on {2,date,long}, we detected \
          {1,number,integer} spaceships on the planet {0}.
planet = Mars

The first line of the properties file contains the message pattern. If you compare this pattern with the message text shown in step 1, you'll see that an argument enclosed in braces replaces each variable in the message text. Each argument starts with a digit called the argument number, which matches the index of an element in an Object array that holds the argument values. Note that in the pattern the argument numbers are not in any particular order. You can place the arguments anywhere in the pattern. The only requirement is that the argument number have a matching element in the array of argument values.

The next step discusses the argument value array, but first let's look at each of the arguments in the pattern. The following table provides some details about the arguments:

Arguments for template in MessageBundle_en_US.properties
Argument | Description
{2,time,short} | The time portion of a Date object. The short style specifies the DateFormat.SHORT formatting style.
{2,date,long} | The date portion of a Date object. The same Date object is used for both the date and time variables. In the Object array of arguments the index of the element holding the Date object is 2. (This is described in the next step.)
{1,number,integer} | A Number object, further qualified with the integer number style.
{0} | The String in the ResourceBundle that corresponds to the planet key.

For a full description of the argument syntax, see the API documentation for the MessageFormat class.

3. Set the Message Arguments

The following lines of code assign values to each argument in the pattern. The indexes of the elements in the messageArguments array match the argument numbers in the pattern. For example, the Integer element at index 1 corresponds to the {1,number,integer} argument in the pattern. Because it must be translated, the String object at element 0 will be fetched from the ResourceBundle with the getString method. Here is the code that defines the array of message arguments:
Object[] messageArguments = {
    messages.getString("planet"),
    new Integer(7),
    new Date()
};

4. Create the Formatter

Next, create a MessageFormat object. You set the Locale because the message contains Date and Number objects, which should be formatted in a locale-sensitive manner.
MessageFormat formatter = new MessageFormat("");
formatter.setLocale(currentLocale);

5. Format the Message Using the Pattern and the Arguments

This step shows how the pattern, message arguments, and formatter all work together. First, fetch the pattern String from the ResourceBundle with the getString method. The key to the pattern is template. Pass the pattern String to the formatter with the applyPattern method. Then format the message using the array of message arguments, by invoking the format method. The String returned by the format method is ready to be displayed. All of this is accomplished with just two lines of code:
formatter.applyPattern(messages.getString("template"));
String output = formatter.format(messageArguments);

6. Run the Demo Program

The demo program prints the translated messages for the English and German locales and properly formats the date and time variables. Note that the English and German verbs ("detected" and "entdeckt") are in different locations relative to the variables:
currentLocale = en_US
At 1:15 PM on April 13, 1998, we detected 7 spaceships
on the planet Mars.
currentLocale = de_DE
Um 13.15 Uhr am 13. April 1998 haben wir 7 Raumschiffe
auf dem Planeten Mars entdeckt.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Messages
Next page: Handling Plurals


Handling Plurals (The Java™ Tutorials > Internationalization > Formatting)

Trail: Internationalization
Lesson: Formatting
Section: Messages
Formatting
Numbers and Currencies
Using Predefined Formats
Customizing Formats
Dates and Times
Using Predefined Formats
Customizing Formats
Changing Date Format Symbols
Messages
Dealing with Compound Messages
Handling Plurals
Home Page > Internationalization > Formatting
« Previous • Trail • Next »
Handling Plurals
The words in a message may vary if both plural and singular word forms are possible. With the ChoiceFormat class, you can map a number to a word or a phrase, allowing you to construct grammatically correct messages.

In English the plural and singular forms of a word are usually different. This can present a problem when you are constructing messages that refer to quantities. For example, if your message reports the number of files on a disk, the following variations are possible:

There are no files on XDisk.
There is one file on XDisk.
There are 2 files on XDisk.

The fastest way to solve this problem is to create a MessageFormat pattern like this:

There are {0,number} file(s) on {1}.

Unfortunately the preceding pattern results in incorrect grammar:

There are 1 file(s) on XDisk.

You can do better than that, provided that you use the ChoiceFormat class. In this section you'll learn how to deal with plurals in a message by stepping through a sample program called ChoiceFormatDemo. This program also uses the MessageFormat class, which is discussed in the previous section, Dealing with Compound Messages.

1. Define the Message Pattern
First, identify the variables in the message:

Next, replace the variables in the message with arguments, creating a pattern that can be applied to a MessageFormat object:

There {0} on {1}.

The argument for the disk name, which is represented by{1}, is easy enough to deal with. You just treat it like any other String variable in a MessageFormat pattern. This argument matches the element at index 1 in the array of argument values. (See step 7.)

Dealing with argument{0} is more complex, for a couple of reasons:

  • The phrase that this argument replaces varies with the number of files. To construct this phrase at run time, you need to map the number of files to a particular String. For example, the number 1 will map to the String containing the phrase is one file. The ChoiceFormat class allows you to perform the necessary mapping.
  • If the disk contains multiple files, the phrase includes an integer. The MessageFormat class lets you insert a number into a phrase.

2. Create a ResourceBundle

Because the message text must be translated, isolate it in a ResourceBundle:
ResourceBundle bundle =
   ResourceBundle.getBundle("ChoiceBundle", currentLocale);

The sample program backs the ResourceBundle with properties files. The ChoiceBundle_en_US.propertiescontains the following lines:

pattern = There {0} on {1}.
noFiles = are no files
oneFile = is one file
multipleFiles = are {2} files

The contents of this properties file show how the message will be constructed and formatted. The first line contains the pattern for MessageFormat . (See step 1.) The other lines contain phrases that will replace argument {0} in the pattern. The phrase for the multipleFiles key contains the argument {2}, which will be replaced by a number.

Here is the French version of the properties file, ChoiceBundle_fr_FR.properties

pattern = Il {0} sur {1}.
noFiles = n'y a pas de fichiers
oneFile = y a un fichier
multipleFiles = y a {2} fichiers

3. Create a Message Formatter

In this step you instantiate MessageFormat and set its Locale:
MessageFormat messageForm = new MessageFormat("");
messageForm.setLocale(currentLocale);

4. Create a Choice Formatter

The ChoiceFormat object allows you to choose, based on a double number, a particular String. The range of double numbers, and the String objects to which they map, are specified in arrays:
double[] fileLimits = {0,1,2};
String [] fileStrings = {
    bundle.getString("noFiles"),
    bundle.getString("oneFile"),
    bundle.getString("multipleFiles")
};

ChoiceFormat maps each element in the double array to the element in the String array that has the same index. In the sample code the 0 maps to the String returned by calling bundle.getString("noFiles"). By coincidence the index is the same as the value in the fileLimits array. If the code had set fileLimits[0] to seven, ChoiceFormat would map the number 7 to fileStrings[0].

You specify the double and String arrays when instantiating ChoiceFormat:

ChoiceFormat choiceForm = new ChoiceFormat(fileLimits,
                                           fileStrings);

5. Apply the Pattern

Remember the pattern you constructed in step 1? It's time to retrieve the pattern from the ResourceBundle and apply it to the MessageFormat object:
String pattern = bundle.getString("pattern");
messageForm.applyPattern(pattern);

6. Assign the Formats

In this step you assign to the MessageFormat object the ChoiceFormat object created in step 4:
Format[] formats = {choiceForm, null,
                    NumberFormat.getInstance()};
messageForm.setFormats(formats);

The setFormats method assigns Format objects to the arguments in the message pattern. You must invoke the applyPattern method before you call the setFormats method. The following table shows how the elements of the Format array correspond to the arguments in the message pattern:

The Format Array of the ChoiceFormatDemo Program
Array Element | Pattern Argument
choiceForm | {0}
null | {1}
NumberFormat.getInstance() | {2}

7. Set the Arguments and Format the Message
At run time the program assigns the variables to the array of arguments it passes to the MessageFormat object. The elements in the array correspond to the arguments in the pattern. For example, messageArgument[1] maps to pattern argument {1}, which is a String containing the name of the disk. In the previous step the program assigned a ChoiceFormat object to argument {0} of the pattern. Therefore the number assigned to messageArgument[0] determines which String the ChoiceFormat object selects. If messageArgument[0] is greater than or equal to 2, the String containing the phrase are {2} files replaces argument {0} in the pattern. The number assigned to messageArgument[2] will be substituted in place of pattern argument {2}. Here's the code that tries this out:
Object[] messageArguments = {null, "XDisk", null};
for (int numFiles = 0; numFiles < 4; numFiles++) {
    messageArguments[0] = new Integer(numFiles);
    messageArguments[2] = new Integer(numFiles);
    String result = messageForm.format(messageArguments);
    System.out.println(result);
}

8. Run the Demo Program

Compare the messages displayed by the program with the phrases in the ResourceBundle of step 2. Notice that the ChoiceFormat object selects the correct phrase, which the MessageFormat object uses to construct the proper message. The output of the ChoiceFormatDemo program is as follows:
currentLocale = en_US
There are no files on XDisk.
There is one file on XDisk.
There are 2 files on XDisk.
There are 3 files on XDisk.

currentLocale = fr_FR
Il n'y a pas des fichiers sur XDisk.
Il y a un fichier sur XDisk.
Il y a 2 fichiers sur XDisk.
Il y a 3 fichiers sur XDisk.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Dealing with Compound Messages
Next page: Working with Text


Lesson: Working with Text (The Java™ Tutorials > Internationalization)

Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Trail: Internationalization
Home Page > Internationalization
« Previous • Trail • Next »
Lesson: Working with Text
Nearly all programs with user interfaces manipulate text. In an international market the text your programs display must conform to the rules of languages from around the world. The Java programming language provides a number of classes that help you handle text in a locale-independent manner.

Checking Character Properties

This section explains how to use the Character comparison methods to check character properties for all major languages.

Comparing Strings

In this section you'll learn how to perform locale-independent string comparisons with the Collator class.

Detecting Text Boundaries

This section shows how the BreakIterator class can detect character, word, sentence, and line boundaries.

Converting Non-Unicode Text

Different computer systems around the world store text in a variety of encoding schemes. This section describes the classes that help you convert text between Unicode and other encodings.

Normalizer's API

This section explains how to use the Normalizer's API to transform text applying different normalization forms.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Checking Character Properties


Checking Character Properties (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
Checking Character Properties
You can categorize characters according to their properties. For instance, X is an uppercase letter and 4 is a decimal digit. Checking character properties is a common way to verify the data entered by end users. If you are selling books online, for example, your order entry screen should verify that the characters in the quantity field are all digits.

Developers who aren't used to writing global software might determine a character's properties by comparing it with character constants. For instance, they might write code like this:

char ch;
...

// This code is WRONG!

if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z'))
  // ch is a letter
...
if (ch >= '0' && ch <= '9')
  // ch is a digit
...
if ((ch == ' ') || (ch =='\n') || (ch == '\t'))
  // ch is a whitespace

The preceding code is wrong because it works only with English and a few other languages. To internationalize the previous example, replace it with the following statements:

char ch;
...

// This code is OK!

if (Character.isLetter(ch))
...
if (Character.isDigit(ch))
...
if (Character.isSpaceChar(ch))
The Character methods rely on the Unicode Standard for determining the properties of a character. Unicode is a 16-bit character encoding that supports the world's major languages. In the Java programming language char values represent Unicode characters. If you check the properties of a char with the appropriate Character method, your code will work with all major languages. For example, the Character.isLetter method returns true if the character is a letter in Chinese, German, Arabic, or another language.

The following list gives some of the most useful Character comparison methods. The Character API documentation fully specifies the methods.

  • isDigit
  • isLetter
  • isLetterOrDigit
  • isLowerCase
  • isUpperCase
  • isSpaceChar
  • isDefined

The Character.getType method returns the Unicode category of a character. Each category corresponds to a constant defined in the Character class. For instance, getType returns the Character.UPPERCASE_LETTER constant for the character A. For a complete list of the category constants returned by getType, see the Character API documentation. The following example shows how to use getType and the Character category constants. All of the expressions in these if statements are true:

if (Character.getType('a') == Character.LOWERCASE_LETTER)
...
if (Character.getType('R') == Character.UPPERCASE_LETTER)
...
if (Character.getType('>') == Character.MATH_SYMBOL)
...
if (Character.getType('_') == Character.CONNECTOR_PUNCTUATION)
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Working with Text
Next page: Comparing Strings


Comparing Strings (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
Comparing Strings
Applications that sort through text perform frequent string comparisons. For example, a report generator performs string comparisons when sorting a list of strings in alphabetical order.

If your application audience is limited to people who speak English, you can probably perform string comparisons with the String.compareTo method. The String.compareTo method performs a binary comparison of the Unicode characters within the two strings. For most languages, however, this binary comparison cannot be relied on to sort strings, because the Unicode values do not correspond to the relative order of the characters.

Fortunately the Collator class allows your application to perform string comparisons for different languages. In this section, you'll learn how to use the Collator class when sorting text.

Performing Locale-Independent Comparisons

Collation rules define the sort sequence of strings. These rules vary with locale, because various natural languages sort words differently. Using the predefined collation rules provided by the Collator class, you can sort strings in a locale-independent manner.

Customizing Collation Rules

In some cases, the predefined collation rules provided by the Collator class may not work for you. For example, you may want to sort strings in a language whose locale is not supported by Collator. In this situation, you can define your own collation rules, and assign them to a RuleBasedCollator object.

Improving Collation Performance

With the CollationKey class, you may increase the efficiency of string comparisons. This class converts String objects to sort keys that follow the rules of a given Collator.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Checking Character Properties
Next page: Performing Locale-Independent Comparisons


Performing Locale-Independent Comparisons (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Section: Comparing Strings
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
Performing Locale-Independent Comparisons
Collation rules define the sort sequence of strings. These rules vary with locale, because various natural languages sort words differently. You can use the predefined collation rules provided by the Collator class to sort strings in a locale-independent manner.

To instantiate the Collator class invoke the getInstance method. Usually, you create a Collator for the default Locale, as in the following example:

Collator myDefaultCollator = Collator.getInstance();
You can also specify a particular Locale when you create a Collator, as follows:
Collator myFrenchCollator = Collator.getInstance(Locale.FRENCH);

The getInstance method returns a RuleBasedCollator, which is a concrete subclass of Collator. The RuleBasedCollator contains a set of rules that determine the sort order of strings for the locale you specify. These rules are predefined for each locale. Because the rules are encapsulated within the RuleBasedCollator, your program won't need special routines to deal with the way collation rules vary with language.

You invoke the Collator.compare method to perform a locale-independent string comparison. The compare method returns an integer less than, equal to, or greater than zero when the first string argument is less than, equal to, or greater than the second string argument. The following table contains some sample calls to Collator.compare:

Collator.compare Examples
Example | Return Value | Explanation
myCollator.compare("abc", "def") | -1 | "abc" is less than "def"
myCollator.compare("rtf", "rtf") | 0 | the two strings are equal
myCollator.compare("xyz", "abc") | 1 | "xyz" is greater than "abc"

You use the compare method when performing sort operations. The sample program called CollatorDemo uses the compare method to sort an array of English and French words. This program shows what can happen when you sort the same list of words with two different collators:

Collator fr_FRCollator = Collator.getInstance(new Locale("fr","FR"));

Collator en_USCollator = Collator.getInstance(new Locale("en","US"));

The method for sorting, called sortStrings, can be used with any Collator. Notice that the sortStrings method invokes the compare method:

public static void sortStrings(Collator collator,
                               String[] words) {
    String tmp;
    for (int i = 0; i < words.length; i++) {
    for (int j = i + 1; j < words.length; j++) {
        if (collator.compare(words[i], words[j]) > 0) {
        tmp = words[i];
        words[i] = words[j];
        words[j] = tmp;
        }
    }
    }
}
The English Collator sorts the words as follows:
peach
péché
pêche
sin

According to the collation rules of the French language, the preceding list is in the wrong order. In French péché should follow pêche in a sorted list. The French Collator sorts the array of words correctly, as follows:

peach
pêche
péché
sin
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Comparing Strings
Next page: Customizing Collation Rules


Customizing Collation Rules (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Section: Comparing Strings
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
Customizing Collation Rules
The previous section discussed how to use the predefined rules for a locale to compare strings. These collation rules determine the sort order of strings. If the predefined collation rules do not meet your needs, you can design your own rules and assign them to a RuleBasedCollator object.

Customized collation rules are contained in a String object that is passed to the RuleBasedCollator constructor. Here's a simple example:

String simpleRule = "< a < b < c < d";
RuleBasedCollator simpleCollator =  new RuleBasedCollator(simpleRule);

For the simpleCollator object in the previous example, a is less than b, which is less that c, and so forth. The simpleCollator.compare method references these rules when comparing strings. The full syntax used to construct a collation rule is more flexible and complex than this simple example. For a full description of the syntax, refer to the API documentation for the RuleBasedCollator class.

The example that follows sorts a list of Spanish words with two collators. Full source code for this example is in RulesDemo.java.

The RulesDemo program starts by defining collation rules for English and Spanish. The program will sort the Spanish words in the traditional manner. When sorting by the traditional rules, the letters ch and ll and their uppercase equivalents each have their own positions in the sort order. These character pairs compare as if they were one character. For example, ch sorts as a single letter, following cz in the sort order. Note how the rules for the two collators differ:

String englishRules =
    ("< a,A < b,B < c,C < d,D < e,E < f,F " +
     "< g,G < h,H < i,I < j,J < k,K < l,L " +
     "< m,M < n,N < o,O < p,P < q,Q < r,R " +
     "< s,S < t,T < u,U < v,V < w,W < x,X " +
     "< y,Y < z,Z");

String smallnTilde = new String("\u00F1"); // ñ
String capitalNTilde = new String("\u00D1"); // Ñ

String traditionalSpanishRules =
    ("< a,A < b,B < c,C " +
     "< ch, cH, Ch, CH " +
     "< d,D < e,E < f,F " +
     "< g,G < h,H < i,I < j,J < k,K < l,L " +
     "< ll, lL, Ll, LL " +
     "< m,M < n,N " +
     "< " + smallnTilde + "," + capitalNTilde + " " +
     "< o,O < p,P < q,Q < r,R " +
     "< s,S < t,T < u,U < v,V < w,W < x,X " +
     "< y,Y < z,Z");

The following lines of code create the collators and invoke the sort routine:

try {
    RuleBasedCollator enCollator =
        new RuleBasedCollator(englishRules);
    RuleBasedCollator spCollator =
        new RuleBasedCollator(traditionalSpanishRules);

    sortStrings(enCollator, words);
    printStrings(words);

    System.out.println();

    sortStrings(spCollator, words);
    printStrings(words);
} catch (ParseException pe) {
    System.out.println("Parse exception for rules");
}

The sort routine, called sortStrings, is generic. It will sort any array of words according to the rules of any Collator object:

public static void sortStrings(Collator collator, String[] words) {
    String tmp;
    for (int i = 0; i < words.length; i++) {
    for (int j = i + 1; j < words.length; j++) {
        if (collator.compare(words[i], words[j]) > 0) {
        tmp = words[i];
        words[i] = words[j];
        words[j] = tmp;
        }
    }
    }
}

When sorted with the English collation rules, the array of words is as follows:

chalina
curioso
llama
luz

Compare the preceding list with the following, which is sorted according to the traditional Spanish rules of collation:

curioso
chalina
luz
llama
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Performing Locale-Independent Comparisons
Next page: Improving Collation Performance


Improving Collation Performance (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Section: Comparing Strings
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
Improving Collation Performance
Sorting long lists of strings is often time consuming. If your sort algorithm compares strings repeatedly, you can speed up the process by using the CollationKey class.

A CollationKey object represents a sort key for a given String and Collator. Comparing two CollationKey objects involves a bitwise comparison of sort keys and is faster than comparing String objects with the Collator.compare method. However, generating CollationKey objects requires time. Therefore if a String is to be compared just once, Collator.compare offers better performance.

The example that follows uses a CollationKey object to sort an array of words. Source code for this example is in KeysDemo.java.

The KeysDemo program creates an array of CollationKey objects in the main method. To create a CollationKey, you invoke the getCollationKey method on a Collator object. You cannot compare two CollationKey objects unless they originate from the same Collator. The main method is as follows:

static public void main(String[] args) {
    Collator enUSCollator =
              Collator.getInstance (new Locale("en","US"));
    String [] words = {
    "peach",
    "apricot",
    "grape",
    "lemon"
    };

    CollationKey[] keys = new CollationKey[words.length];

    for (int k = 0; k < keys.length; k ++) {
    keys[k] = enUSCollator.getCollationKey(words[k]);
    }

    sortArray(keys);
    printArray(keys);
}

The sortArray method invokes the CollationKey.compareTo method. The compareTo method returns an integer less than, equal to, or greater than zero if the keys[i] object is less than, equal to, or greater than the keys[j] object. Note that the program compares the CollationKey objects, not the String objects from the original array of words. Here is the code for the sortArray method:

public static void sortArray(CollationKey[] keys) {

    CollationKey tmp;
    for (int i = 0; i < keys.length; i++) {
    for (int j = i + 1; j < keys.length; j++) {
        if (keys[i].compareTo(keys[j]) > 0) {
        tmp = keys[i];
        keys[i] = keys[j];
        keys[j] = tmp;
        }
    }
    }
}

The KeysDemo program sorts an array of CollationKey objects, but the original goal was to sort an array of String objects. To retrieve the String representation of each CollationKey, the program invokes getSourceString in the displayWords method, as follows:

static void displayWords(CollationKey[] keys) {

    for (int i = 0; i < keys.length; i++) {
    System.out.println(keys[i].getSourceString());
    }
}

The displayWords method prints the following lines:

apricot
grape
lemon
peach
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Customizing Collation Rules
Next page: Detecting Text Boundaries


Detecting Text Boundaries (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
Detecting Text Boundaries
Applications that manipulate text need to locate boundaries within the text. For example, consider some of the common functions of a word processor: highlighting a character, cutting a word, moving the cursor to the next sentence, and wrapping a word at a line ending. To perform each of these functions, the word processor must be able to detect the logical boundaries in the text. Fortunately you don't have to write your own routines to perform boundary analysis. Instead, you can take advantage of the methods provided by the BreakIterator class.

About the BreakIterator Class

This section discusses the instantiation methods and the imaginary cursor of the BreakIterator class.

Character Boundaries

In this section you'll learn about the difference between user and Unicode characters, and how to locate user characters with a BreakIterator.

Word Boundaries

If your application needs to select or locate words within text, you'll find it helpful to use a BreakIterator.

Sentence Boundaries

Determining sentence boundaries can be problematic, because of the ambiguous use of sentence terminators in many written languages. This section examines some of the problems you may encounter, and how the BreakIterator deals with them.

Line Boundaries

This section describes how to locate potential line breaks in a text string with a BreakIterator.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Improving Collation Performance
Next page: About the BreakIterator Class


About the BreakIterator Class (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Section: Detecting Text Boundaries
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
About the BreakIterator Class
The BreakIterator class is locale-sensitive, because text boundaries vary with language. For example, the syntax rules for line breaks are not the same for all languages. To determine which locales the BreakIterator class supports, invoke the getAvailableLocales method, as follows:
Locale[] locales = BreakIterator.getAvailableLocales();

You can analyze four kinds of boundaries with the BreakIterator class: character, word, sentence, and potential line break. When instantiating a BreakIterator, you invoke the appropriate factory method:

  • getCharacterInstance
  • getWordInstance
  • getSentenceInstance
  • getLineInstance

Each instance of BreakIterator can detect just one type of boundary. If you want to locate both character and word boundaries, for example, you create two separate instances.

A BreakIterator has an imaginary cursor that points to the current boundary in a string of text. You can move this cursor within the text with the previous and the next methods. For example, if you've created a BreakIterator with getWordInstance, the cursor moves to the next word boundary in the text every time you invoke the next method. The cursor-movement methods return an integer indicating the position of the boundary. This position is the index of the character in the text string that would follow the boundary. Like string indexes, the boundaries are zero-based. The first boundary is at 0, and the last boundary is the length of the string. The following figure shows the word boundaries detected by the next and previous methods in a line of text:

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

You should use the BreakIterator class only with natural-language text. To tokenize a programming language, use the StreamTokenizer class.

The sections that follow give examples for each type of boundary analysis. The coding examples are from the source code file named BreakIteratorDemo.java.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Detecting Text Boundaries
Next page: Character Boundaries


Character Boundaries (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Section: Detecting Text Boundaries
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
Character Boundaries
You need to locate character boundaries if your application allows the end user to highlight individual characters or to move a cursor through text one character at a time. To create a BreakIterator that locates character boundaries, you invoke the getCharacterInstance method, as follows:
BreakIterator characterIterator =
         BreakIterator.getCharacterInstance(currentLocale);

This type of BreakIterator detects boundaries between user characters, not just Unicode characters.

A user character may be composed of more than one Unicode character. For example, the user character ü can be composed by combining the Unicode characters \u0075 (u) and \u00a8 (¨). This isn't the best example, however, because the character ü may also be represented by the single Unicode character \u00fc. We'll draw on the Arabic language for a more realistic example.

In Arabic the word for house is:

This word contains three user characters, but it is composed of the following six Unicode characters:

String house = "\u0628" + "\u064e" + "\u064a" +
           "\u0652" + "\u067a" + "\u064f";

The Unicode characters at positions 1, 3, and 5 in the house string are diacritics. Arabic requires diacritics because they can alter the meanings of words. The diacritics in the example are nonspacing characters, since they appear above the base characters. In an Arabic word processor you cannot move the cursor on the screen once for every Unicode character in the string. Instead you must move it once for every user character, which may be composed by more than one Unicode character. Therefore you must use a BreakIterator to scan the user characters in the string.

The sample program BreakIteratorDemo, creates a BreakIterator to scan Arabic characters. The program passes this BreakIterator, along with the String object created previously, to a method named listPositions:

BreakIterator arCharIterator =
        BreakIterator.getCharacterInstance(new Locale ("ar","SA"));

listPositions (house, arCharIterator);

The listPositions method uses a BreakIterator to locate the character boundaries in the string. Note that the BreakIteratorDemo assigns a particular string to the BreakIterator with the setText method. The program retrieves the first character boundary with the first method and then invokes the next method until the constant BreakIterator.DONE is returned. The code for this routine is as follows:

static void listPositions(String target, BreakIterator iterator) {

    iterator.setText(target);
    int boundary = iterator.first();

    while (boundary != BreakIterator.DONE) {
        System.out.println (boundary);
        boundary = iterator.next();
    }
}

The listPositions method prints out the following boundary positions for the user characters in the string house. Note that the positions of the diacritics (1, 3, 5) are not listed:

0
2
4
6
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: About the BreakIterator Class
Next page: Word Boundaries


Word Boundaries (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Section: Detecting Text Boundaries
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
Word Boundaries
You invoke the getWordIterator method to instantiate a BreakIterator that detects word boundaries:
BreakIterator wordIterator =
    BreakIterator.getWordInstance(currentLocale);

You'll want to create such a BreakIterator when your application needs to perform operations on individual words. These operations might be common word- processing functions, such as selecting, cutting, pasting, and copying. Or, your application may search for words, and it must be able to distinguish entire words from simple strings.

When a BreakIterator analyzes word boundaries, it differentiates between words and characters that are not part of words. These characters, which include spaces, tabs, punctuation marks, and most symbols, have word boundaries on both sides.

The example that follows, which is from the program BreakIteratorDemo, marks the word boundaries in some text. The program creates the BreakIterator and then calls the markBoundaries method:

Locale currentLocale = new Locale ("en","US");

BreakIterator wordIterator =
    BreakIterator.getWordInstance(currentLocale);

String someText = "She stopped. " +
          "She said, \"Hello there,\" and then went on.";

markBoundaries(someText, wordIterator);

The markBoundaries method is defined in BreakIteratorDemo.java. This method marks boundaries by printing carets (^) beneath the target string. In the code that follows, notice the while loop where markBoundaries scans the string by calling the next method:

static void markBoundaries(String target, BreakIterator iterator) {

    StringBuffer markers = new StringBuffer();
    markers.setLength(target.length() + 1);
    for (int k = 0; k < markers.length(); k++) {
    markers.setCharAt(k,' ');
    }

    iterator.setText(target);
    int boundary = iterator.first();

    while (boundary != BreakIterator.DONE) {
    markers.setCharAt(boundary,'^');
    boundary = iterator.next();
    }

    System.out.println(target);
    System.out.println(markers);
}

The output of the markBoundaries method follows. Note where the carets (^) occur in relation to the punctuation marks and spaces:

She stopped.  She said, "Hello there," and then went on.
^  ^^      ^^ ^  ^^   ^^^^    ^^    ^^^^  ^^   ^^   ^^ ^^

The BreakIterator class makes it easy to select words from within text. You don't have to write your own routines to handle the punctuation rules of various languages; the BreakIterator class does this for you.

The extractWords method in the following example extracts and prints words for a given string. Note that this method uses Character.isLetterOrDigit to avoid printing "words" that contain space characters.

static void extractWords(String target, BreakIterator wordIterator) {

    wordIterator.setText(target);
    int start = wordIterator.first();
    int end = wordIterator.next();

    while (end != BreakIterator.DONE) {
    String word = target.substring(start,end);
    if (Character.isLetterOrDigit(word.charAt(0))) {
        System.out.println(word);
    }
    start = end;
    end = wordIterator.next();
    }
}

The BreakIteratorDemo program invokes extractWords, passing it the same target string used in the previous example. The extractWords method prints out the following list of words:

She
stopped
She
said
Hello
there
and
then
went
on
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Character Boundaries
Next page: Sentence Boundaries


Sentence Boundaries (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Section: Detecting Text Boundaries
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
Sentence Boundaries
You can use a BreakIterator to determine sentence boundaries. You start by creating a BreakIterator with the getSentenceInstance method:
BreakIterator sentenceIterator = BreakIterator.getSentenceInstance(currentLocale);

To show the sentence boundaries, the program uses the markBoundaries method, which is discussed in the section Word Boundaries. The markBoundaries method prints carets (^) beneath a string to indicate boundary positions. Here are some examples:

She stopped.  She said, "Hello there," and then went on.
^             ^                                         ^

He's vanished!  What will we do?  It's up to us.
^               ^                 ^             ^

Please add 1.5 liters to the tank.
^                                 ^
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Word Boundaries
Next page: Line Boundaries


Line Boundaries (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Section: Detecting Text Boundaries
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
Line Boundaries
Applications that format text or that perform line wrapping must locate potential line breaks. You can find these line breaks, or boundaries, with a BreakIterator that has been created with the getLineInstance method:
BreakIterator lineIterator =
        BreakIterator.getLineInstance(currentLocale);

This BreakIterator determines the positions in a string where text can break to continue on the next line. The positions detected by the BreakIterator are potential line breaks. The actual line breaks displayed on the screen may not be the same.

The two examples that follow use the markBoundaries method of BreakIteratorDemo.java to show the line boundaries detected by a BreakIterator. The markBoundaries method indicates line boundaries by printing carets (^) beneath the target string.

According to a BreakIterator, a line boundary occurs after the termination of a sequence of whitespace characters (space, tab, new line). In the following example, note that you can break the line at any of the boundaries detected:

She stopped.  She said, "Hello there," and then went on.
^   ^         ^   ^     ^      ^     ^ ^   ^    ^    ^  ^

Potential line breaks also occur immediately after a hyphen:

There are twenty-four hours in a day.
^     ^   ^      ^    ^     ^  ^ ^   ^

The next example breaks a long string of text into fixed-length lines with a method called formatLines. This method uses a BreakIterator to locate the potential line breaks. The formatLines method is short, simple, and, thanks to the BreakIterator, locale-independent. Here is the source code:

static void formatLines(String target, int maxLength,
            Locale currentLocale) {

    BreakIterator boundary =
    BreakIterator.getLineInstance(currentLocale);
    boundary.setText(target);
    int start = boundary.first();
    int end = boundary.next();
    int lineLength = 0;

    while (end != BreakIterator.DONE) {
    String word = target.substring(start,end);
    lineLength = lineLength + word.length();
    if (lineLength >= maxLength) {
        System.out.println();
        lineLength = word.length();
    }
    System.out.print(word);
    start = end;
    end = boundary.next();
    }
}

The BreakIteratorDemo program invokes the formatLines method as follows:

String moreText = "She said, \"Hello there,\" and then " +
     "went on down the street. When she stopped " +
     "to look at the fur coats in a shop window, " +
     "her dog growled._ \"Sorry Jake,\" she said. " +
     " \"I didn't know you would take it personally.\"";

formatLines(moreText, 30, currentLocale);

The output from this call to formatLines is:

She said, "Hello there," and
then went on down the
street. When she stopped to
look at the fur coats in a
shop window, her dog
growled. "Sorry Jake," she
said. "I didn't know you
would take it personally."
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Sentence Boundaries
Next page: Converting Non-Unicode Text


Converting Non-Unicode Text (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
Converting Non-Unicode Text
In the Java programming language char values represent Unicode characters. Unicode is a 16-bit character encoding that supports the world's major languages. You can learn more about the Unicode standard at the Unicode Consortium Web site .

Few text editors currently support Unicode text entry. The text editor we used to write this section's code examples supports only ASCII characters, which are limited to 7 bits. To indicate Unicode characters that cannot be represented in ASCII, such as ö, we used the \uXXXX escape sequence. Each X in the escape sequence is a hexadecimal digit. The following example shows how to indicate the ö character with an escape sequence:

String str = "\u00F6";
char c = '\u00F6';
Character letter = new Character('\u00F6');

A variety of character encodings are used by systems around the world. Currently few of these encodings conform to Unicode. Because your program expects characters in Unicode, the text data it gets from the system must be converted into Unicode, and vice versa. Data in text files is automatically converted to Unicode when its encoding matches the default file encoding of the Java Virtual Machine. You can identify the default file encoding by creating an OutputStreamWriter using it and asking for its canonical name:

OutputStreamWriter out = new OutputStreamWriter(new ByteArrayOutputStream());
System.out.println(out.getEncoding());

If the default file encoding differs from the encoding of the text data you want to process, then you must perform the conversion yourself. You might need to do this when processing text from another country or computing platform.

This section discusses the APIs you use to translate non-Unicode text into Unicode. Before using these APIs, you should verify that the character encoding you wish to convert into Unicode is supported. The list of supported character encodings is not part of the Java programming language specification. Therefore the character encodings supported by the APIs may vary with platform. To see which encodings the Java Development Kit supports, see the Supported Encodings document.

The material that follows describes two techniques for converting non-Unicode text to Unicode. You can convert non-Unicode byte arrays into String objects, and vice versa. Or you can translate between streams of Unicode characters and byte streams of non-Unicode text.

Byte Encodings and Strings

This section shows you how to convert non-Unicode byte arrays into String objects, and vice versa.

Character and Byte Streams

In this section you'll learn how to translate between streams of Unicode characters and byte streams of non-Unicode text.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Line Boundaries
Next page: Byte Encodings and Strings


Byte Encodings and Strings (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Section: Converting Non-Unicode Text
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
Byte Encodings and Strings
If a byte array contains non-Unicode text, you can convert the text to Unicode with one of the String constructor methods. Conversely, you can convert a String object into a byte array of non-Unicode characters with the String.getBytes method. When invoking either of these methods, you specify the encoding identifier as one of the parameters.

The example that follows converts characters between UTF-8 and Unicode. UTF-8 is a transmission format for Unicode that is safe for UNIX file systems. The full source code for the example is in the file StringConverter.java.

The StringConverter program starts by creating a String containing Unicode characters:

String original = new String("A" + "\u00ea" + "\u00f1" +
                 "\u00fc" + "C");

When printed, the String named original appears as:

AêñüC

To convert the String object to UTF-8, invoke the getBytes method and specify the appropriate encoding identifier as a parameter. The getBytes method returns an array of bytes in UTF-8 format. To create a String object from an array of non-Unicode bytes, invoke the String constructor with the encoding parameter. The code that makes these calls is enclosed in a try block, in case the specified encoding is unsupported:

try {
    byte[] utf8Bytes = original.getBytes("UTF8");
    byte[] defaultBytes = original.getBytes();

    String roundTrip = new String(utf8Bytes, "UTF8");
    System.out.println("roundTrip = " + roundTrip);
    System.out.println();
    printBytes(utf8Bytes, "utf8Bytes");
    System.out.println();
    printBytes(defaultBytes, "defaultBytes");
} catch (UnsupportedEncodingException e) {
    e.printStackTrace();
}

The StringConverter program prints out the values in the utf8Bytes and defaultBytes arrays to demonstrate an important point: The length of the converted text might not be the same as the length of the source text. Some Unicode characters translate into single bytes, others into pairs or triplets of bytes.

The printBytes method displays the byte arrays by invoking the byteToHex method, which is defined in the source file, UnicodeFormatter.java. Here is the printBytes method:

public static void printBytes(byte[] array, String name) {
    for (int k = 0; k < array.length; k++) {
    System.out.println(name + "[" + k + "] = " + "0x" +
               UnicodeFormatter.byteToHex(array[k]));
    }
}

The output of the printBytes method follows. Note that only the first and last bytes, the A and C characters, are the same in both arrays:

utf8Bytes[0] = 0x41
utf8Bytes[1] = 0xc3
utf8Bytes[2] = 0xaa
utf8Bytes[3] = 0xc3
utf8Bytes[4] = 0xb1
utf8Bytes[5] = 0xc3
utf8Bytes[6] = 0xbc
utf8Bytes[7] = 0x43
defaultBytes[0] = 0x41
defaultBytes[1] = 0xea
defaultBytes[2] = 0xf1
defaultBytes[3] = 0xfc
defaultBytes[4] = 0x43
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Converting Non-Unicode Text
Next page: Character and Byte Streams


Character and Byte Streams (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Section: Converting Non-Unicode Text
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
Character and Byte Streams
The java.io package provides classes that allow you to convert between Unicode character streams and byte streams of non-Unicode text. With the InputStreamReader class, you can convert byte streams to character streams. You use the OutputStreamWriterclass to translate character streams into byte streams. The following figure illustrates the conversion process:

This figure represents the conversion process

When you create InputStreamReader and OutputStreamWriter objects, you specify the byte encoding that you want to convert. For example, to translate a text file in the UTF-8 encoding into Unicode, you create an InputStreamReader as follows:

FileInputStream fis = new FileInputStream("test.txt");
InputStreamReader isr = new InputStreamReader(fis, "UTF8");

If you omit the encoding identifier, InputStreamReader and OutputStreamWriter rely on the default encoding. You can determine which encoding an InputStreamReader or OutputStreamWriter uses by invoking the getEncoding method, as follows:

InputStreamReader defaultReader = new InputStreamReader(fis);
String defaultEncoding = defaultReader.getEncoding();

The example that follows shows you how to perform character-set conversions with the InputStreamReader and OutputStreamWriter classes. The full source code for this example is in StreamConverter.java. This program displays Japanese characters. Before trying it out, verify that the appropriate fonts have been installed on your system. If you are using the JDK software that is compatible with version 1.1, make a copy of the font.properties file and then replace it with the font.properties.ja file.

The StreamConverter program converts a sequence of Unicode characters from a String object into a FileOutputStream of bytes encoded in UTF-8. The method that performs the conversion is called writeOutput:

static void writeOutput(String str) {

    try {
    FileOutputStream fos = new FileOutputStream("test.txt");
    Writer out = new OutputStreamWriter(fos, "UTF8");
    out.write(str);
    out.close();
    } catch (IOException e) {
    e.printStackTrace();
    }
}

The readInput method reads the bytes encoded in UTF-8 from the file created by the writeOutput method. An InputStreamReader object converts the bytes from UTF-8 into Unicode and returns the result in a String. The readInput method is as follows:

static String readInput() {

    StringBuffer buffer = new StringBuffer();
    try {
    FileInputStream fis = new FileInputStream("test.txt");
    InputStreamReader isr = new InputStreamReader(fis,
                              "UTF8");
    Reader in = new BufferedReader(isr);
    int ch;
    while ((ch = in.read()) > -1) {
        buffer.append((char)ch);
    }
    in.close();
    return buffer.toString();
    } catch (IOException e) {
    e.printStackTrace();
    return null;
    }
}

The main method of the StreamConverter program invokes the writeOutput method to create a file of bytes encoded in UTF-8. The readInput method reads the same file, converting the bytes back into Unicode. Here is the source code for the main method:

public static void main(String[] args) {

    String jaString =
    new String("\u65e5\u672c\u8a9e\u6587\u5b57\u5217");

    writeOutput(jaString);
    String inputString = readInput();
    String displayString = jaString + " " + inputString;
    new ShowString(displayString, "Conversion Demo");
}

The original string (jaString) should be identical to the newly created string (inputString). To show that the two strings are the same, the program concatenates them and displays them with a ShowString object. The ShowString class displays a string with the Graphics.drawString method. The source code for this class is in ShowString.java. When the StreamConverter program instantiates ShowString, the following window appears. The repetition of the characters displayed verifies that the two strings are identical:

This is a screens hot of the StreamConverter program

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Byte Encodings and Strings
Next page: Normalizer's API


Normalizer's API (The Java™ Tutorials > Internationalization > Working with Text)

Trail: Internationalization
Lesson: Working with Text
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Home Page > Internationalization > Working with Text
« Previous • Trail • Next »
Normalizer's API

Normalization is the process by which you can perform certain transformations of text to make it reconcilable in a way which it may not have been before. Let's say, you would like searching or sorting text, in this case you need to normalize that text to account for code points that should be represented as the same text.

What can be normalized? The normalization is applicable when you need to convert characters with diacritical marks, change all letters case, decompose ligatures, or convert half-width katakana characters to full-width characters and so on.

In accordance with the Unicode Standard Annex #15 the Normalizer's API supports all of the following four Unicode text normalization forms that are defined in the java.text.Normalizer.Form :

  • NFC – Normalization Form Composition
  • NFD – Normalization Form Decomposition
  • NFKC – Normalization Form Canonical Composition
  • NFKD – Normalization Form Canonical Decomposition

Let's examine how the latin small letter “o” with diaeresis can be normalized by using these normalization forms:
Original word | NFC | NFD | NFKC | NFKD
"schön" | "schön" | "scho\u0308n" | "schön" | "scho\u0308n"

You can notice that an original word is left unchanged in NFC and NFKC. This is because with NFD and NFKD, composite characters are mapped to their canonical decompositions. But with NFC and NFKC, combining character sequences are mapped to composites, if possible. There is no composite for diaeresis, so it is left decomposed in NFC and NFKC.

In the code example, NormSample.java , which is represented later, you can also notice another normalization feature. The half-width and full-width katakana characters will have the same compatibility decomposition and are thus compatibility equivalents. However, they are not canonical equivalents.

To be sure that you really need to normalize the text you may use the isNormalized method to determine if the given sequence of char values is normalized. If this method returns false, it means that you have to normalize this sequence and you should use the normalize method which normalizes a char values according to the specified normalization form. For example, to transform text into the canonical decomposed form you will have to use the following normalize method:

normalized_string = Normalizer.normalize(target_chars, Normalizer.Form.NFD);

Also, the normalize method rearranges accents into the proper canonical order, so that you do not have to worry about accent rearrangement on your own.

The following example represents an application that enables you to select a normalization form and a template to normalize:

Note: If you don't see the applet running above, you need to install release 6 of the JDK.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Character and Byte Streams
Next page: Internationalization of Network Resources


Lesson: Internationalization of Network Resources (The Java™ Tutorials > Internationalization)

Internationalization of Network Resources
Internationalized Domain Name
Internationalized Resource Identifier
Trail: Internationalization
Home Page > Internationalization
« Previous • Trail • Next »
Lesson: Internationalization of Network Resources

In a modern Internet community, many users are no longer satisfied with using only ASCII symbols to identify a domain name or a web resource. For example, they would like to be able to register a new domain using their native characters in Arabic or Chinese or to define a new URI using Unicode characters. That is why the internationalization of network resources is a cornerstone in widening horizons for the World Wide Web.

This lesson describes the internationalization of the network resources Domain Name and Resource Identifier.

Internationalized Domain Name

This section explains how to perform a mapping between Unicode domain name and its ASCII form.

Internationalized Resource Identifier

This section shows how to use the mapping methods of the URI class to convert between an IRI and a URI.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Internationalized Domain Name


Internationalized Domain Name (The Java™ Tutorials > Internationalization > Internationalization of Network Resources)

Trail: Internationalization
Lesson: Internationalization of Network Resources
Internationalization of Network Resources
Internationalized Domain Name
Internationalized Resource Identifier
Home Page > Internationalization > Internationalization of Network Resources
« Previous • Trail • Next »
Internationalized Domain Name

Historically an Internet domain names contain ASCII symbols only. But lately the number of those users who want to use Unicode characters when registering their domain names increased steeply. But domain name resolving system does not allow to apply Unicode characters.

Internationalizing Domain Names in Applications (IDNA) was adopted as the chosen standard and has a purpose to convert Unicode characters into standard ASCII domain names and thus preserve the stability of the domain name system.

Examples of the internationalized domain names:

  • http://清华大学.cn
  • http://www.транспорт.com

As you follow one of these links you may notice that a Unicode domain name represented in the address bar will be sustituted by the ASCII string.

You may get interested about how to perform such conversion in your application.
According to RFC 3490, IDNA does not extend the service offered by DNS to the applications. Instead, the applications (and, by implication, the users) continue to see an exact-match lookup service.

There are two main operations to accomplish the conversion between ASCII and non ASCII formats:

  • In Java™SE the ToASCII operation is used before sending an IDN to domain name resolving system or writing an IDN into a file where ASCII characters are expected (such as a DNS master file).
  • The ToUnicode operation is used when displaying names to users, for example names obtained from a DNS zone.

A special class java.net.IDN in Java™ SE allows to perform these operations. This class has two methods per each operations. The toASCII(String input, int flag) method allows to convert Unicode characters to ASCII.

flag parameter defines the behavior of the conversion process. The ALLOW_UNASSIGNED flag indicates the using of code points that are unassigned in Unicode 3.2 and the USE_STD3_ASCII_RULES flag enables the check against STD-3 ASCII rules. You can use these flags separately or logically OR'ed together. If the flag equals zero, you can specify its value in the two-argument method or just invoke a counterpart method:

    toASCII(input);

If the an input argiment doesn't conform to RFC 3490, this method will throw IllegalArgumentException.

    String ace_name = IDN.toASCII("http://清华大学.cn/");

The toUnicode method Translates a string from ASCII Compatible Encoding (ACE) to Unicode code points. This method never fails, in case of any error the input string remains the same and will be returned unmodified.

Security concern

A potential security risk appeared because IDN allows websites to use Unicode names. It can make easier to create a web site that can has a domain name, security certificates or even an outward appearance exactly like your own site. But in fact, it can be used for phishing purpose in order to collect private information about your site visitors. These sites are called a spoofed web sites.

For example, somebody can register a site with identical domain name as you have, by substituting a small Latin "a" or "o" with a resembling Cyrillic "a" or "o". In this case, new domain points users to another site and potentially opens users up to homograph attacks.

This is a well-known issue from the very beginning of introducing of the IDN conception. You can avoid it by turning off the IDN support entirely. You should type "about:config" into the address bar of the browser, find the "network.enableIDN" setting, and change its value to "false".

Also, both Mozilla and Opera have now announced the using of per-domain whitelists for selectively switching on IDN for those domains which are taking appropriate anti-spoofing precautions.
You can try to adjust the "network.IDN.whitelist.<lang>" settings to enable/disable a whitelist for a partucular language.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Internationalization of Network Resources
Next page: Internationalized Resource Identifier


Internationalized Resource Identifier (The Java™ Tutorials > Internationalization > Internationalization of Network Resources)

Trail: Internationalization
Lesson: Internationalization of Network Resources
Internationalization of Network Resources
Internationalized Domain Name
Internationalized Resource Identifier
Home Page > Internationalization > Internationalization of Network Resources
« Previous • Trail • Next »
Internationalized Resource Identifier

Internationalized Resource Identifier (IRI) like IDN may contain Unicode characters, while Uniform Resource Identifier (URI) is limited to ASCII symbols only.

According to RFC 3987 IRIs are meant to replace URIs in identifying resources for protocols, formats, and software components that use a UCS-based character repertoire.

At first sight, you may consider that this task must been decided with the same means as for IDN. But there is not so exactly. Let's view a resource identifier structure:

This figure represents a resource identifier structure

You may notice that it has several components.

The authority component of a URI parses according to the following syntax

    [user-info@]host[:port]
where the characters @ and : stand for themselves. The host component can be an IP-literal, an IPv4address, or just a name.

In a case, where a host is a domain name the IDN approach, i.e. the mapping, could be applied.

But generally the URI structure is more complicated. Applications can use URI-reference syntax to make reference to a URI, instead of always using above generic syntax rule. A URI-reference is either a URI or a relative reference. If a URI-reference doesn't specifies a scheme, it is said to be a relative reference. Usually, a relative reference expresses a URI reference relative to the name space of another URI.

Nevertheless, the instances the java.net.URI class can represent IRIs whenever they contain non ASCII characters.

This class was enhanced by the following methods to perform the operations and conversions according to RFC 3987:

  • toASCIIString() - converts an IRI to a URI and returns its content as a US-ASCII string.
  • toString() - returns the content of this URI as a string in its original Unicode form.
  • toIRIString()Converts this URI to an IRI and returns its content as a string.

As regards the following code:

     URI uri = new URI("http://清华大学.cn/");
     HttpURLConnection conn = (HttpURLConnection)
                  uri.toURL().openConnection();
     conn.getResponseCode();
Unfortunately, we can not perform this now, it is planned for the next release of Java™ SE.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Internationalized Domain Name
Next page: End of Trail


Trail: 2D Graphics (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: 2D Graphics

This trail introduces you to the Java 2D™ API and shows you how to display and print 2D graphics in your Java programs. The trial is intended for developers who want to enrich their knowledge of the Java 2D API, as well as for beginners in computer graphics. Almost every section contains relevant examples to illustrate specific capabilities. The Java 2D API enables you to easily perform the following tasks:

  • Draw lines, rectangles and any other geometric shape.
  • Fill those shapes with solid colors or gradients and textures.
  • Draw text with options for fine control over the font and rendering process.
  • Draw images, optionally applying filtering operations.
  • Apply operations such as compositing and transforming during any of the above rendering operations.
This chapter also explains less familiar concepts such as compositing.

This figure represents different graphics capabilities

Using 2D Graphics API to display complex charts

This figure represents the using of filtering operation

Using image-filtering operations

This chapter describes the concept of drawing on-screen and off-screen images, as well as surfaces and printer devices. This trail covers the most common uses of the Java 2D APIs and briefly describes some of the more advanced features.

Overview of the Java 2D Graphics API introduces the key Java 2D concepts and describes the Java 2D rendering model. This lesson is more conceptual than other lessons of this trail, it enables you to get deep into basic notions and classes descriptions.

Getting started with Graphics uses a developed example to show you how to obtain a Graphics object and use it for common graphics rendering tasks.

Working with Geometry teaches you how to use APIs to draw graphic primitives and arbitrary shapes, and how to apply fancy strokes and fill styles.

Working with Text APIs shows you how to effectively use text APIs, including how to create a Font object with desired attributes, measure text, and determine the names of the fonts available on your system.

Working with Images explains how to create a BufferedImage object, perform image-filtering operations, and draw on an image.

Printing teaches you how to render 2D graphics to a printer, print complex documents, and use Print Services.

Advanced topics in Java 2D explains how to perform transformations, clip the drawing region, composite overlapping graphics, specify rendering preferences, and control rendering quality.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Overview of the Java 2D API Concepts


Lesson: Overview of the Java 2D API Concepts (The Java™ Tutorials > 2D Graphics)

Overview of the Java 2D API Concepts
Coordinates
Java 2D Rendering
Geometric Primitives
Text
Images
Printing
Trail: 2D Graphics
Home Page > 2D Graphics
« Previous • Trail • Next »
Lesson: Overview of the Java 2D API Concepts
The Java 2D™ API provides two-dimensional graphics, text, and imaging capabilities for Java™ programs through extensions to the Abstract Windowing Toolkit (AWT). This comprehensive rendering package supports line art, text, and images in a flexible, full-featured framework for developing richer user interfaces, sophisticated drawing programs, and image editors. Java 2D objects exist on a plane called user coordinate space, or just user space. When objects are rendered on a screen or a printer, user space coordinates are transformed to device space coordinates. The following links are useful to start learning about the Java 2D API:
  • Graphics class
  • Graphics2D class

The Java 2D API provides following capabilities:

  • A uniform rendering model for display devices and printers
  • A wide range of geometric primitives, such as curves, rectangles, and ellipses, as well as a mechanism for rendering virtually any geometric shape
  • Mechanisms for performing hit detection on shapes, text, and images
  • A compositing model that provides control over how overlapping objects are rendered
  • Enhanced color support that facilitates color management
  • Support for printing complex documents
  • Control of the quality of the rendering through the use of rendering hints
These topics are discussed in the following sections:
  • Java 2D Rendering
  • Geometric Primitives
  • Text
  • Images
  • Printing
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: Coordinates


Coordinates (The Java™ Tutorials > 2D Graphics > Overview of the Java 2D API Concepts)

Trail: 2D Graphics
Lesson: Overview of the Java 2D API Concepts
Overview of the Java 2D API Concepts
Coordinates
Java 2D Rendering
Geometric Primitives
Text
Images
Printing
Home Page > 2D Graphics > Overview of the Java 2D API Concepts
« Previous • Trail • Next »
Coordinates
The Java 2D™ API maintains two coordinate spaces.
  • User space – The space in which graphics primitives are specified
  • Device space – The coordinate system of an output device such as a screen, window, or a printer

User space is a device-independent logical coordinate system, the coordinate space that your program uses. All geometries passed into Java 2D rendering routines are specified in user-space coordinates.

When the default transformation from user space to device space is used, the origin of user space is the upper-left corner of the component’s drawing area. The x coordinate increases to the right, and the y coordinate increases downward, as shown in the following figure. The top-left corner of a window is 0,0. All coordinates are specified using integers, which is usually sufficient. However, some cases require floating point or even double precision which are also supported.

This figure represents the space in which

Device space is a device-dependent coordinate system that varies according to the target rendering device. Although the coordinate system for a window or screen might be very different from the coordinate system of a printer, these differences are invisible to Java programs. The necessary conversions between user space and device space are performed automatically during rendering.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Overview of the Java 2D API Concepts
Next page: Java 2D Rendering


Java 2D Rendering (The Java™ Tutorials > 2D Graphics > Overview of the Java 2D API Concepts)

Trail: 2D Graphics
Lesson: Overview of the Java 2D API Concepts
Overview of the Java 2D API Concepts
Coordinates
Java 2D Rendering
Geometric Primitives
Text
Images
Printing
Home Page > 2D Graphics > Overview of the Java 2D API Concepts
« Previous • Trail • Next »
Java 2D Rendering
The Java 2D™ API provides a uniform rendering model across different types of devices. At the application level, the rendering process is the same whether the target rendering device is a screen or a printer. When a component needs to be displayed, its paint or update method is automatically invoked with an appropriate Graphics context.

The Java 2D API includes the java.awt.Graphics2D class, which extends the Graphics class to provide access to the enhanced graphics and rendering features of the Java 2D API. These features include:

  • Rendering the outline of any geometry primitive, using the stroke and paint attributes (draw method).
  • Rendering any geometry primitive by filling its interior with the color or pattern specified by the paint attributes (fill method).
  • Rendering any text string (drawString method). The font attribute is used to convert the string to glyphs, which are then filled with the color or pattern specified by the paint attributes.
  • Rendering the specified image (drawImage method).

In addition, the Graphics2D class supports the Graphics rendering methods for particular shapes, such as drawOval and fillRect.

All methods that are represented above can be divided into two groups. First group contains methods to draw a shape. Second group contains methods to affect the rendering. The last group operate with a term attributes.

You can modify the state attributes that form the Graphics2D context for following purposes:

  • To vary the stroke width
  • To change how strokes are joined together
  • To set a clipping path to limit the area that is rendered
  • To translate, rotate, scale, or shear objects when they are rendered
  • To define colors and patterns to fill shapes with
  • To specify how to compose multiple graphics objects

To use Java 2D API features, you cast the Graphics object passed into a component’s rendering method to a Graphics2D object. For example:

public void paint (Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    ...
}

As the following figure shows, the Graphics2D class rendering context contains several attributes.
This figure represents a stroke to outline the shape | The pen attribute is applied to the outline of a shape. This stroke attribute enables you to draw lines with any point size and dashing pattern and to apply end-cap and join decorations to a line.
This figure shows how to fill a shape with solid color | The fill attribute is applied to a shape's interior. This paint attribute enables you to fill shapes with solid colors, gradients, and patterns.
This figure shows how to composite an existing image and a graphic primitives | The compositing attribute is used when rendered objects overlap existing objects.
This figure represents shearing transform | The transform attribute is applied during rendering to convert the rendered object from user space to device-space coordinates. Optional translation, rotation, scaling, or shearing transforms can also be applied through this attribute.
This figure represents how to define the clipping path by using the Shape object | The clip, type restricts rendering to the area within the outline of the Shape object used to define the clipping path. Any Shape object can be used to define the clip.
This figure demonstrates a sample of glyphs | The font attribute is used to convert text strings to glyphs.
This figure represents antialiasing | Rendering hints specify preferences in the trade-offs between speed and quality. For example, you can specify whether antialiasing should be used, if this feature available. See also Controlling Rendering Quality.

To learn more about transforming and compositing see the Advanced Topics in 2D Graphcis lesson.

When you set an attribute, you pass in the appropriate attribute object. As the following example shows, to change the paint attribute to a blue-green gradient fill, you would construct a GradientPaint object and then call the setPaint method.

gp = new GradientPaint(0f,0f,blue,0f,30f,green);
g2.setPaint(gp);
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Coordinates
Next page: Geometric Primitives


Geometric Primitives (The Java™ Tutorials > 2D Graphics > Overview of the Java 2D API Concepts)

Trail: 2D Graphics
Lesson: Overview of the Java 2D API Concepts
Overview of the Java 2D API Concepts
Coordinates
Java 2D Rendering
Geometric Primitives
Text
Images
Printing
Home Page > 2D Graphics > Overview of the Java 2D API Concepts
« Previous • Trail • Next »
Geometric Primitives
The Java 2D™ API provides a useful set of standard shapes such as points, lines, rectangles, arcs, ellipses, and curves. The most important package to define common geometric primitives is the java.awt.geom package. Arbitrary shapes can be represented by combinations of straight geometric primitives.

The Shape interface represents a geometric shape, which has an outline and an interior. This interface provides a common set of methods for describing and inspecting two-dimensional geometric objects and supports curved line segments and multiple sub-shapes. The Graphics class supports only straight line segments. The Shape interface can support curves segments.

For more details about how to draw and fill shapes, see the Working with Geometry lesson.

Points

The Point2D class defines a point representing a location in (x, y) coordinate space. The term “point” in the Java 2D API is not the same as a pixel. A point has no area, does not contain a color, and cannot be rendered.

Points are used to create other shapes. ThePoint2D class also includes a method for calculating the distance between two points.

Lines

The Line2D class is an abstract class that represents a line. A line’s coordinates can be retrieved as double. The Line2D class includes several methods for setting a line’s endpoints.

Also, you can create a straight line segment by using the GeneralPath class described below.

Rectangular Shapes

The Rectangle2D, RoundRectangle2D, Arc2D, and Ellipse2D primitives are all derived from the RectangularShape class. This class defines methods for Shape objects that can be described by a rectangular bounding box. The geometry of a RectangularShape object can be extrapolated from a rectangle that completely encloses the outline of the Shape.

Quadratic and Cubic Curves

The QuadCurve2D enables you to create quadratic parametric curve segments. A quadratic curve is defined by two endpoints and one control point.

The CubicCurve2D class enables you to create cubic parametric curve segments. A cubic curve is defined by two endpoints and two control points. The following are examples of quadratic and cubic curves. See Stroking and Filling for implementations of cubic and quadratic curves.

This figure represents a quadratic curve.

Quadratic parametric curve

This figure represents a cubic curve.

Cubic parametric curve

Arbitrary Shapes

The GeneralPath class enables you to construct an arbitrary shape by specifying a series of positions along the shape’s boundary. These positions can be connected by line segments, quadratic curves, or cubic (Bézier) curves. The following shape can be created with three line segments and a cubic curve. See Stroking and Filling for more information about the implementation of this shape.

This figure represents a polyshape created by using the GeneralPath class

Areas

With the Area class, you can perform boolean operations, such as union, intersection, and subtraction, on any two Shape objects. This technique, often referred to as constructive area geometry, enables you to quickly create complex Shape objects without having to describe each line segment or curve.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Java 2D Rendering
Next page: Text


Text (The Java™ Tutorials > 2D Graphics > Overview of the Java 2D API Concepts)

Trail: 2D Graphics
Lesson: Overview of the Java 2D API Concepts
Overview of the Java 2D API Concepts
Coordinates
Java 2D Rendering
Geometric Primitives
Text
Images
Printing
Home Page > 2D Graphics > Overview of the Java 2D API Concepts
« Previous • Trail • Next »
Text
The Java 2D™ API has various text rendering capabilities including methods for rendering strings and entire classes for setting font attributes and performing text layout.

If you just want to draw a static text string, the most direct way to render it directly through the Graphics class by using the drawString method. To specify the font, you use the setFont method of the Graphics class.

If you want to implement your own text-editing routines or need more control over the layout of the text than the text components provide, you can use the Java 2D text layout classes in the java.awt.font package.

Fonts

The shapes that a font uses to represent the characters in a string are called glyphs. A particular character or combination of characters might be represented as one or more glyphs. For example, á might be represented by two glyphs, whereas the ligature fi might be represented by a single glyph.

A font can be thought of as a collection of glyphs. A single font might have many faces, such as italic and regular. All of the faces in a font have similar typographic features and can be recognized as members of the same family. In other words, a collection of glyphs with a particular style form a font face. A collection of font faces forms a font family. The collection of font families forms the set of fonts that are available on the system.

When you are using the Java 2D API, you specify fonts by using an instance of Font. You can determine what fonts are available by calling the static method GraphicsEnvironment.getLocalGraphicsEnvironment and then querying the returned GraphicsEnvironment. The getAllFonts method returns an array that contains Font instances for all of the fonts available on the system. The getAvailableFontFamilyNames method returns a list of the available font families.

Text Layout

Before text can be displayed, it must be laid out so that the characters are represented by the appropriate glyphs in the proper positions. The following are two Java 2D mechanisms for managing text layout:
  • The TextLayout class manages text layout, highlighting, and hit detection. The facilities provided by TextLayout handle the most common cases, including strings with mixed fonts, mixed languages, and bidirectional text. .
  • You can create the own GlyphVector objects by using the Font class and then rendering each GlyphVector object through the Graphics2D class. Thus, you can completely control how text is shaped and positioned. .

Rendering Hints for Text

The Java 2D API enables you to control the quality of shapes and text rendering by using rendering hints. Rendering hints are encapsulated by the java.awt.RenderingHints class.

As applied to text, this capability is used for antialiasing (which is also known as an smooth edges). For example, the KEY_TEXT_ANTIALIASING hint enables you to control the antialiasing of text separately from the antialiasing of other shapes. To learn more about rendering hints see the Controlling Rendering Quality lesson.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Geometric Primitives
Next page: Images


Images (The Java™ Tutorials > 2D Graphics > Overview of the Java 2D API Concepts)

Trail: 2D Graphics
Lesson: Overview of the Java 2D API Concepts
Overview of the Java 2D API Concepts
Coordinates
Java 2D Rendering
Geometric Primitives
Text
Images
Printing
Home Page > 2D Graphics > Overview of the Java 2D API Concepts
« Previous • Trail • Next »
Images
In the Java 2D™ API an image is typically a rectangular two-dimensional array of pixels, where each pixel represents the color at that position of the image and where the dimensions represent the horizontal extent (width) and vertical extent (height) of the image as it is displayed.

The most important image class for representing such images is the java.awt.image.BufferedImage class. The Java 2D API stores the contents of such images in memory so that they can be directly accessed.

Applications can directly create a BufferedImage object or obtain an image from an external image format such as PNG or GIF.

In either case, the application can then draw on to image by using Java 2D API graphics calls. So, images are not limited to displaying photographic type images. Different objects such as line art, text, and other graphics and even other images can be drawn onto an image (as shown on the following images).

This figure represents an images as a drawing surface

The Java 2D API enables you to apply image filtering operations to BufferedImage and includes several built-in filters. For example, the ConvolveOp filter can be used to blur or sharpen images.

The resulting image can then be drawn to a screen, sent to a printer, or saved in a graphics format such as PNG, GIF etc. To learn more about images see the Working with Images lesson lesson.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Text
Next page: Printing


Printing (The Java™ Tutorials > 2D Graphics > Overview of the Java 2D API Concepts)

Trail: 2D Graphics
Lesson: Overview of the Java 2D API Concepts
Overview of the Java 2D API Concepts
Coordinates
Java 2D Rendering
Geometric Primitives
Text
Images
Printing
Home Page > 2D Graphics > Overview of the Java 2D API Concepts
« Previous • Trail • Next »
Printing
All of the Swing and Java 2D™ graphics, including composited graphics and images, can be rendered to a printer by using the Java 2D Printing API. This API also provides document composition features that enable you to perform such operations as changing the order in which pages are printed.

Rendering to a printer is like rendering to a screen. The printing system controls when pages are rendered, just like the drawing system controls when a component is painted on the screen.

The Java 2D Printing API is based on a callback model in which the printing system, not the application, controls when pages are printed. The application provides the printing system with information about the document to be printed, and the printing system determines when each page needs to be imaged.

The following two features are important to support printing:

  • Job control – Initiating and managing the print job including displaying the standard print and setup dialog boxes
  • Pagination – Rendering each page when the printing system requests it

When pages need to be imaged, the printing system calls the application’s print method with an appropriate Graphics context. To use Java 2D API features when you print, you cast the Graphics object to a Graphics2D class, just like you do when you are rendering to the screen.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Images
Next page: Getting Started with Graphics


Lesson: Getting Started with Graphics (The Java™ Tutorials > 2D Graphics)

Trail: 2D Graphics
Home Page > 2D Graphics
« Previous • Trail • Next »
Lesson: Getting Started with Graphics
The Java 2D™ API is powerful and complex. However, the vast majority of uses for the Java 2D API utilize a small subset of its capabilities encapsulated in the java.awt.Graphics class. This lesson covers the most common needs of applications developers. Less common needs are described later in the Advanced topics in the Java 2D API lesson.

Most methods of the Graphics class can be divided into two basic groups:

  • Draw and fill methods, enabling you to render basic shapes, text, and images
  • Attributes setting methods, which affect how that drawing and filling appears

Methods such as setFont and setColor define how draw and fill methods render.

This figure illustrates how these methods relate to graphic objects:

This figure represents basic methods of the Graphics class

Drawing methods include:

  • drawString – For drawing text
    •    g.drawString("Hello", 10, 10);
  • drawImage – For drawing images
    •    g.drawImage(img,
                    0, 0, width, height,
                    0, 0, imageWidth, imageHeight,
                    null);
  • drawLine, drawArc, drawRect, drawOval, drawPolygon – For drawing geometric shapes
    • g2.draw(new Line2D.Double(0, 0, 30, 40));

Depending on your current need, you can choose one of several methods in the Graphics class based on the following criteria:

  • Whether you want to render the image at the specified location in its original size or scale it to fit inside the given rectangle
  • Whether you prefer to fill the transparent areas of the image with color or keep them transparent

Fill methods apply to geometric shapes and include fillArc, fillRect, fillOval, fillPolygon.

Whether you draw a line of text or an image, remember that in 2D graphics every point is determined by its x and y coordinates. All of the draw and fill methods need this information which determines where the text or image should be rendered.

For example, to draw a line, an application calls the following:

java.awt.Graphics.drawLine(int x1, int y1, int x2, int y2)

In this code (x1, y1) is the start point of the line, and (x2, y2) is the end point of the line.

So the code to draw a horizontal line is as follows:

Graphics.drawLine(20, 100, 120, 100);

The demo below accumulates all mentioned techniques. Move the slider to display various weather types.

Note: If you don't see the applet running above, you need to install release 6 of the JDK.

The WeatherWizard demo uses the JSlider component as well as various graphics capabilities to generate and display a specified weather type. For more information about the JSlider class see the How to Use Sliders section of the Swing Tutorial.

The paint method of the WeatherPainter class implements graphics features. The following code draws an image determined by using the setupWeatherReport() method.

        ...
        origComposite = g2.getComposite();
        if (alpha0 != null) g2.setComposite(alpha0);
        g2.drawImage(img0,
                0, 0, size.width, size.height,
                0, 0, img0.getWidth(null), img0.getHeight(null),
                null);
        if (img1 != null) {
            if (alpha1 != null) g2.setComposite(alpha1);
            g2.drawImage(img1,
                    0, 0, size.width, size.height,
                    0, 0, img1.getWidth(null), img1.getHeight(null),
                    null);
        }
        ...

The setFont and drawString methods render the temperature and the weather condition.

        ...
        // Freezing, Cold, Cool, Warm, Hot,
        // Blue, Green, Yellow, Orange, Red
        Font font = new Font("Serif", Font.PLAIN, 36);
        g.setFont(font);

        String tempString = feels + " " + temperature+"F";
        FontRenderContext frc = ((Graphics2D)g).getFontRenderContext();
        ...
        g.setColor(textColor);
        int xTextTemp = rX-(int)boundsTemp.getX();
        int yTextTemp = rY-(int)boundsTemp.getY();
        g.drawString(tempString, xTextTemp, yTextTemp);

        int xTextCond = rX-(int)boundsCond.getX();
        int yTextCond = rY-(int)boundsCond.getY() + (int)boundsTemp.getHeight();
        g.drawString(condStr, xTextCond, yTextCond);

The fillRect method allows you to draw a rectangle filled with the specified color.

        ...
        Rectangle2D boundsTemp = font.getStringBounds(tempString, frc);
        Rectangle2D boundsCond = font.getStringBounds(condStr, frc);
        int wText = Math.max((int)boundsTemp.getWidth(), (int)boundsCond.getWidth());
        int hText = (int)boundsTemp.getHeight() + (int)boundsCond.getHeight();
        int rX = (size.width-wText)/2;
        int rY = (size.height-hText)/2;

        g.setColor(Color.LIGHT_GRAY);
        g2.fillRect(rX, rY, wText, hText);
    ...
Try to modify the WeatherWizard demo to alter the graphical content. For example, use the fillRoundRect method instead of fillRect or apply another font size in the setFont method. Find the complete code for this applet in the WeatherWizard.java file. The demo also requires the following images: weather-cloud.png, weather-rain.png, weather-snow.png, and weather-sun.png located in the images directory.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Working with Geometry


Lesson: Working with Geometry (The Java™ Tutorials > 2D Graphics)

Working with Geometry
Drawing Geometric Primitives
Drawing Arbitrary Shapes
Stroking and Filling Graphics Primitives
Trail: 2D Graphics
Home Page > 2D Graphics
« Previous • Trail • Next »
Lesson: Working with Geometry
In prior lessons, you have learned the graphics concept, including basic information about the coordinate system and graphic object creation. Now, you will progress to more detailed lessons about the 2D graphics classes. This lesson shows you how to use the Graphics2D class to draw graphic primitives as well as arbitrary shapes, and how to display graphics with fancy outline and fill styles. These topics are discussed in the following sections.

Drawing Geometric Primitives

This section explains how to create standard shapes such as points, lines, curves, arcs, rectangles, and ellipses.

Drawing Arbitrary Shapes

This section explains how to draw shapes represented by combinations of straight geometric primitives by using the GeneralPath class.

Filling and Stroking

This section explains how to set the stroke and paint attributes to control the outline and fill styles applied to Shape objects and text.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Drawing Geometric Primitives


Drawing Geometric Primitives (The Java™ Tutorials > 2D Graphics > Working with Geometry)

Trail: 2D Graphics
Lesson: Working with Geometry
Working with Geometry
Drawing Geometric Primitives
Drawing Arbitrary Shapes
Stroking and Filling Graphics Primitives
Home Page > 2D Graphics > Working with Geometry
« Previous • Trail • Next »
Drawing Geometric Primitives
The Java 2D™ API provides several classes that define common geometric objects such as points, lines, curves, and rectangles. These geometry classes are part of the java.awt.geom package.
The PathIterator interface defines methods for retrieving elements from a path.
The Shape interface provides a set of methods for describing and inspecting geometric path objects. This interface is implemented by the GeneralPath class and other geometry classes.

All examples represented in this section create geometries by using java.awt.geom and then render them by using the Graphics2D class. To begin you obtain a Graphics2D object, for example by casting the Graphics parameter of the paint() method.

public void paint (Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    ...
}

Point

The Point class creates a point representing a location in (x,y) coordinate space. The subclasses Point2D.Float and Point2D.Double provide correspondingly float and double precision for storing the coordinates of the point.
//Create Point2D.Double
Point2D.Double point = new Point2D.Double(x, y);
To create a point with the coordinates 0,0 you use the default constructor, Point2D.Double().
You can use the setLocation method to set the position of the point as follows:
  • setLocation(double x, double y) – To set the location of the point- defining coordinates as double values
  • setLocation(Point2D p) – To set the location of the point using the coordinates of another point.
Also, the Point2D class has methods to calculate the distance between the current point and a point with given coordinates, or the distance between two points.

Line

The Line2D class represents a line segment in (x, y) coordinate space. The Line2D.Float and Line2D.Double subclasses specify lines in float and double precision. For example:

// draw Line2D.Double
g2.draw(new Line2D.Double(x1, y1, x2, y2));
Line

This class includes several setLine() methods to define the endpoints of the line.
Aternatively, the endpoints of the line could be specified by using the constructor for the Line2D.Float class as follows:

  • Line2D.Float(float X1, float Y1, float X2, float Y2)
  • Line2D.Float(Point2D p1, Point2D p2)
Use the Stroke object in the Graphics2D class to define the stroke for the line path.

Curves

The java.awt.geom package enables you to create a quadratic or cubic curve segment.

Quadratic Curve Segment

The QuadCurve2D class implements the Shape interface. This class represents a quadratic parametric curve segment in (x, y) coordinate space. The QuadCurve2D.Float and QuadCurve2D.Double subclasses specify a quadratic curve in float and double precision.

Several setCurve methods are used to specify two endpoints and a control point of the curve, whose coordinates can be defined directly, by the coordinates of other points and by using a given array.
A very useful method, setCurve(QuadCurve2D c), sets the quadratic curve with the same endpoints and the control point as a supplied curve. For example:

// create new QuadCurve2D.Float
QuadCurve2D q = new QuadCurve2D.Float();
// draw QuadCurve2D.Float with set coordinates
q.setCurve(x1, y1, ctrlx, ctrly, x2, y2);
g2.draw(q);
Quadratic parametric curve segment

Cubic Curve Segment

The CubicCurve2D class also implements the Shape interface. This class represents a cubic parametric curve segment in (x, y) coordinate space. CubicCurve2D.Float and CubicCurve2D.Double subclasses specify a cubic curve in float and double precision.

The CubicCurve2D class has similar methods for setting the curve as the QuadraticCurve2Dclass, except with a second control point. For example:

// create new CubicCurve2D.Double
CubicCurve2D c = new CubicCurve2D.Double();
// draw CubicCurve2D.Double with set coordinates
c.setCurve(x1, y1, ctrlx1,
          ctrly1, ctrlx2, ctrly2, x2, y2);
g2.draw(c);
Cubic Curve Segment

Rectangle

Classes that specify primitives represented in the following example extend the RectangularShape class, which implements the Shape interface and adds a few methods of its own.

These methods enables you to get information about a shape’s location and size, to examine the center point of a rectangle, and to set the bounds of the shape.

The Rectangle2D class represents a rectangle defined by a location (x, y) and dimension (w x h). The Rectangle2D.Float and Rectangle2D.Double subclasses specify a rectangle in float and double precision. For example:

// draw Rectangle2D.Double
g2.draw(new Rectangle2D.Double(x, y,
                               rectwidth,
                               rectheight));
Rectangle

The RoundRectangle2D class represents a rectangle with rounded corners defined by a location (x, y), a dimension (w x h), and the width and height of the corner arc. The RoundRectangle2D.Float and RoundRectangle2D.Double subclasses specify a round rectangle in float and double precision.

The rounded rectangle is specified with following parameters:

  • Location
  • Width
  • Height
  • Width of the corner arc
  • Height of the corner acr
To set the location, size, and arcs of a RoundRectangle2D object, use the method setRoundRect(double a, double y, double w, double h, double arcWidth, double arcHeight). For example:

// draw RoundRectangle2D.Double
g2.draw(new RoundRectangle2D.Double(x, y,
                                   rectwidth,
                                   rectheight,
                                   10, 10));
Rounded Rectangle

Ellipse

The Ellipse2d class represents an ellipse defined by a bounding rectangle. The Ellipse2D.Float and Ellipse2D.Double subclasses specify an ellipse in float and double precision.

Ellipse is fully defined by a location, a width and a height. For example:

// draw Ellipse2D.Double
g2.draw(new Ellipse2D.Double(x, y,
                             rectwidth,
                             rectheight));
Ellipse

Arc

To draw a piece of an ellipse, you use the Arc2D class. This class represents an arc defined by a bounding rectangle, a start angle, an angular extent, and a closure type. The Arc2D.Float and Arc2D.Double subclasses specify an ellipse in float and double precision.

The Arc2D class defines the following three types of arcs, represented by corresponding constants in this class: OPEN, PIE and CHORD.

Several methods set the size and parameters of the arc:

  • Directly, by coordinates
  • By supplied Point2D and Dimension2D
  • By copying an existing Arc2D
Also, you can use the setArcByCenter method to specify an arc from a center point, given by its coordinates and a radius.

// draw Arc2D.Double
g2.draw(new Arc2D.Double(x, y,
                         rectwidth,
                         rectheight,
                         90, 135,
                         Arc2D.OPEN));
Arc

The ShapesDemo2D.java code example contains implementations off all described geometric primitives. For more information about classes and methods represented in this section see the java.awt.geom specification.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Working with Geometry
Next page: Drawing Arbitrary Shapes


Drawing Arbitrary Shapes (The Java™ Tutorials > 2D Graphics > Working with Geometry)

Trail: 2D Graphics
Lesson: Working with Geometry
Working with Geometry
Drawing Geometric Primitives
Drawing Arbitrary Shapes
Stroking and Filling Graphics Primitives
Home Page > 2D Graphics > Working with Geometry
« Previous • Trail • Next »
Drawing Arbitrary Shapes
You have already learned how to draw most of shapes represented in the java.awt.geom package. To create more complicated geometry, such as polygons, polylines, or stars you use another class from this package, GeneralPath.

This class implements the Shape interface and represents a geometric path constructed from lines, and quadratic and cubic curves. The three constructors in this class can create the GeneralPath object with the default winding rule (WIND_NON_ZERO), the given winding rule (WIND_NON_ZERO or WIND_EVEN_ODD), or the specified initial coordinate capacity. The winding rule specifies how the interior of a path is determined.

public void Paint (Graphics g) {
    Graphics2D g2 = (Graphics2D) g;
    ...
}

To create an empty GeneralPath instance call new GeneralPath() and then add segments to the shape by using the following methods:

  • moveTo(float x, float y) – Moves the current point of the path to the given point
  • lineTo(float x, float y) – Adds a line segment to the current path
  • quadTo(float ctrlx, float ctrly, float x2, floaty2) – Adds a quadratic curve segment to the current path
  • curveTo(float ctrlx1, float ctrly1, float ctrlx2, float ctrly2, float x3, floaty3) – Adds a cubic curve segment to the current path
  • closePath() – Closes the current path

The following example illustrates how to draw a polyline by using GeneralPath:
// draw GeneralPath (polyline)
int x2Points[] = {0, 100, 0, 100};
int y2Points[] = {0, 50, 50, 0};
GeneralPath polyline =
    new GeneralPath(GeneralPath.WIND_EVEN_ODD, x2Points.length);

polyline.moveTo (x2Points[0], y2Points[0]);

for (int index = 1; index < x2Points.length; index++) {
      polyline.lineTo(x2Points[index], y2Points[index]);
};

g2.draw(polyline);
This image represents a polyline

This example illustrates how to draw a polygon by using GeneralPath:
// draw GeneralPath (polygon)
int x1Points[] = {0, 100, 0, 100};
int y1Points[] = {0, 50, 50, 0};
GeneralPath polygon =
    new GeneralPath(GeneralPath.WIND_EVEN_ODD, x1Points.length);
polygon.moveTo(x1Points[0], y1Points[0]);

for (int index = 1; index < x1Points.length; index++) {
        polygon.lineTo(x1Points[index], y1Points[index]);
};

polygon.closePath();
g2.draw(polygon);
This image represents a polygon

Note that the only difference between two last code examples is the closePath() method. This method makes a polygon from a polyline by drawing a straight line back to the coordinates of the last moveTo.

To add a specific path to the end of your GeneralPath object you use one of the append() methods. The ShapesDemo2D.java code example contains additional implementations of arbitrary shapes.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Drawing Geometric Primitives
Next page: Stroking and Filling Graphics Primitives


Stroking and Filling Graphics Primitives (The Java™ Tutorials > 2D Graphics > Working with Geometry)

Trail: 2D Graphics
Lesson: Working with Geometry
Working with Geometry
Drawing Geometric Primitives
Drawing Arbitrary Shapes
Stroking and Filling Graphics Primitives
Home Page > 2D Graphics > Working with Geometry
« Previous • Trail • Next »
Stroking and Filling Graphics Primitives

You already know how to create different geometric primitives and more complicated shapes. This lesson teaches how to add some color and fancy outlines to your graphics and represents filling and stroking:

  • Filling – is a process of painting the shape’s interior with solid color or a color gradient, or a texture pattern
  • Stroking – is a process of drawing a shape’s outline applying stroke width, line style, and color attribute

To apply fancy line styles and fill patterns to geometric primitives change the stroke and paint attributes in the Graphics2D context before rendering. For example, draw a dashed line by creating an appropriate Stroke object. To add this stroke to the Graphics2D context before you render the line call the setStroke method . Similarly, you apply a gradient fill to a Shape object by creating a GradientPaint object and adding it to the Graphics2D context.

The following code lines enrich geometric primitives with filling and stroking context:
// draw RoundRectangle2D.Double

final static float dash1[] = {10.0f};
    final static BasicStroke dashed = new BasicStroke(1.0f,
                                          BasicStroke.CAP_BUTT,
                                          BasicStroke.JOIN_MITER,
                                          10.0f, dash1, 0.0f);
g2.setStroke(dashed);
g2.draw(new RoundRectangle2D.Double(x, y,
                                   rectWidth,
                                   rectHeight,
                                   10, 10));
Dashed rounded rectangle
// fill Ellipse2D.Double
redtowhite = new GradientPaint(0,0,color.RED,100, 0,color.WHITE);
g2.setPaint(redtowhite);
g2.fill (new Ellipse2D.Double(0, 0, 100, 50));
Polygon filled with gradient color

The ShapesDemo2D.java code example represents additional implementations of stoking and filling.

Defining Fancy Line Styles and Fill Patterns

Using the Java 2D™ Stroke and Paint classes, you can define fancy line styles and fill patterns.

Line Styles

Line styles are defined by the stroke attribute in the Graphics2D rendering context. To set the stroke attribute, you create a BasicStroke object and pass it into the Graphics2D setStroke method.

A BasicStroke object holds information about the line width, join style, end-cap style, and dash style. This information is used when a Shape is rendered with the draw method.

The line width is the thickness of the line measured perpendicular to its trajectory. The line width is specified as a float value in user coordinate units, which are roughly equivalent to 1/72 of an inch when the default transform is used.

The join style is the decoration that is applied where two line segments meet. BasicStroke supports the following three join styles:

Join bevel stroke style JOIN_BEVEL

Join miter stroke style JOIN_MITER

Join round stroke style JOIN_ROUND

The end-cap style is the decoration that is applied where a line segment ends. BasicStroke supports the following three end-cap styles:

Butt end-cap style CAP_BUTT

Round end-cap style CAP_ROUND

Square end-cap style CAP_SQUARE

The dash style defines the pattern of opaque and transparent sections applied along the length of the line. The dash style is defined by a dash array and a dash phase. The dash array defines the dash pattern. Alternating elements in the array represent the dash length and the length of the space between dashes in user coordinate units. Element 0 represents the first dash, element 1 the first space, and so on. The dash phase is an offset into the dash pattern, also specified in user coordinate units. The dash phase indicates what part of the dash pattern is applied to the beginning of the line.

Fill Patterns

Fill patterns are defined by the paint attribute in the Graphics2D rendering context. To set the paint attribute, you create an instance of an object that implements the Paint interface and pass it into the Graphics2D setPaint method.

The following three classes implement the Paint interface: Color, GradientPaint, and TexturePaint.

To create a GradientPaint, you specify a beginning position and color and an ending position and color. The gradient changes proportionally from one color to the other color along the line connecting the two positions. For example:

The pattern for a TexturePaint class is defined by a BufferedImage class. To create a TexturePaint object, you specify the image that contains the pattern and a rectangle that is used to replicate and anchor the pattern. The following image represents this feature:

Using a texture to fill a rectangle

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Drawing Arbitrary Shapes
Next page: Working with Text APIs


Lesson: Working with Text APIs (The Java™ Tutorials > 2D Graphics)

Working with Text APIs
Selecting a Font
Measuring Text
Advanced Text Display
Displaying Antialiased Text by Using Rendering Hints
Using Text Attributes to Style Text
Drawing Multiple Lines of Text
Trail: 2D Graphics
Home Page > 2D Graphics
« Previous • Trail • Next »
Lesson: Working with Text APIs

This lesson introduces you to the concept of working with text API’s to apply text rendering capabilities. Already in this trail, you have used basic Java 2D™ text APIs and know how to set a font and position, and how to draw text.

This lesson expands on that material to help you develop an understanding of how to use those APIs and moves further into the capabilities of Java 2D text display.

These topics are discussed in the following sections.

Selecting a font

This section explains how to use the methods of the Font class to determine which fonts are available on your system, to create a Font object, and obtain information about a font family.

Measuring Text

This section explains how to properly measure text by using an instance of the FontMetrics class.

Advanced Text Display

This section explains how to position and render a paragraph of styled text, how to display antialiased text, and how to use text attributes to style text.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Selecting a Font


Selecting a Font (The Java™ Tutorials > 2D Graphics > Working with Text APIs)

Trail: 2D Graphics
Lesson: Working with Text APIs
Working with Text APIs
Selecting a Font
Measuring Text
Advanced Text Display
Displaying Antialiased Text by Using Rendering Hints
Using Text Attributes to Style Text
Drawing Multiple Lines of Text
Home Page > 2D Graphics > Working with Text APIs
« Previous • Trail • Next »
Selecting a Font

Java 2D™ defines the following five logical font families:

  • Dialog
  • DialogInput
  • Monospaced
  • Serif
  • SansSerif

These fonts are available on any Java platform and can be thought of as aliases for some underlying font that has the properties implied by its name. A Serif font is a font similar to Times New Roman, which is commonly used in print. A Sans Serif font is more typical for onscreen use.

These fonts can be customized for the locale of the user. In addition these fonts support the widest range of code points (unicode characters).

Apart from the family, fonts have other attributes, the most important of which are style and size. Styles are Bold and Italic.

The default Java 2D font is 12 pt Dialog. This font is a typical point size for reading text on a normal 72–120 DPI display device. An application can create an instance of this font directly by specifying the following:

Font font = new Font("Dialog", Font.PLAIN, 12);

In addition to the logical fonts, Java software provides access to other fonts that are installed on your system. The names of all available font families can be found by calling the following:

GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
String []fontFamilies = ge.getAvailableFontFamilyNames();

The FontSelector sample program (available in FontSelector.java) illustrates how to locate and select these fonts. You can use this example to view how Sans Serif appears on your system. These other fonts are called physical fonts.

Note: Applications should not assume that any particular physical font is present. However, the logical fonts are a safe choice because they are always present.

Note: If you don't see the applet running above, you need to install release 6 of the JDK.

Sometimes, an application cannot depend on a font being installed on the system, usually because the font is a custom font that is not otherwise available. In this case, the application must include the font. This lesson shows how to obtain a TrueType font, the most commonly used font type on modern operating systems, to a java.awt.Font object.

You can use either of these methods:

Font java.awt.Font.createFont(int fontFormat, InputStream in);
Font java.awt.Font.createFont(int fontFormat, File fontFile);
To identify a TrueType font, fontFormat must be the constant Font.TRUETYPE_FONT.
Font font = Font.createFont(Font.TRUETYPE_FONT, new File("A.ttf"));

Accessing the font directly from a file must be more convenient for some cases. However, an InputStream might be needed if your code is unable to access file system resources, or if the font is packaged in a Java Archive (JAR) file along with the rest of the application or applet.

The returned Font instance can then be used with the Font.deriveFont(..) methods to derive a version that is the required size. For example:

try {
     /* Returned font is of pt size 1 */
     Font font = Font.createFont(Font.TRUETYPE_FONT, new File("A.ttf"));

     /* derive and return a 12 pt version : need to use float otherwise
      * it would be interpreted as style
      */
     return font.deriveFont(12f);

} catch (IOException ioe);
} catch (FontFormatException ffe);
}

It is important to use deriveFont() because fonts which are created by application are not part of the set of fonts known to the underlying font system. Because deriveFont works from the original created font it does not have this limitation.

The solution for this problem is to register the created font with the graphics environment. For example:

try {
     GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
     ge.registerFont(Font.createFont(Font.TRUETYPE_FONT, new File("A.ttf"));
} catch (IOException ioe);
} catch (FontFormatException ffe);
}
After this step is done, the font is available in calls to getAvailableFontFamilyNames() and can be used in font constructors.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Working with Text APIs
Next page: Measuring Text


Measuring Text (The Java™ Tutorials > 2D Graphics > Working with Text APIs)

Trail: 2D Graphics
Lesson: Working with Text APIs
Working with Text APIs
Selecting a Font
Measuring Text
Advanced Text Display
Displaying Antialiased Text by Using Rendering Hints
Using Text Attributes to Style Text
Drawing Multiple Lines of Text
Home Page > 2D Graphics > Working with Text APIs
« Previous • Trail • Next »
Measuring Text

To properly measure text, you need to learn a few methods and some mistakes to avoid. Font metrics are measurements of text rendered by a Font object such as the height of a line of text in the font. The most common way to measure text is to use a FontMetrics instance which encapsulates this metrics information. For example:

    // get metrics from the graphics
    FontMetrics metrics = graphics.getFontMetrics(font);
    // get the height of a line of text in this font and render context
    int hgt = metrics.getHeight();
    // get the advance of my text in this font and render context
    int adv = metrics.stringWidth(text);
    // calculate the size of a box to hold the text with some padding.
    Dimension size = new Dimension(adv+2, hgt+2);
This way is sufficient for many applications to evenly space lines of text or to size Swing components.

Note the following:

  • The metrics are obtained from the Graphics class, because this class encapsulates the FontRenderContext, which is needed to accurately measure text. At screen resolutions, fonts are adjusted for ease of reading. As text size increases, this adjustment does not scale linearly. So, at 20 pt, a font will not display text exactly twice the length as it would at 10 pt. Besides the text itself and the font, the other important piece of information needed to measure text is the FontRenderContext. This method includes the transform from user space to device pixels that is used in measuring text.
  • The height is reported without reference to any particular string of text. It is useful, for example in, a text editor where you want the same line spacing between each line of text.
  • stringWidth() returns the advance width of the text. Advance width is the distance from the origin of the text to the position of a subsequently rendered string.

    • When using these methods to measure text, note that the text can extend in any direction outside of a rectangle, defined by the font height and the advance of the string.

    This figure shows hot to measure text by using font metrics

    Typically, the simplest solution is to ensure that the text is not clipped, for example, by components that surround the text. Add padding in cases where the text might otherwise be clipped.

    If this solution is insufficient, other text measurement APIs in the Java 2D™ software can return rectangular bounding boxes. These boxes account for the height of the specific text to be measured and for pixelization effects.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Selecting a Font
Next page: Advanced Text Display


Advanced Text Display (The Java™ Tutorials > 2D Graphics > Working with Text APIs)

Trail: 2D Graphics
Lesson: Working with Text APIs
Working with Text APIs
Selecting a Font
Measuring Text
Advanced Text Display
Displaying Antialiased Text by Using Rendering Hints
Using Text Attributes to Style Text
Drawing Multiple Lines of Text
Home Page > 2D Graphics > Working with Text APIs
« Previous • Trail • Next »
Advanced Text Display

The Java 2D™ API provides mechanisms to support sophisticated text layout. This section describes following features of advanced text display.

Displaying Antialiased Text by Using Rendering Hints

This section explains how to control the rendering quality through the use of rendering hints.

Using Text Attributes to Style Text

This section explains how to use the TextAttribute class to underline or strikethough text.

Drawing Multiple Lines of Text

This section explains how to position and render a paragraph of styled text by using the TextLayout and LineBreakMeasurer classes.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Measuring Text
Next page: Displaying Antialiased Text by Using Rendering Hints


Displaying Antialiased Text by Using Rendering Hints (The Java™ Tutorials > 2D Graphics > Working with Text APIs)

Trail: 2D Graphics
Lesson: Working with Text APIs
Section: Advanced Text Display
Working with Text APIs
Selecting a Font
Measuring Text
Advanced Text Display
Displaying Antialiased Text by Using Rendering Hints
Using Text Attributes to Style Text
Drawing Multiple Lines of Text
Home Page > 2D Graphics > Working with Text APIs
« Previous • Trail • Next »
Displaying Antialiased Text by Using Rendering Hints

Java 2D™ text rendering can be affected by rendering hints.

Recall that the most important text drawing method is the following:

Graphics.drawString(String s, int x, int y);
Usually, this method draws each glyph in a string of text with a solid color and each pixel that is “on” in that glyph is set to that colour. This type of drawing produces the highest contrast text, but sometimes with jagged (aliased) edges.

Text antialiasing is a technique used to smooth the edges of text on a screen. The Java 2D API enables applications to specify whether this technique should be used and what algorithm to use by applying a text rendering hint to the Graphics.

The most common rendering hint blends the foreground (text) color with the onscreen background pixels at the edges of the text. To request this hint an application must invoke the following:

graphics2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                           (RenderingHints.VALUE_TEXT_ANTIALIAS_ON);

The following figure illustrates the antialiasing capability.

This figure represents an antialiasing hint for the Hello World string.

If used inappropriately this method can make the text appear overly fuzzy. In such cases, a better hint to use is the following:

graphics2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                           (RenderingHints.VALUE_TEXT_ANTIALIAS_GASP);

This method automatically uses information in the font itself to decide whether to use antialiasing or to use solid colors.

LCD displays have a property that the Java 2D API can use to produce text that isn't as fuzzy as typical antialiasing but is more legible at small sizes. To request that text be drawn using the sub-pixel LCD text mode for a typical LCD display, an application must invoke the following:

graphics2D.setRenderingHint(RenderingHints.KEY_TEXT_ANTIALIASING,
                           (RenderingHints.VALUE_TEXT_ANTIALIAS_LCD_HRGB);
The code example represented below illustrates the antialiasing capability in the following order:
  1. Antialiasing is off.
  2. Antialiasing is on.
  3. Antialiasing using the TEXT_ANTIALIAS_GASP hint.
    4. Note: Consequently the GASP table specifies to use only hinting at those sizes and not "smoothing". So in many cases the resulting text display is equivalent to VALUE_TEXT_ANTIALIAS_OFF.
  4. Antialiasing using the TEXT_ANTIALIAS_LCD_HRGB hint.

Note: If you don't see the applet running above, you need to install release 6 of the JDK. The complete code for this applet is in AntialiasedText.java.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Advanced Text Display
Next page: Using Text Attributes to Style Text


Using Text Attributes to Style Text (The Java™ Tutorials > 2D Graphics > Working with Text APIs)

Trail: 2D Graphics
Lesson: Working with Text APIs
Section: Advanced Text Display
Working with Text APIs
Selecting a Font
Measuring Text
Advanced Text Display
Displaying Antialiased Text by Using Rendering Hints
Using Text Attributes to Style Text
Drawing Multiple Lines of Text
Home Page > 2D Graphics > Working with Text APIs
« Previous • Trail • Next »
Using Text Attributes to Style Text

Applications typically need the capability to apply the following text attributes:

  • Underline – A line that is drawn underneath text
  • Strikethrough – A horizontal line that is drawn through the text
  • Superscript or Subscript – A text or a letter that appears slightly above a line or correspondingly below a line
  • Kerning – The adjustment of the space between characters

These and other text attributes can be applied by using the Java 2D™ TextAttribute class.

To apply these text attributes by add them to a Font object. For example:

Map<TextAttribute, Object> map = new Hashtable<TextAttribute, Object>();
map.put(TextAttribute.KERNING, TextAttribute.KERNING_ON);
font = font.deriveFont( map );
graphics.setFont( font );

The code example represented below shows the application of text attributes in the following order:

  1. Sample string (no text attributes applied)
  2. Kerning
  3. Kerning and Underlining
  4. Kerning,Underlining and Strikethrough
  5. Kerning,Underlining, Strikethrough and Color

Note: If you don't see the applet running above, you need to install release 6 of the JDK. The complete code for this applet is in AttributedText.java.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Displaying Antialiased Text by Using Rendering Hints
Next page: Drawing Multiple Lines of Text


Drawing Multiple Lines of Text (The Java™ Tutorials > 2D Graphics > Working with Text APIs)

Trail: 2D Graphics
Lesson: Working with Text APIs
Section: Advanced Text Display
Working with Text APIs
Selecting a Font
Measuring Text
Advanced Text Display
Displaying Antialiased Text by Using Rendering Hints
Using Text Attributes to Style Text
Drawing Multiple Lines of Text
Home Page > 2D Graphics > Working with Text APIs
« Previous • Trail • Next »
Drawing Multiple Lines of Text

If you have a paragraph of styled text that you would like to fit within a specific width, you can use the LineBreakMeasurer class. This class enables styled text to be broken into lines so that they fit within a particular visual advance. Each line is returned as a TextLayout object, which represents unchangeable, styled character data. However, this class also enables access to layout information. The getAscent and getDescent methods of TextLayout return information about the font that is used to position the lines in the component. The text is stored as an AttributedCharacterIterator object so that the font and point size attributes can be stored with the text.

The following applet positions a paragraph of styled text within a component, using LineBreakMeasurer, TextLayout and AttributedCharacterIterator.

Note: If you don't see the applet running above, you need to install release 6 of the JDK. The complete code for this applet is in LineBreakSample.java.

The following code creates an iterator with the string vanGogh. The start and end of the iterator is retrieved and a new LineBreakMeasurer is created from the iterator.

    AttributedCharacterIterator paragraph = vanGogh.getIterator();
    paragraphStart = paragraph.getBeginIndex();
    paragraphEnd = paragraph.getEndIndex();
    FontRenderContext frc = g2d.getFontRenderContext();
    lineMeasurer = new LineBreakMeasurer(paragraph, frc);

The size of the window is used to determine where the line should break. Also a TextLayout object is created for each line in the paragraph.

        // Set break width to width of Component.
        float breakWidth = (float)getSize().width;
        float drawPosY = 0;
        // Set position to the index of the first character in the paragraph.
        lineMeasurer.setPosition(paragraphStart);

        // Get lines from until the entire paragraph has been displayed.
        while (lineMeasurer.getPosition() < paragraphEnd) {

            TextLayout layout = lineMeasurer.nextLayout(breakWidth);

            // Compute pen x position. If the paragraph is right-to-left we
            // will align the TextLayouts to the right edge of the panel.
            float drawPosX = layout.isLeftToRight()
                ? 0 : breakWidth - layout.getAdvance();

            // Move y-coordinate by the ascent of the layout.
            drawPosY += layout.getAscent();

            // Draw the TextLayout at (drawPosX, drawPosY).
            layout.draw(g2d, drawPosX, drawPosY);

            // Move y-coordinate in preparation for next layout.
            drawPosY += layout.getDescent() + layout.getLeading();
        }

The TextLayout class is not frequently created directly by applications. However, this class is useful when applications need to work directly with text that has had styles (text attributes) applied at specific positions in text. For example, to draw a single word italicized in a paragraph, an application would need to perform measurements and set the font for each substring. If the text is bidirectional, this task is not so easy to do correctly. Creating a TextLayout object from an AttributedString object handles this problem for you. Consult the Java SE specification for more information about TextLayout.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Text Attributes to Style Text
Next page: Working with Images


Lesson: Working with Images (The Java™ Tutorials > 2D Graphics)

Working with Images
Reading/Loading an Image
Drawing an Image
Creating and Drawing to an Image
Writing/Saving an Image
Trail: 2D Graphics
Home Page > 2D Graphics
« Previous • Trail • Next »
Lesson: Working with Images

As you have already learned from the Overview lesson, Images are described by a width and a height, measured in pixels, and have a coordinate system that is independent of the drawing surface.

There are a number of common tasks when working with images.

  • Loading an external GIF, PNG JPEG image format file into Java 2D™'s internal image representation.
  • Directly creating a Java 2D image and rendering to it.
  • Drawing the contents of a Java 2D image on to a drawing surface.
  • Saving the contents of a Java 2D image to an external GIF, PNG, or JPEG image file.

This lesson teaches you the basics of loading, displaying, and saving images.

The are two main classes that you must learn about to work with images:

  • The java.awt.Image class is the superclass that represents graphical images as rectangular arrays of pixels.
  • The java.awt.image.BufferedImage class, which extends the Image class to allow the application to operate directly with image data (for example, retrieving or setting up the pixel color). Applications can directly construct instances of this class.

The BufferedImage class is a cornerstone of the Java 2D immediate-mode imaging API. It manages the image in memory and provides methods for storing, interpreting, and obtaining pixel data. Since BufferedImage is a subclass of Image it can be rendered by the Graphics and Graphics2D methods that accept an Image parameter.

A BufferedImage is essentially an Image with an accessible data buffer. It is therefore more efficient to work directly with BufferedImage. A BufferedImage has a ColorModel and a Raster of image data. The ColorModel provides a color interpretation of the image's pixel data.

The Raster performs the following functions:

  • Represents the rectangular coordinates of the image
  • Maintains image data in memory
  • Provides a mechanism for creating multiple subimages from a single image data buffer
  • Provides methods for accessing specific pixels within the image

The basic operations with images are represented in the following sections:

Reading/Loading an image

This section explains how to load an image from an external image format into a Java application using the Image I/O API

Drawing an image

This section teaches how to display images using the drawImage method of the Graphics and Graphics2D classes.

Creating and drawing To an image

This section describes how to create an image and how to use the image itself as a drawing surface.

Writing/saving an image

This section explains how to save created images in an appropriate format.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Reading/Loading an Image


Reading/Loading an Image (The Java™ Tutorials > 2D Graphics > Working with Images)

Trail: 2D Graphics
Lesson: Working with Images
Working with Images
Reading/Loading an Image
Drawing an Image
Creating and Drawing to an Image
Writing/Saving an Image
Home Page > 2D Graphics > Working with Images
« Previous • Trail • Next »
Reading/Loading an Image

When you think of digital images, you probably think of sampled image formats such as the JPEG image format used in digital photography, or GIF images commonly used on web pages. All programs that can use these images must first convert them from that external format into an internal format.

Java 2D™ supports loading these external image formats into its BufferedImage format using its Image I/O API which is in the javax.imageio package. Image I/O has built-in support for GIF, PNG, JPEG, BMP, and WBMP. Image I/O is also extensible so that developers or administrators can "plug-in" support for additional formats. For example, plug-ins for TIFF and JPEG 2000 are separately available.

To load an image from a specific file use the following code:

BufferedImage img = null;
try {
    img = ImageIO.read(new File("strawberry.jpg"));
} catch (IOException e) {
}

Image I/O recognises the contents of the file as a JPEG format image, and decodes it into a BufferedImage which can be directly used by Java 2D.

LoadImageApp.java shows how to display this image.

If the code is running in an applet, then its just as easy to obtain the image from the applet codebase :

         try {
             URL url = new URL(getCodeBase(), "strawberry.jpg");
             img = ImageIO.read(url);
         } catch (IOException e) {
         }

The getCodeBase method used in this example returns the URL of the directory containing this applet.

The following example shows how to use the getCodeBase method to load the strawberry.jpg file.

Note: If you don't see the applet running above, you need to install release 6 of the JDK.

LoadImageApp.java contains the complete code for this example and this applet requires the strawberry.jpg image file. In addition to reading from files or URLS, Image I/O can read from other sources, such as an InputStream.

ImageIO.read() is the most straightforward convenience API for most applications, but the javax.imageio.ImageIO provides many more static methods for more advanced usages of the Image I/O API. The collection of methods on this class represent just a subset of the rich set of APIs for discovering information about the images and for controlling the image decoding (reading) process.

We will explore some of the other capabilities of Image I/O later in the Writing/saving an image section. More information can be found in the Image I/O guide.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Working with Images
Next page: Drawing an Image


Drawing an Image (The Java™ Tutorials > 2D Graphics > Working with Images)

Trail: 2D Graphics
Lesson: Working with Images
Working with Images
Reading/Loading an Image
Drawing an Image
Creating and Drawing to an Image
Writing/Saving an Image
Home Page > 2D Graphics > Working with Images
« Previous • Trail • Next »
Drawing an Image

As you have already learned, the Graphics.drawImage method draws an image at a specific location:

boolean Graphics.drawImage(Image img,
                           int x, int y,
                           ImageObserver observer);

The x,y location specifies the position for the top-left of the image. The observer parameter notifies the application of updates to an image that is loaded asynchronously. The observer parameter is not frequently used directly and is not needed for the BufferedImage class, so it usually is null.

The described method addresses only the case where the entire image is to be drawn, mapping image pixels to user space coordinates 1:1. Sometimes applications require to draw a part of the image (a sub-image), or scale the image to cover a particular area of the drawing surface, or transform or filter the image before drawing.

The overloads of the drawImage() method perform these operations. For example, the following overload of the drawImage() method enables you to draw as much of a specified area of the specified image as is currently available, scaling it to fit inside the specified area of the destination drawable surface:

boolean Graphics.drawImage(Image img,
                           int dstx1, int dsty1, int dstx2, int dsty2,
                           int srcx1, int srcy1, int srcx2, int srcy2,
                           ImageObserver observer);

The src parameters represent the area of the image to copy and draw. The dst parameters display the area of the destination to cover by the the source area. The dstx1, dsty1 coordinates define the location to draw the image. The width and height dimensions on the destination area are calculated by the following expressions: (dstx2-dstx1), (dsty2-dsty1). If the dimensions of the source and destinations areas are different, the Java 2D™ API will scale up or scale down, as needed.

The following code example divides an image into four quadrants and randomly draws each quadrant of the source image into a different quadrant of the destination.

Note: If you don't see the applet running above, you need to install release 6 of the JDK. The complete code for this applet is in JumbledImageApplet.java. This example uses the following code to paint the jumbled duke_skateboard.jpg image. It iterates over the four sub-images of the source, drawing each in turn into a randomly selected destination quadrant.
        /* divide the image 'bi' into four rectangular areas and draw each
         * of these areas in to a different part of the image, so as to
         * jumble up the image.
         * 'cells' is an array which has been populated with values
         * which redirect drawing of one subarea to another subarea.
         */
        int cellWidth = bi.getWidth(null)/2;
        int cellHeight = bi.getHeight(null)/2;
        for (int x=0; x<2; x++) {
            int sx = x*cellWidth;
            for (int y=0; y<2; y++) {
                int sy = y*cellHeight;
                int cell = cells[x*2+y];
                int dx = (cell / 2) * cellWidth;
                int dy = (cell % 2) * cellHeight;
                g.drawImage(bi,
                            dx, dy, dx+cellWidth, dy+cellHeight,
                            sx, sy, sx+cellWidth, sy+cellHeight,
                            null);
            }
        }

Filtering Images

In addition to copying and scaling images, the Java 2D API also filter an image. Filtering is drawing or producing a new image by applying an algorithm to the pixels of the source image. Image filters can be applied by using the following method:

void Graphics2D.drawImage(BufferedImage img,
                          BufferedImageOp op,
                          int x, int y)

The BufferedImageOp parameter implements the filter. The following applet represents an image drawn on top of text. Drag the slider to show more or less of the text through the image and make the image more or less transparent.

Note: If you don't see the applet running above, you need to install release 6 of the JDK.

The following code shows how the filter action is done by operating on a BufferedImage object with an alpha channel and rescales that alpha channel by using the RescaleOp object. The alpha channel determines the translucency of each pixel. It also specifies the degree to which this image overwrites.

   /* Create an ARGB BufferedImage */
   BufferedImage img = ImageIO.read(imageSrc);
   int w = img.getWidth(null);
   int h = img.getHeight(null);
   BufferedImage bi = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
   Graphics g = bi.getGraphics();
   g.drawImage(img, 0, 0, null);

   /* Create a rescale filter op that makes the image 50% opaque */
   float[] scales = { 1f, 1f, 1f, 0.5f };
   float[] offsets = new float[4];
   RescaleOp rop = new RescaleOp(scales, offsets, null);

   /* Draw the image, applying the filter */
   g2d.drawImage(bi, rop, 0, 0);

The complete example represented in SeeThroughImageApplet.java includes the code that uses the slider to adjust the transparency from the initial 50%. This example also requires the duke_skateboard.jpg image.

The RescaleOp object is just one of many filters that can be created. The Java 2D API has several built in filters including the following:

  • ConvolveOp. Each output pixel is computed from surrounding pixels in the source image. It may be used to blur or sharpen images.
  • AffineTransformOp. This filter maps pixels in the source to a different position in the destination by applying a transformation on the pixel location.
  • LookupOp. This filter uses an application supplied lookup table to remap pixel colors.
  • RescaleOp. This filter multiplies the colors by some factor. Can be used to lighten or darken the image, to increase or reduce its opacity, etc.

The following example uses each of the described filters as well as scaling:

Note: If you don't see the applet running above, you need to install release 6 of the JDK. The complete code for this applet is in ImageDrawingApplet.java and this applet requires the bld.jpg image.

Use the drop-down menu to select an image scaling or filtering operation.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Reading/Loading an Image
Next page: Creating and Drawing to an Image


Creating and Drawing to an Image (The Java™ Tutorials > 2D Graphics > Working with Images)

Trail: 2D Graphics
Lesson: Working with Images
Working with Images
Reading/Loading an Image
Drawing an Image
Creating and Drawing to an Image
Writing/Saving an Image
Home Page > 2D Graphics > Working with Images
« Previous • Trail • Next »
Creating and Drawing to an Image

We already know how to load an existing image, which was created and stored in your system or in any network location. But, you probably would like also to create an new image as a pixel data buffer.

In this case, you can create a BufferedImage object manually, using three constructors of this class:

  • new BufferedImage(width, height, type) - constructs a BufferedImage of one of the predefined image types.
  • new BufferedImage(width, height, type, colorModel) - constructs a BufferedImage of one of the predefined image types: TYPE_BYTE_BINARY or TYPE_BYTE_INDEXED.
  • new BufferedImage(colorModel, raster, premultiplied, properties) - constructs a new BufferedImage with a specified ColorModel and Raster.

On the other hand, we can use methods of the Component class. These methods can analyze the display resolution for the given Component or GraphicsConfiguration and create an image of an appropriate type.

  • Component.createImage(width, height)
  • GraphicsConfiguration.createCompatibleImage(width, height)
  • GraphicsConfiguration.createCompatibleImage(width, height, transparency)

GraphicsConfiguration returns an object of BufferedImage type, but the Component returns an object of Image type, if you need a BufferedImage object instead then you can perform an instanceof and cast to a BufferedImage in your code.

As was already mentioned in the previous lessons, we can render images not only on screen. An images itself can be considered as a drawing surface. You can use a createGraphics() method of the BufferedImage class for this purpose:

...

BufferedImage off_Image =
    new BufferedImage(100, 50, BufferedImage.TYPE_INT_ARGB);

Graphics2D g2 = off_Image.createGraphics();

Another interesting use of offscreen images is an automatic double buffering. This feature allows to avoid flicker in animated images by drawing an image to a back buffer and then copying that buffer onto the screen instead of drawing directly to the screen.

Java 2D™ also allows access to hardware acceleration for offscreen images, which can provide the better performance of rendering to and copying from these images. You can get the benefit of this functionality by using the following methods of the Image class:

  • The getCapabilities method allows you to determine whether the image is currently accelerated.
  • The setAccelerationPriority method lets you set a hint about how important acceleration is for the image.
  • The getAccelerationPriority method gets a hint about the acceleration importance.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Drawing an Image
Next page: Writing/Saving an Image


Writing/Saving an Image (The Java™ Tutorials > 2D Graphics > Working with Images)

Trail: 2D Graphics
Lesson: Working with Images
Working with Images
Reading/Loading an Image
Drawing an Image
Creating and Drawing to an Image
Writing/Saving an Image
Home Page > 2D Graphics > Working with Images
« Previous • Trail • Next »
Writing/Saving an Image

This lesson started with an explanation for using the javax.imageio package, to load images from an external image format into Java 2D™'s internal BufferedImage format. Then it explains how to use the Graphics.drawImage() to draw that image, with optional filtering.

The final stage is saving a BufferedImage object into an external image format. This may be an image that was originally loaded by the Image I/O class from an external image format and perhaps modified using the Java 2D APIs, or it may be one that was created by Java 2D.

The Image I/O class provides a simple way to save images in a variety of image formats in the following example:

static boolean ImageIO.write(RenderedImage im,
                             String formatName,
                             File output) throws IOException
Note: the BufferedImage class implements the RenderedImage interface.
.

The formatName parameter selects the image format in which to save the BufferedImage.

    try {
        BufferedImage bi = getMyImage(); // retrieve image
        File outputfile = new File("saved.png");
        ImageIO.write(bi, "png", outputfile);
    } catch (IOException e)
    }

The ImageIO.write method calls the code that implements PNG writing a “PNG writer plug-in”. The term plug-in is used since Image I/O is extensible and can support a wide range of formats.

But the following standard image format plugins : JPEG, PNG, GIF, BMP and WBMP are always be present.

Each image format has its advantages and disadvantages:
Plus | Minus
GIF | Supports animation, and transparent pixels | Supports only 256 colors and no translucency
PNG | Better alternative than GIF or JPG for high colour lossless images, supports translucency | Doesn't support animation
JPG | Great for photographic images | Loss of compression, not good for text, screenshots, or any application where the original image must be preserved exactly

For most applications it is sufficient to use one of these standard plugins. They have the advantage of being readily available. The Image I/O class provides a way to plug in support for additional formats which can be used, and many such plug-ins exist. If you are interested in what file formats are available to load or save in your system, you may use the getReaderFormatNames and getWriterFormatNames methods of the ImageIO class. These methods return an array of strings listing all of the formats supported in this JRE.

String writerNames[] = ImageIO.getWriterFormatNames();

The returned array of names will include any additional plug-ins that are installed and any of these names may be used as a format name to select an image writer. The following code example is a simple version of a complete image edit/touch up program which uses a revised version of the ImageDrawingApplet.java sample program which can be used as follows :

  • An image is first loaded via Image I/O
  • The user selects a filter from the drop down list and a new updated image is drawn
  • The user selects a save format from the drop down list
  • Next a file chooser appears and the user selects where to save the image
  • The modified image can now be viewed by other desktop applications

The complete code of this example is represented in SaveImage.java.

In this lesson you have learned just the basics of Image I/O, which provides extensive support for writing images, including working directly with an ImageWriter plug-in to achieve finer control over the encoding process. ImageIO can write multiple images, image metadata, and determine quality vs. size tradeoffs. For more information see Java Image I/O API Guide.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating and Drawing to an Image
Next page: Printing


Lesson: Printing (The Java™ Tutorials > 2D Graphics)

Printing
A Basic Printing Program
Using Print Setup Dialogs
Printing a Multiple Page Document
Working with Print Services and Attributes
Printing the Contents of a User Interface
Printing Support in Swing Components
Trail: 2D Graphics
Home Page > 2D Graphics
« Previous • Trail • Next »
Lesson: Printing

Since the Java 2D™ API enables you to draw on any surface, a natural extension of that is the ability to print Java 2D graphics. A printer can be considered a graphics device just like a display.

The Java 2D printing API is not limited to printing graphics. It enables you to print the content of an application's user interface as well. Content can be printed by sending raw data to the printer under the formatting control of the Java 2D printing API, or by using the Java 2D Graphics API.

In this lesson you will explore the printer and job control functions of the Java 2D printing API which are complements to the rendering elements. You will learn how to look up printers configured on the system or network and discover information about these printers such as the paper sizes it supports, and selecting these attributes for printing, and user dialogs.

The main classes and interfaces involved in printing are represented in the java.awt.print and javax.print packages (the last package allows you to get access to the printing services).

The basic printing operations are represented in the following sections:

A Basic Printing Program

This section describes the Printable interface and presents a basic printing program.

Using Print Setup Dialogs

This sections explains how to display the Print Setup Dialog.

Printing a Multiple Page Document

This section explains how to use pagination for printing a multiple page document.

Working with Print Services and Attributes

This section teaches you about print services, how to specify the print data format, and how to create print job using the javax.print package.

Printing the Contents of a User Interface

This section explains how to print the contents of a window or a frame.

Printing Support in Swing Components

This section provides a brief description of the related printing functionality in Swing and refers to specific Swing classes and interfaces.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: A Basic Printing Program


A Basic Printing Program (The Java™ Tutorials > 2D Graphics > Printing)

Trail: 2D Graphics
Lesson: Printing
Printing
A Basic Printing Program
Using Print Setup Dialogs
Printing a Multiple Page Document
Working with Print Services and Attributes
Printing the Contents of a User Interface
Printing Support in Swing Components
Home Page > 2D Graphics > Printing
« Previous • Trail • Next »
A Basic Printing Program

This section explains how to create a basic printing program that displays a print dialog and prints the text "Hello World" to the selected printer.

Printing task usually consists of two parts:

  • Job control — Creating a print job, associating it with a printer, specifying the number of copies, and user print dialog interaction.
  • Page Imaging — Drawing content to a page, and managing content that spans pages (pagination).

First create the printer job. The class representing a printer job and most other related classes is located in the java.awt.print package.

import java.awt.print.*;

PrinterJob job = PrinterJob.getPrinterJob();

Next provide code that renders the content to the page by implementing the Printable interface.

class HelloWorldPrinter implements Printable  { ... }
..
job.setPrintable(new HelloWorldPrinter());

An application typically displays a print dialog so that the user can adjust various options such as number of copies, page orientation, or the destination printer.

boolean doPrint = job.printDialog();

This dialog appears until the user either approves or cancels printing. The doPrint variable will be true if the user gave a command to go ahead and print. If the doPrint variable is false, the user cancelled the print job. Since displaying the dialog at all is optional, the returned value is purely informational.

If the doPrint variable is true, then the application will request that the job be printed by calling the PrinterJob.print method.

if (doPrint) {
  try {
       job.print();
  } catch (PrinterException e) {
   /* The job did not successfully complete */
  }
}

The PrinterException will be thrown if there is problem sending the job to the printer. However, since the PrinterJob.print method returns as soon as the job is sent to the printer, the user application cannot detect paper jams or paper out problems. This job control boilerplate is sufficient for basic printing uses.

The Printable interface has only one method:

public int print(Graphics graphics, PageFormat pf, int page)
            throws PrinterException;

The PageFormat class describes the page orientation (portrait or landscape) and its size and imageable area in units of 1/72nd of an inch. Imageable area accounts for the margin limits of most printers (hardware margin). The imageable area is the space inside these margins, and in practice if is often further limited to leave space for headers or footers.

A page parameter is the zero-based page number that will be rendered.

The following code represents the full Printable implementation:

import java.awt.print.*;
import java.awt.*;

public class HelloWorldPrinter implements Printable {

  public int print(Graphics g, PageFormat pf, int page) throws
                                                        PrinterException {

    if (page > 0) { /* We have only one page, and 'page' is zero-based */
         return NO_SUCH_PAGE;
    }

    /* User (0,0) is typically outside the imageable area, so we must
     * translate by the X and Y values in the PageFormat to avoid clipping
     */
    Graphics2D g2d = (Graphics2D)g;
    g2d.translate(pf.getImageableX(), pf.getImageableY());

    /* Now we perform our rendering */
    g.drawString("Hello world!", 100, 100);

    /* tell the caller that this page is part of the printed document */
    return PAGE_EXISTS;
  }
}
The complete code for this example is in HelloWorldPrinter.java.

Sending a Graphics instance to the printer is essentially the same as rendering it to the screen. In both cases you need to perform the following steps:

  • To draw a test string is as easy as the other operations that were described for drawing to a Graphics2D.
  • Printer graphics have a higher resolution, which should be transparent to most code.
  • The Printable.print() method is called by the printing system, just as the Component.paint() method is called to paint a Component on the display. The printing system will call the Printable.print() method for page 0, 1,.. etc until the print() method returns NO_SUCH_PAGE.
  • The print() method may be called with the same page index multiple times until the document is completed. This feature is applied when the user specifies attributes such as multiple copies with collate option.
  • The PageFormat's imageable area determines the clip area. Imageable area is also important in calculating pagination, or how to span content across printed pages, since page breaks are determined by how much can fit on each page.
    Note: A call to the print() method may be skipped for certain page indices if the user has specified a different page range that does not involve a particular page index.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Printing
Next page: Using Print Setup Dialogs


Using Print Setup Dialogs (The Java™ Tutorials > 2D Graphics > Printing)

Trail: 2D Graphics
Lesson: Printing
Printing
A Basic Printing Program
Using Print Setup Dialogs
Printing a Multiple Page Document
Working with Print Services and Attributes
Printing the Contents of a User Interface
Printing Support in Swing Components
Home Page > 2D Graphics > Printing
« Previous • Trail • Next »
Using Print Setup Dialogs

Traditionally, the user wants to see the page setup and print dialog boxes. From the print dialog you can select a printer, specify pages to print, and set the number of copies.

This figures represents a print dialog

An application displays a print dialog when the user presses a button related to the print command, or chooses an item from the print menu. To display this dialog, call the printDialog method of the PrinterJob class:

 PrinterJob pj = PrinterJob.getPrinterJob();
 ...
     if (pj.printDialog()) {
         try {pj.print();}
     catch (PrinterException exc) {
       System.out.println(exc);
      }
      }
  ...

This method returns true if the user clicked OK to leave the dialog, and false otherwise. The user's choices in the dialog are constrained based on the number and format of the pages that have been set to the PrinterJob.

The printDialog method in the above code snippet opens a native print dialog. The PrintDialogExample.java code example shows how to display a cross-platform print dialog.

You can change the page setup information contained in the PageFormat object by using the page setup dialog.

This figure represents a page setup dialod window

To display the page setup dialog, call the pageDialog method of the PrinterJob class.
   PrinterJob pj = PrinterJob.getPrinterJob();
   PageFormat pf = pj.pageDialog(pj.defaultPage());

The page setup dialog is initialized using the parameter passed to pageDialog. If the user clicks the OK button in the dialog, the PageFormat instance will be created in accordance with the user’s selections, and then returned. If the user cancels the dialog, pageDialog returns the original unchanged PageFormat.

Usually the Java 2D™ Printing API requires an application to display a print dialog, but in sometimes it's possible to print without showing any dialog at all. This type of printing is called silent printing. It may be useful in specific cases, such as, when you need to print a particular database weekly report. In the other cases it is always recommended to inform the user when a print process is starting.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: A Basic Printing Program
Next page: Printing a Multiple Page Document


Printing a Multiple Page Document (The Java™ Tutorials > 2D Graphics > Printing)

Trail: 2D Graphics
Lesson: Printing
Printing
A Basic Printing Program
Using Print Setup Dialogs
Printing a Multiple Page Document
Working with Print Services and Attributes
Printing the Contents of a User Interface
Printing Support in Swing Components
Home Page > 2D Graphics > Printing
« Previous • Trail • Next »
Printing a Multiple Page Document

You have already learned how to use the Printable interface to print a single page document. However, documents are usually more than one physical page in length. Pagination is the process of identifying the location in a document where page breaks and printing accordingly.

In case of printing several graphics images, one per page, use the page index to iterate through these pages and print one on each page. For example, if several images are represented in the following array:

BufferedImage[] images = new BufferedImage[10];
then use the print() method as shown in the following code fragment:
public int print(Graphics graphics, PageFormat pageFormat, int pageIndex)
            throws PrinterException {

    if (pageIndex < images.length) {
        graphics.drawImage(images[pageIndex], 100, 100, null);
        return PAGE_EXISTS;
    } else {
        return NO_SUCH_PAGE:
    }
}
If the document is continuous, the application must calculate how much content can fit on each page, and break the page at that point. If text document consists of many lines, then an application must calculate how many of these lines can fit entirely on a page. The Point class creates a point representing a location in (x,y)

To calculate the height of a single line of text, use the FontMetrics class.

Font font = new Font("Serif", Font.PLAIN, 10);
FontMetrics metrics = graphics.getFontMetrics(font);
int lineHeight = metrics.getHeight();

The PageFormat parameter describes the printable area of the page. In particular, to find the vertical span of the page use the following code fragment:

double pageHeight = pageFormat.getImageableHeight();
Use the following code fragment to calculate the number of lines that fit on a page and the number of page breaks:
int linesPerPage = ((int)pageHeight)/lineHeight);
int numBreaks = (textLines.length-1)/linesPerPage;
int[] pageBreaks = new int[numBreaks];
for (int b=0; b < numBreaks; b++) {
    pageBreaks[b] = (b+1)*linesPerPage;
}

Use the print() method to calculate the printable area for the following reasons:

  • Text measurement depends on the FontRenderContext and this is implicit in the FontMetrics object returned by the printer graphics which is not available except inside the print() method.
  • The page format may not be disclosured until printing occurs. Since if the user selected a landscape mode in the print dialog, then this setting needs to be accounted for. The PageFormat object passed into the print() method provides this information.
The page break positions are used as represented in the following code fragment:
/* Draw each line that is on this page.
 * Increment 'y' position by lineHeight for each line.
 */
int y = 0;
int start = (pageIndex == 0) ? 0 : pageBreaks[pageIndex-1];
int end   = (pageIndex == pageBreaks.length)
                 ? textLines.length : pageBreaks[pageIndex];
for (int line=start; line<end; line++) {
    y += lineHeight;
    g.drawString(textLines[line], 0, y);
}
If a document contains 100 lines and only 48 lines fit on a page, then an application prints 3 pages with page breaks after 48 and 96 lines of text. The remaining 4 lines are printed on the last page. The complete code for this example is in PaginationExample.java.

The following simplifying factors are used in the PaginationExample code:

  • Each page has the same height.
  • The same font is used.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Print Setup Dialogs
Next page: Working with Print Services and Attributes


Working with Print Services and Attributes (The Java™ Tutorials > 2D Graphics > Printing)

Trail: 2D Graphics
Lesson: Printing
Printing
A Basic Printing Program
Using Print Setup Dialogs
Printing a Multiple Page Document
Working with Print Services and Attributes
Printing the Contents of a User Interface
Printing Support in Swing Components
Home Page > 2D Graphics > Printing
« Previous • Trail • Next »
Working with Print Services and Attributes

From the previous lessons you have learned that the Java 2D ™ printing API supports page imaging, displays print and page setup dialogs, and specifies printing attributes. Printing services is another key component of any printing subsystem.

The Java™ Print Service (JPS) API extends the current Java 2D printing features to offer the following functionality:

  • Application discovers printers that cater to its needs by dynamically querying the printer capabilities.
  • Application extends the attributes included with the JPS API.
  • Third parties can plug in their own print services with the Service Provider Interface, which print different formats, including Postscript, PDF, and SVG.

The Java Print Service API consists of four packages:

This figure represents four packages necessary for printing

The javax.print package provides the principal classes and interfaces for the Java™ Print Service API. It enables client and server applications to:

  • Discover and select print services based on their capabilities.
  • Specify the format of print data.
  • Submit print jobs to services that support the document type to be printed.

Document Type Specification

The DocFlavor class represents format of the print data, such as JPEG or PostScript. The DocFlavor format consists of two parts: a MIME type and a representation class name. A MIME type describes the format, and a document representation class name indicates how the document is delivered to the printer or output stream. An application uses the DocFlavor and an attribute set to find printers with the capabilities specified by the attribute set. This code sample demonstrates obtaining an array of StreamPrintServiceFactory objects that can return StreamPrintService objects able to convert a GIF image into PostScript:

    DocFlavor flavor = DocFlavor.INPUT_STREAM.GIF;
    String psMimeType = DocFlavor.BYTE_ARRAY.POSTSCRIPT.getMimeType();
    StreamPrintServiceFactory[] psfactories =
        StreamPrintServiceFactory.lookupStreamPrintServiceFactories(
            flavor, psMimeType);

Attribute Definitions

The javax.print.attribute and javax.print.attribute.standard packages define print attributes which describe the capabilities of a print service, specify the requirements of a print job, and track the progress of the print job.

For example, if you would like to use A4 paper format and print three copies of your document you will have to create a set of the following attributes implementing the PrintRequestAttributeSet interface:

    PrintRequestAttributeSet attr_set = new HashPrintRequestAttributeSet();
    attr_set.add(MediaSize.ISO_A4);
    attr_set.add(new Copies(3));

Then you must pass the attribute set to the print job's print method, along with the DocFlavor.

Print Service Discovery

An application invokes the static methods of the abstract class PrintServiceLookup to locate print services that have the capabilities to satisfy the application's print request. For example, in order to print two copies of a double-sided document, the application first needs to find printers that have double-sided printing capability:

   DocFlavor doc_flavor = DocFlavor.INPUT_STREAM.PDF;
   PrintRequestAttributeSet attr_set = new HashPrintRequestAttributeSet();
   attr_set.add(new Copies(2));
   attr_set.add(Sides.DUPLEX);
   PrintService[] service = PrintServiceLookup.lookupPrintServices(doc_flavor, attr_set);

Common Use of the API

In conclusion, the Java Print Service API performs the following steps to process a print request:

  1. Chooses a DocFlavor.
  2. Creates a set of attributes.
  3. Locates a print service that can handle the print request as specified by the DocFlavor and the attribute set.
  4. Creates a Doc object encapsulating the DocFlavor and the actual print data.
  5. Gets a print job, represented by DocPrintJob, from the print service.
  6. Calls the print method of the print job.

For more information about Java Print Service, see Java 2D™ Print Service API User Guide.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Printing a Multiple Page Document
Next page: Printing the Contents of a User Interface


Printing the Contents of a User Interface (The Java™ Tutorials > 2D Graphics > Printing)

Trail: 2D Graphics
Lesson: Printing
Printing
A Basic Printing Program
Using Print Setup Dialogs
Printing a Multiple Page Document
Working with Print Services and Attributes
Printing the Contents of a User Interface
Printing Support in Swing Components
Home Page > 2D Graphics > Printing
« Previous • Trail • Next »
Printing the Contents of a User Interface

Another common printing task is to print the contents of a window or a frame, either in whole, or in part. The window may contain the following components: toolbars, buttons sliders, text labels, scrollable text areas, images, and other graphical content. All of these components are printed using the following methods of the Java 2D™ printing API:

java.awt.Component.print(Graphics g);
java.awt.Component.printAll(Graphics g);

The following figure represents a simple user interface.

Printing 12 lines in the window

The code to create this UI is located in the sample program PrintUIWindow.java.

To print this window, modify the code in the earlier examples which printed text or images. The resulting code should appear as follows:

   public int print(Graphics g, PageFormat pf, int page) throws
                                                    PrinterException {
        if (page > 0) {
            return NO_SUCH_PAGE;
        }

        Graphics2D g2d = (Graphics2D)g;
        g2d.translate(pf.getImageableX(), pf.getImageableY());

        /* Print the entire visible contents of a java.awt.Frame */
        frame.printAll(g);

        return PAGE_EXISTS;
    }

Note: The call to the printAll method is the only difference between
this example and examples to print text or image.
The print(Graphics g) method mirrors the java.awt.Component.paint(Graphics g) method used
for on-screen rendering. Use the print() method rather
than the paint() method as the Components class may have overridden the
print() method to handle the printing case differently.

The printAll(Graphics g)method prints the component and
all its subcomponents. This method is usually used to print
object such as a complete window, rather than a single component.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Working with Print Services and Attributes
Next page: Printing Support in Swing Components


Printing Support in Swing Components (The Java™ Tutorials > 2D Graphics > Printing)

Trail: 2D Graphics
Lesson: Printing
Printing
A Basic Printing Program
Using Print Setup Dialogs
Printing a Multiple Page Document
Working with Print Services and Attributes
Printing the Contents of a User Interface
Printing Support in Swing Components
Home Page > 2D Graphics > Printing
« Previous • Trail • Next »
Printing Support in Swing Components

The PrintUIWindow.java example represented in the previous section demonstrates that the printout is exactly the same you saw on the screen. This appearance seems reasonable. However, if a window is scrollable, then the contents that are currently scrolled out of view are not included in the printout. This creates a dump effect on the printer. This becomes a particular problem when printing large components such as a Swing table or text components. Components may contain many lines of text which cannot all be entirely visible on the screen. In this case, print the contents displayed by the component in a manner consistent with the screen display.

To solve this problem, the Swing table and all text components are printing aware. The following methods directly provide the use of the Java 2D™ printing:

  • javax.swing.JTable.print();
  • javax.swing.text.JTextComponent.print();

These methods provide a full implementation of printing for their contents. An application doesn't need directly create a PrinterJob object and implement the Printable interface. The call of these methods displays a print dialog and prints the component's data in accordance with the user's selections. There are also additional methods which provide more options.

For more information see related articles at java.sun.com.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Printing the Contents of a User Interface
Next page: Advanced Topics in Java2D


Lesson: Advanced Topics in Java2D (The Java™ Tutorials > 2D Graphics)

Advanced Topics in Java2D
Transforming Shapes, Text, and Images
Clipping the Drawing Region
Compositing Graphics
Controlling Rendering Quality
Constructing Complex Shapes from Geometry Primitives
Supporting User Interaction
Trail: 2D Graphics
Home Page > 2D Graphics
« Previous • Trail • Next »
Lesson: Advanced Topics in Java2D
This lesson shows you how to use Graphics2D to display graphics with fancy outline and fill styles, transform graphics when they are rendered, constrain rendering to a particular area, and generally control the way graphics look when they are rendered. You'll also learn how to create complex Shape objects by combining simple ones and how to detect when the user clicks on a displayed graphics primitive. These topics are discussed in the following sections:

Transforming Shapes, Text, and Images

This section shows you how to modify the default transformation so that objects are translated, rotated, scaled, or sheared when they are rendered.

Clipping the Drawing Region

You can use any shape as a clipping path--the area within which rendering takes place.

Compositing Graphics

This section illustrates the various compositing styles supported by AlphaComposite and shows you how to set the compositing style in the Graphics2D rendering context.

Controlling Rendering Quality

This section describes the rendering hints that Graphics2D supports and shows you how to specify your preference in the trade-off between rendering quality and speed.

Constructing Complex Shapes from Geometry Primitives

This section shows you how to perform boolean operations on Shape objects using the Area class.

Supporting User Interaction

This section shows you how to perform hit detection on graphics primitives.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Transforming Shapes, Text, and Images


Transforming Shapes, Text, and Images (The Java™ Tutorials > 2D Graphics > Advanced Topics in Java2D)

Trail: 2D Graphics
Lesson: Advanced Topics in Java2D
Advanced Topics in Java2D
Transforming Shapes, Text, and Images
Clipping the Drawing Region
Compositing Graphics
Controlling Rendering Quality
Constructing Complex Shapes from Geometry Primitives
Supporting User Interaction
Home Page > 2D Graphics > Advanced Topics in Java2D
« Previous • Trail • Next »
Transforming Shapes, Text, and Images
You can modify the transform attribute in the Graphics2D context to move, rotate, scale, and shear graphics primitives when they are rendered. The transform attribute is defined by an instance of the AffineTransform class. An affine transform is a transformation such as translate, rotate, scale, or shear in which parallel lines remain parallel even after being transformed.

The Graphics2D class provides several methods for changing the transform attribute. You can construct a new AffineTransform and change the Graphics2D transform attribute by calling transform.

AffineTransform defines the following factory methods to make it easier to construct new transforms:

  • getRotateInstance
  • getScaleInstance
  • getShearInstance
  • getTranslateInstance

Alternatively you can use one of the Graphics2D transformation methods to modify the current transform. When you call one of these convenience methods, the resulting transform is concatenated with the current transform and is applied during rendering:

  • rotate--to specify an angle of rotation in radians
  • scale--to specify a scaling factor in the x and y directions
  • shear--to specify a shearing factor in the x and y directions
  • translate--to specify a translation offset in the x and y directions

You can also construct an AffineTransform object directly and concatenate it with the current transform by calling the transform method.

The drawImage method is also overloaded to allow you to specify an AffineTransform that is applied to the image as it is rendered. Specifying a transform when you call drawImage does not affect the Graphics2D transform attribute.

Example: Transform

The following program is the same as StrokeandFill, but also allows the user to choose a transformation to apply to the selected object when it is rendered.

Note: If you don't see the applet running above, you need to install release 6 of the JDK.

Transform.java contains the complete code for this applet.

When a transform is chosen from the Transform menu, the transform is concatenated onto the AffineTransform at:

public void setTrans(int transIndex) {
    // Sets the AffineTransform.
    switch ( transIndex ) {
    case 0 : at.setToIdentity();
             at.translate(w/2, h/2); break;
    case 1 : at.rotate(Math.toRadians(45)); break;
    case 2 : at.scale(0.5, 0.5); break;
    case 3 : at.shear(0.5, 0.0); break;
    }
}
Before displaying the shape corresponding to the menu choices, the application first retrieves the current transform from the Graphics2D object:
AffineTransform saveXform = g2.getTransform();
This transform will be restored to the Graphics2D after rendering.

After retrieving the current transform, another AffineTransform, toCenterAt, is created that causes shapes to be rendered in the center of the panel. The at AffineTransform is concatenated onto toCenterAt:

AffineTransform toCenterAt = new AffineTransform();
toCenterAt.concatenate(at);
toCenterAt.translate(-(r.width/2), -(r.height/2));
The toCenterAt transform is concatenated onto the Graphics2D transform with the transform method:
g2.transform(toCenterAt);
After rendering is completed, the original transform is restored using the setTransform method:
g2.setTransform(saveXform);
Note: Never use the setTransform method to concatenate a coordinate transform onto an existing transform. The setTransform method overwrites the Graphics2D object's current transform, which might be needed for other reasons, such as positioning Swing and lightweight components in a window. Use these steps to perform transformations:
  1. Use the getTransform method to get the current transform.
  2. Use transform, translate, scale, shear, or rotate to concatenate a transform.
  3. Perform the rendering.
  4. Restore the original transform using the setTransform method.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Advanced Topics in Java2D
Next page: Clipping the Drawing Region


Clipping the Drawing Region (The Java™ Tutorials > 2D Graphics > Advanced Topics in Java2D)

Trail: 2D Graphics
Lesson: Advanced Topics in Java2D
Advanced Topics in Java2D
Transforming Shapes, Text, and Images
Clipping the Drawing Region
Compositing Graphics
Controlling Rendering Quality
Constructing Complex Shapes from Geometry Primitives
Supporting User Interaction
Home Page > 2D Graphics > Advanced Topics in Java2D
« Previous • Trail • Next »
Clipping the Drawing Region
Any Shape object can be used as a clipping path that restricts the portion of the drawing area that will be rendered. The clipping path is part of the Graphics2D context; to set the clip attribute, you call Graphics2D.setClip and pass in the Shape that defines the clipping path you want to use. You can shrink the clipping path by calling the clip method and passing in another Shape; the clip is set to the intersection of the current clip and the specified Shape.

Example: ClipImage

This example animates a clipping path to reveal different portions of an image.

Note: If you don't see the applet running above, you need to install release 6 of the JDK.

ClipImage.java contains the complete code for this applet. The applet requires the clouds.jpg image file.

The clipping path is defined by the intersection of an ellipse and a rectangle whose dimensions are set randomly. The ellipse is passed to the setClip method, and then clip is called to set the clipping path to the intersection of the ellipse and the rectangle.

private Ellipse2D ellipse = new Ellipse2D.Float();
private Rectangle2D rect = new Rectangle2D.Float();
...
ellipse.setFrame(x, y, ew, eh);
g2.setClip(ellipse);
rect.setRect(x+5, y+5, ew-10, eh-10);
g2.clip(rect);

Example: Starry

A clipping area can also be created from a text string. The following example creates a TextLayout with the string The Starry Night. Then, it gets the outline of the TextLayout. The TextLayout.getOutline method returns a Shape object and a Rectangle is created from the bounds of this Shape object. The bounds contain all the pixels the layout can draw. The color in the graphics context is set to blue and the outline shape is drawn, as illustrated by the following image and code snippet.

FontRenderContext frc = g2.getFontRenderContext();
Font f = new Font("Helvetica", 1, w/10);
String s = new String("The Starry Night");
TextLayout textTl = new TextLayout(s, f, frc);
AffineTransform transform = new AffineTransform();
Shape outline = textTl.getOutline(null);
Rectangle r = outline.getBounds();
transform = g2.getTransform();
transform.translate(w/2-(r.width/2), h/2+(r.height/2));
g2.transform(transform);
g2.setColor(Color.blue);
g2.draw(outline);

Next, a clipping area is set on the graphics context using the Shape object created from getOutline. The starry.gif image, which is Van Gogh's famous painting, The Starry Night, is drawn into this clipping area starting at the lower left corner of the Rectangle object.

g2.setClip(outline);
g2.drawImage(img, r.x, r.y, r.width, r.height, this);
Note: If you don't see the applet running above, you need to install release 6 of the JDK.

Starry.java contains the complete code for this program. This applet requires the Starry.gif image file.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Transforming Shapes, Text, and Images
Next page: Compositing Graphics


Compositing Graphics (The Java™ Tutorials > 2D Graphics > Advanced Topics in Java2D)

Trail: 2D Graphics
Lesson: Advanced Topics in Java2D
Advanced Topics in Java2D
Transforming Shapes, Text, and Images
Clipping the Drawing Region
Compositing Graphics
Controlling Rendering Quality
Constructing Complex Shapes from Geometry Primitives
Supporting User Interaction
Home Page > 2D Graphics > Advanced Topics in Java2D
« Previous • Trail • Next »
Compositing Graphics
The AlphaComposite class encapsulates various compositing styles, which determine how overlapping objects are rendered. An AlphaComposite can also have an alpha value that specifies the degree of transparency: alpha = 1.0 is totally opaque, alpha = 0.0 totally transparent (clear). AlphaComposite supports most of the standard Porter-Duff compositing rules shown in the following table.

Source-over (SRC_OVER)
 If pixels in the object being rendered (the source) have the same location as previously rendered pixels (the destination), the source pixels are rendered over the destination pixels.
Source-in (SRC_IN)
 If pixels in the source and the destination overlap, only the source pixels in the overlapping area are rendered.
Source-out (SRC_OUT)
 If pixels in the source and the destination overlap, only the source pixels outside of the overlapping area are rendered. The pixels in the overlapping area are cleared.
Destination-over (DST_OVER)
 If pixels in the source and the destination overlap, only the source pixels outside of the overlapping area are rendered. The pixels in the overlapping area are not changed.
Destination-in (DST_IN)
 If pixels in the source and the destination overlap, the alpha from the source is applied to the destination pixels in the overlapping area. If the alpha = 1.0, the pixels in the overlapping area are unchanged; if the alpha is 0.0, pixels in the overlapping area are cleared.
Destination-out (DST_OUT)
 If pixels in the source and the destination overlap, the alpha from the source is applied to the destination pixels in the overlapping area. If the alpha = 1.0, the pixels in the overlapping area are cleared; if the alpha is 0.0, the pixels in the overlapping area are unchanged.
Clear (CLEAR)
 If the pixels in the source and the destination overlap, the pixels in the overlapping area are cleared.

To change the compositing style used by the Graphics2D class, create an AlphaComposite object and pass it into the setComposite method.

Example: Composite

This program illustrates the effects of various compositing style and alpha combinations.

Note: If you don't see the applet running above, you need to install release 6 of the JDK.

Composite.java. contains the full code for this applet.

A new AlphaComposite object ac is constructed by calling AlphaComposite.getInstance and specifying the desired compositing rule.

AlphaComposite ac =
               AlphaComposite.getInstance(AlphaComposite.SRC);

When a different compositing rule or alpha value is selected, AlphaComposite.getInstance is called again, and the new AlphaComposite is assigned to ac. The selected alpha is applied in addition to the per-pixel alpha value and is passed as a second parameter to AlphaComposite.getInstance.

ac = AlphaComposite.getInstance(getRule(rule), alpha);

The composite attribute is modified by passing the AlphaComposite object to Graphics 2D setComposite. The objects are rendered into a BufferedImage and are later copied to the screen, so the composite attribute is set on the Graphics2D context for the BufferedImage:

BufferedImage buffImg = new BufferedImage(w, h,
                            BufferedImage.TYPE_INT_ARGB);
Graphics2D gbi = buffImg.createGraphics();
...
gbi.setComposite(ac);
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Clipping the Drawing Region
Next page: Controlling Rendering Quality


Controlling Rendering Quality (The Java™ Tutorials > 2D Graphics > Advanced Topics in Java2D)

Trail: 2D Graphics
Lesson: Advanced Topics in Java2D
Advanced Topics in Java2D
Transforming Shapes, Text, and Images
Clipping the Drawing Region
Compositing Graphics
Controlling Rendering Quality
Constructing Complex Shapes from Geometry Primitives
Supporting User Interaction
Home Page > 2D Graphics > Advanced Topics in Java2D
« Previous • Trail • Next »
Controlling Rendering Quality

Use the Graphics2D class rendering hints attribute to specify whether you want objects to be rendered as quickly as possible or whether you prefer that the rendering quality be as high as possible.

To set or change the rendering hints attribute in the Graphics2D context, construct a RenderingHints object and pass it into Graphics2D by using the setRenderingHints method. If you just want to set one hint, you can call Graphics2D setRenderingHint and specify the key-value pair for the hint you want to set. (The key-value pairs are defined in the RenderingHints class.)

For example, to set a preference for antialiasing to be used if possible, you could use setRenderingHint:

   public void paint (graphics g){
       Graphics2D g2 = (Graphics2D)g;
    RenderingHints rh = new RenderingHints(
        RenderingHints.KEY_TEXT_ANTIALIASING,
        RenderingHints.VALUE_TEXT_ANTIALIAS_ON);
    g2.setRenderingHints(rh);
   ...
   }
Note: Not all platforms support modification of the rendering mode, so specifying rendering hints does not guarantee that they will be used.

RenderingHints supports the following types of hints:
Hint | Key | Values
Antialiasing KEY_ANTIALIASING VALUE_ANTIALIAS_ON
VALUE_ANTIALIAS_OFF
VALUE_ANTIALIAS_DEFAULT
Alpha Interpolation KEY_ALPHA_INTERPOLATION VALUE_ALPHA_INTERPOLATION_QUALITY
VALUE_ALPHA_INTERPOLATION_SPEED
VALUE_ALPHA_INTERPOLATION_DEFAULT
Color Rendering KEY_COLOR_RENDERING VALUE_COLOR_RENDER_QUALITY
VALUE_COLOR_RENDER_SPEED
VALUE_COLOR_RENDER_DEFAULT
Dithering KEY_DITHERING VALUE_DITHER_DISABLE
VALUE_DITHER_ENABLE
VALUE_DITHER_DEFAULT
Fractional Text Metrics KEY_FRACTIONALMETRICS VALUE_FRACTIONALMETRICS_ON
VALUE_FRACTIONALMETRICS_OFF
VALUE_FRACTIONALMETRICS_DEFAULT
Image Interpolation KEY_INTERPOLATION VALUE_INTERPOLATION_BICUBIC
VALUE_INTERPOLATION_BILINEAR
VALUE_INTERPOLATION_NEAREST_NEIGHBOR
Rendering KEY_RENDERING VALUE_RENDER_QUALITY
VALUE_RENDER_SPEED
VALUE_RENDER_DEFAULT
Stroke Normalization Control KEY_STROKE_CONTROL VALUE_STROKE_NORMALIZE
VALUE_STROKE_DEFAULT
VALUE_STROKE_PURE
Stroke Normalization Control KEY_STROKE_CONTROL VALUE_STROKE_NORMALIZE
VALUE_STROKE_DEFAULT
VALUE_STROKE_PURE
Text Antialiasing KEY_TEXT_ANTIALIASING VALUE_TEXT_ANTIALIAS_ON
VALUE_TEXT_ANTIALIAS_OFF
VALUE_TEXT_ANTIALIAS_DEFAULT
VALUE_TEXT_ANTIALIAS_GASP
VALUE_TEXT_ANTIALIAS_LCD_HRGB
VALUE_TEXT_ANTIALIAS_LCD_HBGR
VALUE_TEXT_ANTIALIAS_LCD_VRGB
VALUE_TEXT_ANTIALIAS_LCD_VBGR
LCD Text Contrast | KEY_TEXT_LCD_CONTRAST | Values should be a positive integer in the range 100 to 250. A lower value (eg 100) corresponds to higher contrast text when displaying dark text on a light background. A higher value (eg 200) corresponds to lower contrast text when displaying dark text on a light background. A typical useful value is in the narrow range 140-180. If no value is specified, a system or implementation default value will be applied.

When a hint is set to default, the platform rendering default is used.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Compositing Graphics
Next page: Constructing Complex Shapes from Geometry Primitives


Constructing Complex Shapes from Geometry Primitives (The Java™ Tutorials > 2D Graphics > Advanced Topics in Java2D)

Trail: 2D Graphics
Lesson: Advanced Topics in Java2D
Advanced Topics in Java2D
Transforming Shapes, Text, and Images
Clipping the Drawing Region
Compositing Graphics
Controlling Rendering Quality
Constructing Complex Shapes from Geometry Primitives
Supporting User Interaction
Home Page > 2D Graphics > Advanced Topics in Java2D
« Previous • Trail • Next »
Constructing Complex Shapes from Geometry Primitives
Constructive area geometry (CAG) is the process of creating new geometric shapes by performing boolean operations on existing ones. In the Java 2D™ API the Area class implements the Shape interface and supports the following boolean operations.

Union | Subtraction
Intersection | Exclusive-or (XOR)

Example: Areas

In this example Area objects construct a pear shape from several ellipses.

Note: If you don't see the applet running above, you need to install release 6 of the JDK.

Pear.java contains the complete code for this applet.

The leaves are each created by performing an intersection on two overlapping circles.

leaf = new Ellipse2D.Double();
...
leaf1 = new Area(leaf);
leaf2 = new Area(leaf);
...
leaf.setFrame(ew-16, eh-29, 15.0, 15.0);
leaf1 = new Area(leaf);
leaf.setFrame(ew-14, eh-47, 30.0, 30.0);
leaf2 = new Area(leaf);
leaf1.intersect(leaf2);
g2.fill(leaf1);
...
leaf.setFrame(ew+1, eh-29, 15.0, 15.0);
leaf1 = new Area(leaf);
leaf2.intersect(leaf1);
g2.fill(leaf2);

Overlapping circles are also used to construct the stem through a subtraction operation.

stem = new Ellipse2D.Double();
...
stem.setFrame(ew, eh-42, 40.0, 40.0);
st1 = new Area(stem);
stem.setFrame(ew+3, eh-47, 50.0, 50.0);
st2 = new Area(stem);
st1.subtract(st2);
g2.fill(st1);

The body of the pear is constructed by performing a union operation on a circle and an oval.

circle = new Ellipse2D.Double();
oval = new Ellipse2D.Double();
circ = new Area(circle);
ov = new Area(oval);
...
circle.setFrame(ew-25, eh, 50.0, 50.0);
oval.setFrame(ew-19, eh-20, 40.0, 70.0);
circ = new Area(circle);
ov = new Area(oval);
circ.add(ov);
g2.fill(circ);
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Controlling Rendering Quality
Next page: Supporting User Interaction


Supporting User Interaction (The Java™ Tutorials > 2D Graphics > Advanced Topics in Java2D)

Trail: 2D Graphics
Lesson: Advanced Topics in Java2D
Advanced Topics in Java2D
Transforming Shapes, Text, and Images
Clipping the Drawing Region
Compositing Graphics
Controlling Rendering Quality
Constructing Complex Shapes from Geometry Primitives
Supporting User Interaction
Home Page > 2D Graphics > Advanced Topics in Java2D
« Previous • Trail • Next »
Supporting User Interaction
To enable the user to interact with the graphics you display, you need to be able to determine when the user clicks on one of them. The hit method of the Graphics2D class provides a way to easily determine whether a mouse click occurred over a particular Shape object. Alternatively you can get the location of the mouse click and call contains on the Shape to determine whether the click was within the bounds of the Shape.

If you are using primitive text, you can perform simple hit testing by getting the outline Shape that corresponds to the text and then calling hit or contains with that Shape. Supporting text editing requires much more sophisticated hit testing. If you want to allow the user to edit text, you should generally use one of the Swing editable text components. If you are working with primitive text and are using the TextLayout class to manage the shaping and positioning of the text, you can also use TextLayout to perform hit testing for text editing. For more information see the chapter Text and Fonts in the Java 2D™ Programmer's Guide or see the HitTestSample example below, which uses a TextLayout to perform simple hit-testing.

Example: ShapeMover

This applet allows the user to drag a Shape around within the applet window. The Shape is redrawn at every mouse location to provide feedback as the user drags it.

Note: If you don't see the applet running above, you need to install release 6 of the JDK.

ShapeMover.java contains the complete code for this applet.

The contains method is called to determine whether the cursor is within the bounds of the rectangle when the mouse is pressed. If it is, the location of the rectangle is updated.

public void mousePressed(MouseEvent e){
    last_x = rect.x - e.getX();
    last_y = rect.y - e.getY();
    if(rect.contains(e.getX(), e.getY())) updateLocation(e);
...

public void updateLocation(MouseEvent e){
    rect.setLocation(last_x + e.getX(), last_y + e.getY());
    ...
    repaint();

You might notice that redrawing the Shape at every mouse location is slow, because the filled rectangle is rerendered every time it is moved. Using double buffering can eliminate this problem. If you use Swing, the drawing will be double buffered automatically; you don't have to change the rendering code at all. The code for a Swing version of this program is SwingShapeMover.java.

Example: HitTestSample

This application illustrates hit testing by drawing the default caret wherever the user clicks on the TextLayout, as shown in the following figure.

Note: If you don't see the applet running above, you need to install release 6 of the JDK.

HitTestSample.java contains the complete code for this applet.

The mouseClicked method uses TextLayout.hitTestChar to return a java.awt.font.TextHitInfo object that contains the mouse click location (the insertion index) in the TextLayout object.

Information returned by the TextLayout getAscent, getDescent, and getAdvance methods is used to compute the location of the origin for the TextLayout object so it is horizontally and vertically centered.

...

private Point2D computeLayoutOrigin() {
  Dimension size = getPreferredSize();
  Point2D.Float origin = new Point2D.Float();

  origin.x = (float) (size.width - textLayout.getAdvance()) / 2;
  origin.y =
    (float) (size.height - textLayout.getDescent()
             + textLayout.getAscent())/2;
  return origin;
}

...

public void paintComponent(Graphics g) {
  super.paintComponent(g);
  setBackground(Color.white);
  Graphics2D graphics2D = (Graphics2D) g;
  Point2D origin = computeLayoutOrigin();
  graphics2D.translate(origin.getX(), origin.getY());

  // Draw textLayout.
  textLayout.draw(graphics2D, 0, 0);

  // Retrieve caret Shapes for insertionIndex.
  Shape[] carets = textLayout.getCaretShapes(insertionIndex);

  // Draw the carets.  carets[0] is the strong caret and
  // carets[1] is the weak caret.
  graphics2D.setColor(STRONG_CARET_COLOR);
  graphics2D.draw(carets[0]);
  if (carets[1] != null) {
    graphics2D.setColor(WEAK_CARET_COLOR);
    graphics2D.draw(carets[1]);
  }
}

...

private class HitTestMouseListener extends MouseAdapter {

    /**
     * Compute the character position of the mouse click.
     */
    public void mouseClicked(MouseEvent e) {

      Point2D origin = computeLayoutOrigin();

      // Compute the mouse click location relative to
      // textLayout's origin.
      float clickX = (float) (e.getX() - origin.getX());
      float clickY = (float) (e.getY() - origin.getY());

      // Get the character position of the mouse click.
      TextHitInfo currentHit = textLayout.hitTestChar(clickX, clickY);
      insertionIndex = currentHit.getInsertionIndex();

      // Repaint the Component so the new caret(s) will be displayed.
      hitPane.repaint();
    }
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Constructing Complex Shapes from Geometry Primitives
Next page: End of Trail


Trail: Sound (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Sound
The Java Sound API is a low-level API for effecting and controlling the input and output of sound media, including both audio and Musical Instrument Digital Interface (MIDI) data. The Java Sound API provides explicit control over the capabilities normally required for sound input and output, in a framework that promotes extensibility and flexibility.

The Java Sound API fulfills the needs of a wide range of application developers. Potential application areas include:

  • Communication frameworks, such as conferencing and telephony
  • End-user content delivery systems, such as media players and music using streamed content
  • Interactive application programs, such as games and Web sites that use dynamic content
  • Content creation and editing
  • Tools, toolkits, and utilities

The Java Sound API provides the lowest level of sound support on the Java platform. It provides application programs with a great amount of control over sound operations, and it is extensible. For example, the Java Sound API supplies mechanisms for installing, accessing, and manipulating system resources such as audio mixers, MIDI synthesizers, other audio or MIDI devices, file readers and writers, and sound format converters. The Java Sound API does not include sophisticated sound editors or graphical tools, but it provides capabilities upon which such programs can be built. It emphasizes low-level control beyond that commonly expected by the end user.

The Java Sound API includes support for both digital audio and MIDI data. These two major modules of functionality are provided in separate packages:

  • javax.sound.sampled
    This package specifies interfaces for capture, mixing, and playback of digital (sampled) audio.
  • javax.sound.midi
    This package provides interfaces for MIDI synthesis, sequencing, and event transport.

Two other packages permit service providers (as opposed to application developers) to create custom software components that extend the capabilities of an implementation of the Java Sound API:

  • javax.sound.sampled.spi
  • javax.sound.midi.spi

This page introduces the sampled-audio system, the MIDI system, and the SPI packages. Each package is then discussed in greater detail later in the tutorial.

Note: There are other Java platform APIs that also have sound-related elements. The Java Media Framework API (JMF) is a higher-level API that is currently available as a Standard Extension to the Java platform. JMF specifies a unified architecture, messaging protocol, and programming interface for capturing and playing back time-based media. JMF provides a simpler solution for basic media-player application programs, and it enables synchronization between different media types, such as audio and video. On the other hand, programs that focus on sound can benefit from the Java Sound API, especially if they require more advanced features, such as the ability to carefully control buffered audio playback or directly manipulate a MIDI synthesizer. Other Java APIs with sound aspects include Java 3D and APIs for telephony and speech. An implementation of any of these APIs might use an implementation of the Java Sound API internally, but is not required to do so.

What is Sampled Audio?

The javax.sound.sampled package handles digital audio data, which the Java Sound API refers to as sampled audio. Samples are successive snapshots of a signal. In the case of audio, the signal is a sound wave. A microphone converts the acoustic signal into a corresponding analog electrical signal, and an analog-to-digital converter transforms that analog signal into a sampled digital form. The following figure shows a brief moment in a sound recording.

A Sampled Sound Wave

A Sampled Sound Wave

This graph plots sound pressure (amplitude) on the vertical axis, and time on the horizontal axis. The amplitude of the analog sound wave is measured periodically at a certain rate, resulting in the discrete samples (the red data points in the figure) that comprise the digital audio signal. The center horizontal line indicates zero amplitude; points above the line are positive-valued samples, and points below are negative. The accuracy of the digital approximation of the analog signal depends on its resolution in time (the sampling rate) and its quantization, or resolution in amplitude (the number of bits used to represent each sample). As a point of reference, the audio recorded for storage on compact discs is sampled 44,100 times per second and represented with 16 bits per sample.

The term "sampled audio" is used here slightly loosely. A sound wave could be sampled at discrete intervals while being left in an analog form. For purposes of the Java Sound API, however, "sampled audio" is equivalent to "digital audio."

Typically, sampled audio on a computer comes from a sound recording, but the sound could instead be synthetically generated (for example, to create the sounds of a touch-tone telephone). The term "sampled audio" refers to the type of data, not its origin.

The Java Sound API does not assume a specific audio hardware configuration; it is designed to allow different sorts of audio components to be installed on a system and accessed by the API. The Java Sound API supports common functionality such as input and output from a sound card (for example, for recording and playback of sound files) as well as mixing of multiple streams of audio. Here is one example of a typical audio architecture:

The following context describes this figure

A Typical Audio Architecture

In this example, a device such as a sound card has various input and output ports, and mixing is provided in the software. The mixer might receive data that has been read from a file, streamed from a network, generated on the fly by an application program, or produced by a MIDI synthesizer. The mixer combines all its audio inputs into a single stream, which can be sent to an output device for rendering.

What is MIDI?

The javax.sound.midi package contains APIs for transporting and sequencing MIDI events, and for synthesizing sound from those events.

Whereas sampled audio is a direct representation of a sound itself, MIDI data can be thought of as a recipe for creating a sound, especially a musical sound. MIDI data, unlike audio data, does not describe sound directly. Instead, it describes events that affect the sounds (or actions) performed by a MIDI-enabled device or instrument, such as a synthesizer. MIDI data is analogous to a graphical user interface's keyboard and mouse events. In the case of MIDI, the events can be thought of as actions upon a musical keyboard, along with actions on various pedals, sliders, switches, and knobs on that musical instrument. These events need not actually originate with a hardware musical instrument; they can be simulated in software, and they can be stored in MIDI files. A program that can create, edit, and perform these files is called a sequencer. Many computer sound cards include MIDI-controllable music synthesizer chips to which sequencers can send their MIDI events. Synthesizers can also be implemented entirely in software. The synthesizers interpret the MIDI events that they receive and produce audio output. Usually the sound synthesized from MIDI data is musical sound (as opposed to speech, for example). MIDI synthesizers are also capable of generating various kinds of sound effects.

Some sound cards include MIDI input and output ports to which external MIDI hardware devices (such as keyboard synthesizers or other instruments) can be connected. From a MIDI input port, an application program can receive events generated by an external MIDI-equipped musical instrument. The program might play the musical performance using the computer's internal synthesizer, save it to disk as a MIDI file, or render it into musical notation. A program might use a MIDI output port to play an external instrument, or to control other external devices such as recording equipment.

The following diagram illustrates the functional relationships between the major components in a possible MIDI configuration based on the Java Sound API. (As with audio, the Java Sound API permits a variety of MIDI software devices to be installed and interconnected. The system shown here is just one potential scenario.) The flow of data between components is indicated by arrows. The data can be in a standard file format, or (as indicated by the key in the lower right corner of the diagram), it can be audio, raw MIDI bytes, or time-tagged MIDI messages.

The following context describes this figure.

A Possible MIDI Configuration

In this example, the application program prepares a musical performance by loading a musical score that's stored as a standard MIDI file on a disk (left side of the diagram). Standard MIDI files contain tracks, each of which is a list of time-tagged MIDI events. Most of the events represent musical notes (pitches and rhythms). This MIDI file is read and then "performed" by a software sequencer. A sequencer performs its music by sending MIDI messages to some other device, such as an internal or external synthesizer. The synthesizer itself may read a soundbank file containing instructions for emulating the sounds of certain musical instruments. If not, the synthesizer will play the notes stored in the MIDI file using whatever instrument sounds are already loaded into it.

As illustrated, the MIDI events must be translated into raw (non-time-tagged) MIDI before being sent through a MIDI output port to an external MIDI instrument. Similarly, raw MIDI data coming into the computer from an external MIDI source (a keyboard instrument, in the diagram) is translated into time-tagged MIDI messages that can control a synthesizer, or that a sequencer can store for later use.

Service Provider Interfaces

The javax.sound.sampled.spi and javax.sound.midi.spi packages contain APIs that let software developers create new audio or MIDI resources that can be provided separately to the user and "plugged in" to an existing implementation of the Java Sound API. Here are some examples of services (resources) that can be added in this way:

  • An audio mixer
  • A MIDI synthesizer
  • A file parser that can read or write a new type of audio or MIDI file
  • A converter that translates between different sound data formats

In some cases, services are software interfaces to the capabilities of hardware devices, such as sound cards, and the service provider might be the same as the vendor of the hardware. In other cases, the services exist purely in software. For example, a synthesizer or a mixer could be an interface to a chip on a sound card, or it could be implemented without any hardware support at all.

An implementation of the Java Sound API contains a basic set of services, but the service provider interface (SPI) packages allow third parties to create new services. These third-party services are integrated into the system in the same way as the built-in services. The AudioSystem class and the MidiSystem class act as coordinators that let application programs access the services explicitly or implicitly. Often the existence of a service is completely transparent to an application program that uses it. The service-provider mechanism benefits users of application programs based on the Java Sound API, because new sound features can be added to a program without requiring a new release of the JDK or runtime environment, and, in many cases, without even requiring a new release of the application program itself.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Overview of the Sampled Package


Overview of the Sampled Package (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Overview of the Sampled Package

The javax.sound.sampled package is fundamentally concerned with audio transport — in other words, the Java Sound API focuses on playback and capture. The central task that the Java Sound API addresses is how to move bytes of formatted audio data into and out of the system. This task involves opening audio input and output devices and managing buffers that get filled with real-time sound data. It can also involve mixing multiple streams of audio into one stream (whether for input or output). The transport of sound into or out of the system has to be correctly handled when the user requests that the flow of sound be started, paused, resumed, or stopped.

To support this focus on basic audio input and output, the Java Sound API provides methods for converting between various audio data formats, and for reading and writing common types of sound files. However, it does not attempt to be a comprehensive sound-file toolkit. A particular implementation of the Java Sound API need not support an extensive set of file types or data format conversions. Third-party service providers can supply modules that "plug in" to an existing implementation to support additional file types and conversions.

The Java Sound API can handle audio transport in both a streaming, buffered fashion and an in-memory, unbuffered fashion. "Streaming" is used here in a general sense to refer to real-time handling of audio bytes; it does not refer to the specific, well-known case of sending audio over the Internet in a certain format. In other words, a stream of audio is simply a continuous set of audio bytes that arrive more or less at the same rate that they are to be handled (played, recorded, etc.). Operations on the bytes commence before all the data has arrived. In the streaming model, particularly in the case of audio input rather than audio output, you do not necessarily know in advance how long the sound is and when it will finish arriving. You simply handle one buffer of audio data at a time, until the operation is halted. In the case of audio output (playback), you also need to buffer data if the sound you want to play is too large to fit in memory all at once. In other words, you deliver your audio bytes to the sound engine in chunks, and it takes care of playing each sample at the right time. Mechanisms are provided that make it easy to know how much data to deliver in each chunk.

The Java Sound API also permits unbuffered transport in the case of playback only, assuming you already have all the audio data at hand and it is not too large to fit in memory. In this situation, there is no need for the application program to buffer the audio, although the buffered, real-time approach is still available if desired. Instead, the entire sound can be preloaded at once into memory for subsequent playback. Because all the sound data is loaded in advance, playback can start immediately — for example, as soon as the user clicks a Start button. This can be an advantage compared to the buffered model, where the playback has to wait for the first buffer to fill. In addition, the in-memory, unbuffered model allows sounds to be easily looped (cycled) or set to arbitrary positions in the data.

To play or capture sound using the Java Sound API, you need at least three things: formatted audio data, a mixer, and a line. The following provides an overview of these concepts.

What is Formatted Audio Data?

Formatted audio data refers to sound in any of a number of standard formats. The Java Sound API distinguishes between data formats and file formats.

Data Formats

A data format tells you how to interpret a series of bytes of "raw" sampled audio data, such as samples that have already been read from a sound file, or samples that have been captured from the microphone input. You might need to know, for example, how many bits constitute one sample (the representation of the shortest instant of sound), and similarly you might need to know the sound's sample rate (how fast the samples are supposed to follow one another). When setting up for playback or capture, you specify the data format of the sound you are capturing or playing.

In the Java Sound API, a data format is represented by an AudioFormat object, which includes the following attributes:

  • Encoding technique, usually pulse code modulation (PCM)
  • Number of channels (1 for mono, 2 for stereo, etc.)
  • Sample rate (number of samples per second, per channel)
  • Number of bits per sample (per channel)
  • Frame rate
  • Frame size in bytes
  • Byte order (big-endian or little-endian)

PCM is one kind of encoding of the sound waveform. The Java Sound API includes two PCM encodings that use linear quantization of amplitude, and signed or unsigned integer values. Linear quantization means that the number stored in each sample is directly proportional (except for any distortion) to the original sound pressure at that instant—and similarly proportional to the displacement of a loudspeaker or eardrum that is vibrating with the sound at that instant. Compact discs, for example, use linear PCM-encoded sound. Mu-law encoding and a-law encoding are common nonlinear encodings that provide a more compressed version of the audio data; these encodings are typically used for telephony or recordings of speech. A nonlinear encoding maps the original sound's amplitude to the stored value using a nonlinear function, which can be designed to give more amplitude resolution to quiet sounds than to loud sounds.

A frame contains the data for all channels at a particular time. For PCM-encoded data, the frame is simply the set of simultaneous samples in all channels, for a given instant in time, without any additional information. In this case, the frame rate is equal to the sample rate, and the frame size in bytes is the number of channels multiplied by the sample size in bits, divided by the number of bits in a byte.

For other kinds of encodings, a frame might contain additional information besides the samples, and the frame rate might be completely different from the sample rate. For example, consider the MP3 (MPEG-1 Audio Layer 3) encoding, which is not explicitly mentioned in the current version of the Java Sound API, but which could be supported by an implementation of the Java Sound API or by a third-party service provider. In MP3, each frame contains a bundle of compressed data for a series of samples, not just one sample per channel. Because each frame encapsulates a whole series of samples, the frame rate is slower than the sample rate. The frame also contains a header. Despite the header, the frame size in bytes is less than the size in bytes of the equivalent number of PCM frames. (After all, the purpose of MP3 is to be more compact than PCM data.) For such an encoding, the sample rate and sample size refer to the PCM data that the encoded sound will eventually be converted into before being delivered to a digital-to-analog converter (DAC).

File Formats

A file format specifies the structure of a sound file, including not only the format of the raw audio data in the file, but also other information that can be stored in the file. Sound files come in various standard varieties, such as WAVE (also known as WAV, and often associated with PCs), AIFF (often associated with Macintoshes), and AU (often associated with UNIX systems). The different types of sound file have different structures. For example, they might have a different arrangement of data in the file's "header." A header contains descriptive information that typically precedes the file's actual audio samples, although some file formats allow successive "chunks" of descriptive and audio data. The header includes a specification of the data format that was used for storing the audio in the sound file. Any of these types of sound file can contain various data formats (although usually there is only one data format within a given file), and the same data format can be used in files that have different file formats.

In the Java Sound API, a file format is represented by an AudioFileFormat object, which contains:

  • The file type (WAVE, AIFF, etc.)
  • The file's length in bytes
  • The length, in frames, of the audio data contained in the file
  • An AudioFormat object that specifies the data format of the audio data contained in the file

The AudioSystem class provides methods for reading and writing sounds in different file formats, and for converting between different data formats. Some of the methods let you access a file's contents through a kind of stream called an AudioInputStream . An AudioInputStream is a subclass of the InputStream class, which encapsulates a series of bytes that can be read sequentially. To its superclass, the AudioInputStream class adds knowledge of the bytes' audio data format (represented by an AudioFormat object). By reading a sound file as an AudioInputStream, you get immediate access to the samples, without having to worry about the sound file's structure (its header, chunks, etc.). A single method invocation gives you all the information you need about the data format and the file type.

What is a Mixer?

Many application programming interfaces (APIs) for sound make use of the notion of an audio device. A device is often a software interface to a physical input/output device. For example, a sound-input device might represent the input capabilities of a sound card, including a microphone input, a line-level analog input, and perhaps a digital audio input.

In the Java Sound API, devices are represented by Mixer objects. The purpose of a mixer is to handle one or more streams of audio input and one or more streams of audio output. In the typical case, it actually mixes together multiple incoming streams into one outgoing stream. A Mixer object can represent the sound-mixing capabilities of a physical device such as a sound card, which might need to mix the sound coming in to the computer from various inputs, or the sound coming from application programs and going to outputs.

Alternatively, a Mixer object can represent sound-mixing capabilities that are implemented entirely in software, without any inherent interface to physical devices.

In the Java Sound API, a component such as the microphone input on a sound card is not itself considered a device — that is, a mixer — but rather a port into or out of the mixer. A port typically provides a single stream of audio into or out of the mixer (although the stream can be multichannel, such as stereo). The mixer might have several such ports. For example, a mixer representing a sound card's output capabilities might mix several streams of audio together, and then send the mixed signal to any or all of various output ports connected to the mixer. These output ports could be (for example) a headphone jack, a built-in speaker, or a line-level output.

To understand the notion of a mixer in the Java Sound API, it helps to visualize a physical mixing console, such as those used in live concerts and recording studios.

The following context describes this figure.

A Physical Mixing Console

A physical mixer has "strips" (also called "slices"), each representing a path through which a single audio signal goes into the mixer for processing. The strip has knobs and other controls by which you can control the volume and pan (placement in the stereo image) for the signal in that strip. Also, the mixer might have a separate bus for effects such as reverb, and this bus can be connected to an internal or external reverberation unit. Each strip has a potentiometer that controls how much of that strip's signal goes into the reverberated mix. The reverberated ("wet") mix is then mixed with the "dry" signals from the strips. A physical mixer sends this final mixture to an output bus, which typically goes to a tape recorder (or disk-based recording system) and/or speakers.

Imagine a live concert that is being recorded in stereo. Cables (or wireless connections) coming from the many microphones and electric instruments on stage are plugged into the inputs of the mixing console. Each input goes to a separate strip of the mixer, as illustrated. The sound engineer decides on the settings of the gain, pan, and reverb controls. The output of all the strips and the reverb unit are mixed together into two channels. These two channels go to two outputs on the mixer, into which cables are plugged that connect to the stereo tape recorder's inputs. The two channels are perhaps also sent via an amplifier to speakers in the hall, depending on the type of music and the size of the hall.

Now imagine a recording studio, in which each instrument or singer is recorded to a separate track of a multitrack tape recorder. After the instruments and singers have all been recorded, the recording engineer performs a "mixdown" to combine all the taped tracks into a two-channel (stereo) recording that can be distributed on compact discs. In this case, the input to each of the mixer's strips is not a microphone, but one track of the multitrack recording. Once again, the engineer can use controls on the strips to decide each track's volume, pan, and reverb amount. The mixer's outputs go once again to a stereo recorder and to stereo speakers, as in the example of the live concert.

These two examples illustrate two different uses of a mixer: to capture multiple input channels, combine them into fewer tracks, and save the mixture, or to play back multiple tracks while mixing them down to fewer tracks.

In the Java Sound API, a mixer can similarly be used for input (capturing audio) or output (playing back audio). In the case of input, the source from which the mixer gets audio for mixing is one or more input ports. The mixer sends the captured and mixed audio streams to its target, which is an object with a buffer from which an application program can retrieve this mixed audio data. In the case of audio output, the situation is reversed. The mixer's source for audio is one or more objects containing buffers into which one or more application programs write their sound data; and the mixer's target is one or more output ports.

What is a Line?

The metaphor of a physical mixing console is also useful for understanding the Java Sound API's concept of a line.

A line is an element of the digital audio "pipeline"—that is, a path for moving audio into or out of the system. Usually the line is a path into or out of a mixer (although technically the mixer itself is also a kind of line).

Audio input and output ports are lines. These are analogous to the microphones and speakers connected to a physical mixing console. Another kind of line is a data path through which an application program can get input audio from, or send output audio to, a mixer. These data paths are analogous to the tracks of the multitrack recorder connected to the physical mixing console.

One difference between lines in the Java Sound API and those of a physical mixer is that the audio data flowing through a line in the Java Sound API can be mono or multichannel (for example, stereo). By contrast, each of a physical mixer's inputs and outputs is typically a single channel of sound. To get two or more channels of output from the physical mixer, two or more physical outputs are normally used (at least in the case of analog sound; a digital output jack is often multichannel). In the Java Sound API, the number of channels in a line is specified by the AudioFormat of the data that is currently flowing through the line.

Let's now examine some specific kinds of lines and mixers. The following diagram shows different types of lines in a simple audio-output system that could be part of an implementation of the Java Sound API:

The following context describes this figure.

A Possible Configuration of Lines for Audio Output

In this example, an application program has gotten access to some available inputs of an audio-input mixer: one or more clips and source data lines. A clip is a mixer input (a kind of line) into which you can load audio data prior to playback; a source data line is a mixer input that accepts a real-time stream of audio data. The application program preloads audio data from a sound file into the clips. It then pushes other audio data into the source data lines, a buffer at a time. The mixer reads data from all these lines, each of which may have its own reverberation, gain, and pan controls, and mixes the dry audio signals with the wet (reverberated) mix. The mixer delivers its final output to one or more output ports, such as a speaker, a headphone jack, and a line-out jack.

Although the various lines are depicted as separate rectangles in the diagram, they are all "owned" by the mixer, and can be considered integral parts of the mixer. The reverb, gain, and pan rectangles represent processing controls (rather than lines) that can be applied by the mixer to data flowing through the lines.

Note that this is just one example of a possible mixer that is supported by the API. Not all audio configurations will have all the features illustrated. An individual source data line might not support panning, a mixer might not implement reverb, and so on.

A simple audio-input system might be similar:

The following context describes this figure

A Possible Configuration of Lines for Audio Input

Here, data flows into the mixer from one or more input ports, commonly the microphone or the line-in jack. Gain and pan are applied, and the mixer delivers the captured data to an application program via the mixer's target data line. A target data line is a mixer output, containing the mixture of the streamed input sounds. The simplest mixer has just one target data line, but some mixers can deliver captured data to multiple target data lines simultaneously.

The Line Interface Hierarchy

Now that we've seen some functional pictures of what lines and mixers are, let's discuss them from a slightly more programmatic perspective. Several types of line are defined by subinterfaces of the basic Line interface. The interface hierarchy is shown below.

The following context describes this figure

The Line Interface Hierarchy

The base interface, Line, describes the minimal functionality common to all lines:

  • Controls
    Data lines and ports often have a set of controls that affect the audio signal passing through the line. The Java Sound API specifies control classes that can be used to manipulate aspects of sound such as: gain (which affects the signal's volume in decibels), pan (which affects the sound's right-left positioning, reverb (which adds reverberation to the sound to emulate different kinds of room acoustics), and sample rate (which affects the rate of playback as well as the sound's pitch).
  • Open or closed status
    Successful opening of a line guarantees that resources have been allocated to the line. A mixer has a finite number of lines, so at some point multiple application programs (or the same one) might vie for usage of the mixer's lines. Closing a line indicates that any resources used by the line may now be released.
  • Events
    A line generates events when it opens or closes. Subinterfaces of Line can introduce other types of events. When a line generates an event, the event is sent to all objects that have registered to "listen" for events on that line. An application program can create these objects, register them to listen for line events, and react to the events as desired.

We'll now examine the subinterfaces of the Line interface.

Ports are simple lines for input or output of audio to or from audio devices. As mentioned earlier, some common types of ports are the microphone, line input, CD-ROM drive, speaker, headphone, and line output.

The Mixer interface represents a mixer, of course, which as we have seen represents either a hardware or a software device. The Mixer interface provides methods for obtaining a mixer's lines. These include source lines, which feed audio to the mixer, and target lines, to which the mixer delivers its mixed audio. For an audio-input mixer, the source lines are input ports such as the microphone input, and the target lines are TargetDataLines (described below), which deliver audio to the application program. For an audio-output mixer, on the other hand, the source lines are Clips or SourceDataLines (described below), to which the application program feeds audio data, and the target lines are output ports such as the speaker.

A Mixer is defined as having one or more source lines and one or more target lines. Note that this definition means that a mixer need not actually mix data; it might have only a single source line. The Mixer API is intended to encompass a variety of devices, but the typical case supports mixing.

The Mixer interface supports synchronization; that is, you can specify that two or more of a mixer's lines be treated as a synchronized group. Then you can start, stop, or close all those data lines by sending a single message to any line in the group, instead of having to control each line individually. With a mixer that supports this feature, you can obtain sample-accurate synchronization between lines.

The generic Line interface does not provide a means to start and stop playback or recording. For that you need a data line. The DataLine interface supplies the following additional media-related features beyond those of a Line:

  • Audio format
    Each data line has an audio format associated with its data stream.
  • Media position
    A data line can report its current position in the media, expressed in sample frames. This represents the number of sample frames captured by or rendered from the data line since it was opened.
  • Buffer size
    This is the size of the data line's internal buffer in bytes. For a source data line, the internal buffer is one to which data can be written, and for a target data line it's one from which data can be read.
  • Level (the current amplitude of the audio signal)

  • Start and stop playback or capture

  • Pause and resume playback or capture

  • Flush (discard unprocessed data from the queue)

  • Drain (block until all unprocessed data has been drained from the queue, and the data line's buffer has become empty)

  • Active status
    A data line is considered active if it is engaged in active presentation or capture of audio data to or from a mixer.
  • Events
    START and STOP events are produced when active presentation or capture of data from or to the data line starts or stops.

    • A TargetDataLine receives audio data from a mixer. Commonly, the mixer has captured audio data from a port such as a microphone; it might process or mix this captured audio before placing the data in the target data line's buffer. The TargetDataLine interface provides methods for reading the data from the target data line's buffer and for determining how much data is currently available for reading.

    A SourceDataLine receives audio data for playback. It provides methods for writing data to the source data line's buffer for playback, and for determining how much data the line is prepared to receive without blocking.

    A Clip is a data line into which audio data can be loaded prior to playback. Because the data is pre-loaded rather than streamed, the clip's duration is known before playback, and you can choose any starting position in the media. Clips can be looped, meaning that upon playback, all the data between two specified loop points will repeat a specified number of times, or indefinitely.

    This section has introduced most of the important interfaces and classes of the sampled-audio API. Subsequent sections show how you can access and use these objects in your application program.

    « Previous • Trail • Next »
    Problems with the examples? Try Compiling and Running the Examples: FAQs.
    Complaints? Compliments? Suggestions? Give us your feedback.

    Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

             About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
    Copyright 1995-2008 Sun Microsystems, Inc.
    Previous page: Table of Contents
    Next page: Accessing Audio System Resources


Accessing Audio System Resources (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Accessing Audio System Resources
The Java Sound API takes a flexible approach to system configuration. Different sorts of audio devices (mixers) can be installed on a computer. The API makes few assumptions about what devices have been installed and what their capabilities are. Instead, it provides ways for the system to report about the available audio components, and ways for your program to access them.

The following sections show how your program can learn what sampled-audio resources have been installed on the computer, and how it can gain access to the available resources. Among other things, the resources include mixers and the various types of lines owned by the mixers.

The AudioSystem Class

The AudioSystem class acts as a clearinghouse for audio components, including built-in services and separately installed services from third-party providers. AudioSystem serves as an application program's entry point for accessing these installed sampled-audio resources. You can query the AudioSystem to learn what sorts of resources have been installed, and then you can obtain access to them. For example, an application program might start out by asking the AudioSystem class whether there is a mixer that has a certain configuration, such as one of the input or output configurations illustrated earlier in the discussion of lines. From the mixer, the program would then obtain data lines, and so on.

Here are some of the resources an application program can obtain from the AudioSystem:

  • Mixers
    A system typically has multiple mixers installed. There is usually at least one for audio input and one for audio output. There might also be mixers that don't have I/O ports but instead accept audio from an application program and deliver the mixed audio back to the program. The AudioSystem class provides a list of all of the installed mixers.
  • Lines
    Even though every line is associated with a mixer, an application program can get a line directly from the AudioSystem, without dealing explicitly with mixers.
  • Format conversions
    An application program can use format conversions to translate audio data from one format to another.
  • Files and streams
    The AudioSystem class provides methods for translating between audio files and audio streams. It can also report the file format of a sound file and can write files in different formats.

Information Objects

Several classes in the Java Sound API provide useful information about associated interfaces. For example, Mixer.Info provides details about an installed mixer, such as the mixer's vendor, name, description, and version. Line.Info obtains the class of a specific line. Subclasses of Line.Info include Port.Info and DataLine.Info , which obtain details relevant to a specific port and data line, respectively. Each of these classes is described further in the appropriate section below. It's important not to confuse the Info object with the mixer or line object that it describes.

Getting a Mixer

Usually, one of the first things a program that uses the Java Sound API needs to do is to obtain a mixer, or at least one line of a mixer, so that you can get sound into or out of the computer. Your program might need a specific kind of mixer, or you might want to display a list of all the available mixers so that the user can select one. In either case, you need to learn what kinds of mixers are installed. AudioSystem provides the following method:

static Mixer.Info[] getMixerInfo()
Each Mixer.Info object returned by this method identifies one type of mixer that is installed. (Usually a system has at most one mixer of a given type. If there happens to be more than one of a given type, the returned array still only has one Mixer.Info for that type.) An application program can iterate over the Mixer.Info objects to find an appropriate one, according to its needs. The Mixer.Info includes the following strings to identify the kind of mixer:

  • Name
  • Version
  • Vendor
  • Description

These are arbitrary strings, so an application program that needs a specific mixer must know what to expect and what to compare the strings to. The company that provides the mixer should include this information in its documentation. Alternatively, and perhaps more typically, the application program will display all the Mixer.Info objects' strings to the user and let the user choose the corresponding mixer.

Once an appropriate mixer is found, the application program invokes the following AudioSystem method to obtain the desired mixer:

static Mixer getMixer(Mixer.Info info)
What if your program needs a mixer that has certain capabilities, but it doesn't need a specific mixer made by a specific vendor? And what if you can't depend on the user's knowing which mixer should be chosen? In that case, the information in the Mixer.Info objects won't be of much use. Instead, you can iterate over all the Mixer.Info objects returned by getMixerInfo, get a mixer for each by invoking getMixer, and query each mixer for its capabilities. For example, you might need a mixer that can write its mixed audio data to a certain number of target data lines simultaneously. In that case, you would query each mixer using this Mixer method:
int getMaxLines(Line.Info info)

Here, the Line.Info would specify a TargetDataLine. The Line.Info class is discussed in the next section.

Getting a Line of a Desired Type

There are two ways to get a line:

  • Directly from the AudioSystem object
  • From a mixer that you have already obtained from the AudioSystem object

Getting a Line Directly from the AudioSystem

Let's assume you haven't obtained a mixer, and your program is a simple one that really only needs a certain kind of line; the details of the mixer don't matter to you. You can use the AudioSystem method:

static Line getLine(Line.Info info)
which is analogous to the getMixer method discussed previously. Unlike Mixer.Info , the Line.Info used as an argument doesn't store textual information to specify the desired line. Instead, it stores information about the class of line desired.

Line.Info is an abstract class, so you use one of its subclasses ( Port.Info or DataLine.Info ) to obtain a line. The following code excerpt uses the DataLine.Info subclass to obtain and open a target data line:

TargetDataLine line;
DataLine.Info info = new DataLine.Info(TargetDataLine.class,
    format); // format is an AudioFormat object
if (!AudioSystem.isLineSupported(info)) {
    // Handle the error.
    }
    // Obtain and open the line.
try {
    line = (TargetDataLine) AudioSystem.getLine(info);
    line.open(format);
} catch (LineUnavailableException ex) {
       // Handle the error.
    //...
}
This code obtains a TargetDataLine object without specifying any attributes other than its class and its audio format. You can use analogous code to obtain other kinds of lines. For a SourceDataLine or a Clip, just substitute that class for TargetDataLine as the class of the line variable, and also in the first argument to the DataLine.Info constructor.

For a Port, you can use static instances of Port.Info, in code like the following:

if (AudioSystem.isLineSupported(Port.Info.MICROPHONE)) {
    try {
        line = (Port) AudioSystem.getLine(
            Port.Info.MICROPHONE);
    }
}
Note the use of the method isLineSupported to see whether the mixer even has a line of the desired type.

Recall that a source line is an input to a mixer—namely, a Port object if the mixer represents an audio-input device, and a SourceDataLine or Clip object if the mixer represents an audio-output device. Similarly, a target line is an output of the mixer: a Port object for an audio-output mixer, and a TargetDataLine object for an audio-input mixer. What if a mixer doesn't connect to any external hardware device at all? For example, consider an internal or software-only mixer that gets audio from an application program and delivers its mixed audio back to the program. This kind of mixer has SourceDataLine or Clip objects for its input lines and TargetDataLine objects for its output lines.

You can also use the following AudioSystem methods to learn more about source and target lines of a specified type that are supported by any installed mixer:

static Line.Info[] getSourceLineInfo(Line.Info info)
static Line.Info[] getTargetLineInfo(Line.Info info)
Note that the array returned by each of these methods indicates unique types of lines, not necessarily all the lines. For example, if two of a mixer's lines, or two lines of different mixers, have identical Line.Info objects, the two lines will represented by only one Line.Info in the returned array.

Getting a Line from a Mixer

The Mixer interface includes variations on the AudioSystem access methods for source and target lines, described above. These Mixer methods include ones that take Line.Info arguments, just as AudioSystem's methods do. However, Mixer also includes these variants, which take no arguments:

Line.Info[] getSourceLineInfo()
Line.Info[] getTargetLineInfo()
These methods return arrays of all the Line.Info objects for the particular mixer. Once you've obtained the arrays, you can iterate over them, calling Mixer's getLine method to obtain each line, followed by Line's open method to reserve use of each line for your program.

Selecting Input and Output Ports

The previous section, regarding how to obtain a line of a desired type, applies to ports as well as other types of lines. You can obtain all of the source (i.e., input) and target (i.e, output) ports by passing a Port.Info object to the AudioSystem (or Mixer) methods getSourceLineInfo and getTargetLineInfo that take a Line.Info argument. You then iterate over the returned array of objects and invoke Mixer's getLine method to get each port.

You can then open each Port by invoking Line's open method. Opening a port means you turn it on—that is, you allow sound to come in or out the port. Similarly, you can close ports that you don't want sound to travel through, because some ports might already be open before you even obtain them. Some platforms leave all ports on by default; or a user or system administrator might have selected certain ports to be on or off, using another application program or operating-system software.

Warning: If you want to select a certain port and make sure that the sound is actually going in or out the port, you can open the port as described. However, this can be considered user-hostile behavior! For example, a user might have the speaker port turned off so as not to disturb her co-workers. She would be rather upset if your program suddenly overrode her wishes and started blaring music. As another example, a user might want to be assured that his computer's microphone is never turned on without his knowledge, to avoid eavesdropping. In general, it is recommended not to open or close ports unless your program is responding to the user's intentions, as expressed through the user interface. Instead, respect the settings that the user or the operating system has already selected.

It isn't necessary to open or close a port before the mixer it's attached to will function correctly. For example, you can start playing back sound into an audio-output mixer, even though all its output ports are closed. The data still flows into the mixer; the playback isn't blocked. The user just won't hear anything. As soon as the user opens an output port, the sound will be audible through that port, starting at whatever point in the media the playback has already reached.

Also, you don't need to access the ports to learn whether the mixer has certain ports. To learn whether a mixer is actually an audio-output mixer, for example, you can invoke getTargetLineInfo to see whether it has output ports. There's no reason to access the ports themselves unless you want to change their settings (such as their open-or-closed state, or the settings of any controls they might have).

Permission to Use Audio Resources

The Java Sound API includes an AudioPermission class that indicates what kinds of access an applet (or an application running with a security manager) can have to the sampled-audio system. Permission to record sound is controlled separately. This permission should be granted with care, to help prevent security risks such as unauthorized eavesdropping. By default, applets and applications are granted permissions as follows:

  • An applet running with the applet security manager can play, but not record, audio.
  • An application running with no security manager can both play and record audio.
  • An application running with the default security manager can play, but not record, audio.

In general, applets are run under the scrutiny of a security manager and aren't permitted to record sound. Applications, on the other hand, don't automatically install a security manager, and are able to record sound. (However, if the default security manager is invoked explicitly for an application, the application isn't permitted to record sound.)

Both applets and applications can record sound even when running with a security manager if they have been granted explicit permission to do so.

If your program doesn't have permission to record (or play) sound, an exception will be thrown when it attempts to open a line. There is nothing you can do about this in your program, other than to catch the exception and report the problem to the user, because permissions can't be changed through the API. (If they could, they would be pointless, because nothing would be secure!) Generally, permissions are set in one or more policy configuration files, which a user or system administrator can edit using a text editor or the Policy Tool program.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Overview of the Sampled Package
Next page: Playing Back Audio


Playing Back Audio (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Playing Back Audio
Playback is sometimes referred to as presentation or rendering. These are general terms that are applicable to other kinds of media besides sound. The essential feature is that a sequence of data is delivered somewhere for eventual perception by a user. If the data is time-based, as sound is, it must be delivered at the correct rate. With sound even more than video, it's important that the rate of data flow be maintained, because interruptions to sound playback often produce loud clicks or irritating distortion. The Java Sound API is designed to help application programs play sounds smoothly and continuously, even very long sounds.

Earlier you saw how to obtain a line from the audio system or from a mixer. Here you will learn how to play sound through a line.

As you know, there are two kinds of line that you can use for playing sound: a Clip and a SourceDataLine. The primary difference between the two is that with a Clip you specify all the sound data at one time, before playback, whereas with a SourceDataLine you keep writing new buffers of data continuously during playback. Although there are many situations in which you could use either a Clip or a SourceDataLine, the following criteria help identify which kind of line is better suited for a particular situation:

  • Use a Clip when you have non-real-time sound data that can be preloaded into memory.

    For example, you might read a short sound file into a clip. If you want the sound to play back more than once, a Clip is more convenient than a SourceDataLine, especially if you want the playback to loop (cycle repeatedly through all or part of the sound). If you need to start the playback at an arbitrary position in the sound, the Clip interface provides a method to do that easily. Finally, playback from a Clip generally has less latency than buffered playback from a SourceDataLine. In other words, because the sound is preloaded into a clip, playback can start immediately instead of having to wait for the buffer to be filled.

  • Use a SourceDataLine for streaming data, such as a long sound file that won't all fit in memory at once, or a sound whose data can't be known in advance of playback.

    As an example of the latter case, suppose you're monitoring sound input—that is, playing sound back as it's being captured. If you don't have a mixer that can send input audio right back out an output port, your application program will have to take the captured data and send it to an audio-output mixer. In this case, a SourceDataLine is more appropriate than a Clip. Another example of sound that can't be known in advance occurs when you synthesize or manipulate the sound data interactively in response to the user's input. For example, imagine a game that gives aural feedback by "morphing" from one sound to another as the user moves the mouse. The dynamic nature of the sound transformation requires the application program to update the sound data continuously during playback, instead of supplying it all before playback starts.

Using a Clip

You obtain a Clip as described earlier under Getting a Line of a Desired Type; Construct a DataLine.Info object with Clip.class for the first argument, and pass this DataLine.Info as an argument to the getLine method of AudioSystem or Mixer.

Obtaining a line just means you've gotten a way to refer to it; getLine doesn't actually reserve the line for you. Because a mixer might have a limited number of lines of the desired type available, it can happen that after you invoke getLine to obtain the clip, another application program jumps in and grabs the clip before you're ready to start playback. To actually use the clip, you need to reserve it for your program's exclusive use by invoking one of the following Clip methods:

void open(AudioInputStream stream)
void open(AudioFormat format, byte[] data, int offset, int bufferSize)
Despite the bufferSize argument in the second open method above, Clip (unlike SourceDataLine) includes no methods for writing new data to the buffer. The bufferSize argument here just specifies how much of the byte array to load into the clip. It's not a buffer into which you can subsequently load more data, as you can with a SourceDataLine's buffer.

After opening the clip, you can specify at what point in the data it should start playback, using Clip's setFramePosition or setMicroSecondPosition methods. Otherwise, it will start at the beginning. You can also configure the playback to cycle repeatedly, using the setLoopPoints method.

When you're ready to start playback, simply invoke the start method. To stop or pause the clip, invoke the stop method, and to resume playback, invoke start again. The clip remembers the media position where it stopped playback, so there's no need for explicit pause and resume methods. If you don't want it to resume where it left off, you can "rewind" the clip to the beginning (or to any other position, for that matter) using the frame- or microsecond-positioning methods mentioned above.

A Clip's volume level and activity status (active versus inactive) can be monitored by invoking the DataLine methods getLevel and isActive, respectively. An active Clip is one that is currently playing sound.

Using a SourceDataLine

Obtaining a SourceDataLine is similar to obtaining a Clip.

Opening the SourceDataLine is also similar to opening a Clip, in that the purpose is once again to reserve the line. However, you use a different method, inherited from DataLine:

void open(AudioFormat format)
Notice that when you open a SourceDataLine, you don't associate any sound data with the line yet, unlike opening a Clip. Instead, you just specify the format of the audio data you want to play. The system chooses a default buffer length.

You can also stipulate a certain buffer length in bytes, using this variant:

void open(AudioFormat format, int bufferSize)
For consistency with similar methods, the bufferSize argument is expressed in bytes, but it must correspond to an integral number of frames.

Instead of using the open method described above, it's also possible to open a SourceDataLine using Line's open() method, without arguments. In this case, the line is opened with its default audio format and buffer size. However, you can't change these later. If you want to know the line's default audio format and buffer size, you can invoke DataLine's getFormat and getBufferSize methods, even before the line has ever been opened.

Once the SourceDataLine is open, you can start playing sound. You do this by invoking DataLine's start method, and then writing data repeatedly to the line's playback buffer.

The start method permits the line to begin playing sound as soon as there's any data in its buffer. You place data in the buffer by the following method:

int write(byte[] b, int offset, int length)
The offset into the array is expressed in bytes, as is the array's length.

The line begins sending data as soon as possible to its mixer. When the mixer itself delivers the data to its target, the SourceDataLine generates a START event. (In a typical implementation of the Java Sound API, the delay between the moment that the source line delivers data to the mixer and the moment that the mixer delivers the data to its target is negligible—that is, much less than the time of one sample.) This START event gets sent to the line's listeners, as explained below under Monitoring a Line's Status. The line is now considered active, so the isActive method of DataLine will return true. Notice that all this happens only once the buffer contains data to play, not necessarily right when the start method is invoked. If you invoked start on a new SourceDataLine but never wrote data to the buffer, the line would never be active and a START event would never be sent. (However, in this case, the isRunning method of DataLine would return true.)

So how do you know how much data to write to the buffer, and when to send the second batch of data? Fortunately, you don't need to time the second invocation of write to synchronize with the end of the first buffer! Instead, you can take advantage of the write method's blocking behavior:

  • The method returns as soon as the data has been written to the buffer. It doesn't wait until all the data in the buffer has finished playing. (If it did, you might not have time to write the next buffer without creating a discontinuity in the audio.)
  • It's all right to try to write more data than the buffer will hold. In this case, the method blocks (doesn't return) until all the data you requested has actually been placed in the buffer. In other words, one buffer's worth of your data at a time will be written to the buffer and played, until the remaining data all fits in the buffer, at which point the method returns. Whether or not the method blocks, it returns as soon as the last buffer's worth of data from this invocation can be written. Again, this means that your code will in all likelihood regain control before playback of the last buffer's worth of data has finished.
  • While in many contexts it is fine to write more data than the buffer will hold, if you want to be certain that the next write issued does not block, you can limit the number of bytes you write to the number that DataLine's available method returns.

Here's an example of iterating through chunks of data that are read from a stream, writing one chunk at a time to the SourceDataLine for playback:

// read chunks from a stream and write them to a source data
line
line.start();
while (total < totalToRead && !stopped)}
    numBytesRead = stream.read(myData, 0, numBytesToRead);
    if (numBytesRead == -1) break;
    total += numBytesRead;
    line.write(myData, 0, numBytesRead);

}
If you don't want the write method to block, you can first invoke the available method (inside the loop) to find out how many bytes can be written without blocking, and then limit the numBytesToRead variable to this number, before reading from the stream. In the example given, though, blocking won't matter much, since the write method is invoked inside a loop that won't complete until the last buffer is written in the final loop iteration. Whether or not you use the blocking technique, you'll probably want to invoke this playback loop in a separate thread from the rest of the application program, so that your program doesn't appear to freeze when playing a long sound. On each iteration of the loop, you can test whether the user has requested playback to stop. Such a request needs to set the stopped boolean, used in the code above, to true.

Since write returns before all the data has finished playing, how do you learn when the playback has actually completed? One way is to invoke the drain method of DataLine after writing the last buffer's worth of data. This method blocks until all the data has been played. When control returns to your program, you can free up the line, if desired, without fear of prematurely cutting off the playback of any audio samples:

line.write(b, offset, numBytesToWrite);
//this is the final invocation of write
line.drain();
line.stop();
line.close();
line = null;
You can intentionally stop playback prematurely, of course. For example, the application program might provide the user with a Stop button. Invoke DataLine's stop method to stop playback immediately, even in the middle of a buffer. This leaves any unplayed data in the buffer, so that if you subsequently invoke start, the playback resumes where it left off. If that's not what you want to happen, you can discard the data left in the buffer by invoking flush.

A SourceDataLine generates a STOP event whenever the flow of data has been stopped, whether this stoppage was initiated by the drain method, the stop method, or the flush method, or because the end of a playback buffer was reached before the application program invoked write again to provide new data. A STOP event doesn't necessarily mean that the stop method was invoked, and it doesn't necessarily mean that a subsequent invocation of isRunning will return false. It does, however, mean that isActive will return false. (When the start method has been invoked, the isRunning method will return true, even if a STOP event is generated, and it will begin to return false only once the stop method is invoked.) It's important to realize that START and STOP events correspond to isActive, not to isRunning.

Monitoring a Line's Status

Once you have started a sound playing, how do you find when it's finished? We saw one solution above—invoking the drain method after writing the last buffer of data—but that approach is applicable only to a SourceDataLine. Another approach, which works for both SourceDataLines and Clips, is to register to receive notifications from the line whenever the line changes its state. These notifications are generated in the form of LineEvent objects, of which there are four types: OPEN, CLOSE, START, and STOP.

Any object in your program that implements the LineListener interface can register to receive such notifications. To implement the LineListener interface, the object simply needs an update method that takes a LineEvent argument. To register this object as one of the line's listeners, you invoke the following Line method:

public void addLineListener(LineListener listener)

Whenever the line opens, closes, starts, or stops, it sends an update message to all its listeners. Your object can query the LineEvent that it receives. First you might invoke LineEvent.getLine to make sure the line that stopped is the one you care about. In the case we're discussing here, you want to know if the sound is finished, so you see whether the LineEvent is of type STOP. If it is, you might check the sound's current position, which is also stored in the LineEvent object, and compare it to the sound's length (if known) to see whether it reached the end and wasn't stopped by some other means (such as the user's clicking a Stop button, although you'd probably be able to determine that cause elsewhere in your code).

Along the same lines, if you need to know when the line is opened, closed, or started, you use the same mechanism. LineEvents are generated by different kinds of lines, not just Clips and SourceDataLines. However, in the case of a Port you can't count on getting an event to learn about a line's open or closed state. For example, a Port might be initially open when it's created, so you don't invoke the open method and the Port doesn't ever generate an OPEN event. (See the previous discussion of Selecting Input and Output Ports.)

Synchronizing Playback on Multiple Lines

If you're playing back multiple tracks of audio simultaneously, you probably want to have them all start and stop at exactly the same time. Some mixers facilitate this behavior with their synchronize method, which lets you apply operations such as open, close, start, and stop to a group of data lines using a single command, instead of having to control each line individually. Furthermore, the degree of accuracy with which operations are applied to the lines is controllable.

To find out whether a particular mixer offers this feature for a specified group of data lines, invoke the Mixer interface's isSynchronizationSupported method:

boolean isSynchronizationSupported(Line[] lines, boolean  maintainSync)

The first parameter specifies a group of specific data lines, and the second parameter indicates the accuracy with which synchronization must be maintained. If the second parameter is true, the query is asking whether the mixer is capable of maintaining sample-accurate precision in controlling the specified lines at all times; otherwise, precise synchronization is required only during start and stop operations, not throughout playback.

Processing the Outgoing Audio

Some source data lines have signal-processing controls, such as gain, pan, reverb, and sample-rate controls. Similar controls, especially gain controls, might be present on the output ports as well. For more information on how to determine whether a line has such controls, and how to use them if it does, see Processing Audio with Controls.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Accessing Audio System Resources
Next page: Capturing Audio


Capturing Audio (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Capturing Audio

Capturing refers to the process of obtaining a signal from outside the computer. A common application of audio capture is recording, such as recording the microphone input to a sound file. However, capturing isn't synonymous with recording, because recording implies that the application always saves the sound data that's coming in. An application that captures audio doesn't necessarily store the audio. Instead it might do something with the data as it's coming in — such as transcribe speech into text — but then discard each buffer of audio as soon as it's finished with that buffer.

As discussed in Overview of the Sampled Package, a typical audio-input system in an implementation of the Java Sound API consists of:

  1. An input port, such as a microphone port or a line-in port, which feeds its incoming audio data into:
  2. A mixer, which places the input data in:
  3. One or more target data lines, from which an application can retrieve the data.

    Commonly, only one input port can be open at a time, but an audio-input mixer that mixes audio from multiple ports is also possible. Another scenario consists of a mixer that has no ports but instead gets its audio input over a network.

    The TargetDataLine interface was introduced briefly under The Line Interface Hierarchy. TargetDataLine is directly analogous to the SourceDataLine interface, which was discussed extensively in Playing Back Audio. Recall that the SourceDataLine interface consists of:

  • A write method to send audio to the mixer
  • An available method to determine how much data can be written to the buffer without blocking

Similarly, TargetDataLine consists of:

  • A read method to get audio from the mixer
  • An available method to determine how much data can be read from the buffer without blocking

Setting Up a TargetDataLine

The process of obtaining a target data line was described in Accessing Audio System Resources but we repeat it here for convenience:

TargetDataLine line;
DataLine.Info info = new DataLine.Info(TargetDataLine.class,

    format); // format is an AudioFormat object
if (!AudioSystem.isLineSupported(info)) {
    // Handle the error ...

}
// Obtain and open the line.
try {

    line = (TargetDataLine) AudioSystem.getLine(info);
    line.open(format);
} catch (LineUnavailableException ex) {
    // Handle the error ...
}
You could instead invoke Mixer's getLine method, rather than AudioSystem's.

As shown in this example, once you've obtained a target data line, you reserve it for your application's use by invoking the SourceDataLine method open, exactly as was described in the case of a source data line in Playing Back Audio. The single-parameter version of the open method causes the line's buffer to have the default size. You can instead set the buffer size according to your application's needs by invoking the two-parameter version:

void open(AudioFormat format, int bufferSize)

Reading the Data from the TargetDataLine

Once the line is open, it is ready to start capturing data, but it isn't active yet. To actually commence the audio capture, use the DataLine method start. This begins delivering input audio data to the line's buffer for your application to read. Your application should invoke start only when it's ready to begin reading from the line; otherwise a lot of processing is wasted on filling the capture buffer, only to have it overflow (that is, discard data).

To start retrieving data from the buffer, invoke TargetDataLine's read method:

int read(byte[] b, int offset, int length)
This method attempts to read length bytes of data into the array b, starting at the byte position offset in the array. The method returns the number of bytes actually read.

As with SourceDataLine's write method, you can request more data than actually fits in the buffer, because the method blocks until the requested amount of data has been delivered, even if you request many buffers' worth of data.

To avoid having your application hang during recording, you can invoke the read method within a loop, until you've retrieved all the audio input, as in this example:

// Assume that the TargetDataLine, line, has already
// been obtained and opened.
ByteArrayOutputStream out  = new ByteArrayOutputStream();
int numBytesRead;
byte[] data = new byte[line.getBufferSize() / 5];

// Begin audio capture.
line.start();

// Here, stopped is a global boolean set by another thread.
while (!stopped) {
   // Read the next chunk of data from the TargetDataLine.
   numBytesRead =  line.read(data, 0, data.length);
   // Save this chunk of data.
   out.write(data, 0, numBytesRead);
}
Notice that in this example, the size of the byte array into which the data is read is set to be one-fifth the size of the line's buffer. If you instead make it as big as the line's buffer and try to read the entire buffer, you need to be very exact in your timing, because data will be dumped if the mixer needs to deliver data to the line while you are reading from it. By using some fraction of the line's buffer size, as shown here, your application will be more successful in sharing access to the line's buffer with the mixer.

The read method of TargetDataLine takes three arguments: a byte array, an offset into the array, and the number of bytes of input data that you would like to read. In this example, the third argument is simply the length of your byte array. The read method returns the number of bytes that were actually read into your array.

Typically, you read data from the line in a loop, as in this example. Within the while loop, each chunk of retrieved data is processed in whatever way is appropriate for the application—here, it's written to a ByteArrayOutputStream. Not shown here is the use of a separate thread to set the boolean stopped, which terminates the loop. This boolean's value might be set to true when the user clicks a Stop button, and also when a listener receives a CLOSE or STOP event from the line. The listener is necessary for CLOSE events and recommended for STOP events. Otherwise, if the line gets stopped somehow without stopped being set to true, the while loop will capture zero bytes on each iteration, running fast and wasting CPU cycles. A more thorough code example would show the loop being re-entered if capture becomes active again.

As with a source data line, it's possible to drain or flush a target data line. For example, if you're recording the input to a file, you'll probably want to invoke the drain method when the user clicks a Stop button. The drain method will cause the mixer's remaining data to get delivered to the target data line's buffer. If you don't drain the data, the captured sound might seem to be truncated prematurely at the end.

There might be some cases where you instead want to flush the data. In any case, if you neither flush nor drain the data, it will be left in the mixer. This means that when capture recommences, there will be some leftover sound at the beginning of the new recording, which might be undesirable. It can be useful, then, to flush the target data line before restarting the capture.

Monitoring the Line's Status

Because the TargetDataLine interface extends DataLine, target data lines generate events in the same way source data lines do. You can register an object to receive events whenever the target data line opens, closes, starts, or stops. For more information, see the previous discussion of Monitoring a Line's Status.

Processing the Incoming Audio

Like some source data lines, some mixers' target data lines have signal-processing controls, such as gain, pan, reverb, or sample-rate controls. The input ports might have similar controls, especially gain controls. In the next section, you'll learn how to determine whether a line has such controls, and how to use them if it does.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Playing Back Audio
Next page: Processing Audio with Controls


Processing Audio with Controls (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Processing Audio with Controls
Previous sections have discussed how to play or capture audio samples. The implicit goal has been to deliver samples as faithfully as possible, without modification (other than possibly mixing the samples with those from other audio lines). Sometimes, however, you want to be able to modify the signal. The user might want it to sound louder, quieter, fuller, more reverberant, higher or lower in pitch, and so on. This page discusses the Java Sound API features that provide these kinds of signal processing.

There are two ways to apply signal processing:

  • You can use any processing supported by the mixer or its component lines, by querying for Control objects and then setting the controls as the user desires. Typical controls supported by mixers and lines include gain, pan, and reverberation controls.

  • If the kind of processing you need isn't provided by the mixer or its lines, your program can operate directly on the audio bytes, manipulating them as desired.

This page discusses the first technique in greater detail, because there is no special API for the second technique.

Introduction to Controls

A mixer can have various sorts of signal-processing controls on some or all of its lines. For example, a mixer used for audio capture might have an input port with a gain control, and target data lines with gain and pan controls. A mixer used for audio playback might have sample-rate controls on its source data lines. In each case, the controls are all accessed through methods of the Line interface.

Because the Mixer interface extends Line, the mixer itself can have its own set of controls. These might serve as master controls affecting all the mixer's source or target lines. For example, the mixer might have a master gain control whose value in decibels is added to the values of individual gain controls on its target lines.

Others of the mixer's own controls might affect a special line, neither a source nor a target, that the mixer uses internally for its processing. For example, a global reverb control might choose the sort of reverberation to apply to a mixture of the input signals, and this "wet" (reverberated) signal would get mixed back into the "dry" signal before delivery to the mixer's target lines.

If the mixer or any of its lines have controls, you might wish to expose the controls via graphical objects in your program's user interface, so that the user can adjust the audio characteristics as desired. The controls are not themselves graphical; they just allow you to retrieve and change their settings. It's up to you to decide what sort of graphical representations (sliders, buttons, etc.), if any, to use in your program.

All controls are implemented as concrete subclasses of the abstract class Control. Many typical audio-processing controls can be described by abstract subclasses of Control based on a data type (such as boolean, enumerated, or float). Boolean controls, for example, represent binary-state controls, such as on/off controls for mute or reverb. Float controls, on the other hand, are well suited to represent continuously variable controls, such as pan, balance, or volume.

The Java Sound API specifies the following abstract subclasses of Control:

  • BooleanControl— represents a binary-state (true or false) control. For example, mute, solo, and on/off switches would be good candidates for BooleanControls.

  • FloatControl — data model providing control over a range of floating-point values. For example, volume and pan are FloatControls that could be manipulated via a dial or slider.

  • EnumControl— offers a choice from a set of objects. For example, you might associate a set of buttons in the user interface with an EnumControl to select one of several preset reverberation settings.

  • CompoundControl—provides access to a collection of related items, each of which is itself an instance of a Control subclass. CompoundControls represent multi-control modules such as graphic equalizers. (A graphic equalizer would typically be depicted by a set of sliders, each affecting a FloatControl.)

Each subclass of Control above has methods appropriate for its underlying data type. Most of the classes include methods that set and get the control's current value(s), get the control's label(s), and so on.

Of course, each class has methods that are particular to it and the data model represented by the class. For example, EnumControl has a method that lets you get the set of its possible values, and FloatControl permits you to get its minimum and maximum values, as well as the precision (increment or step size) of the control.

Each subclass of Control has a corresponding Control.Type subclass, which includes static instances that identify specific controls.

The following table shows each Control subclass, its corresponding Control.Type subclass, and the static instances that indicate specific kinds of controls:

Control | Control.Type | Control.Type instances
BooleanControl BooleanControl.Type

MUTE

Mute status of line

APPLY_REVERB

Reverberation on/off

CompoundControl | CompoundControl.Type | (none)
EnumControl EnumControl.Type REVERB

Access to reverb settings (each is an instance of ReverbType)

FloatControl FloatControl.Type AUX_RETURN

Auxiliary return gain on a line

AUX_SEND

Auxiliary send gain on a line

BALANCE

Left-right volume balance

MASTER_GAIN

Overall gain on a line

PAN

Left-right position

REVERB_RETURN

Post-reverb gain on a line

REVERB_SEND

Pre-reverb gain on a line

SAMPLE_RATE

Playback sample rate

VOLUME

Volume on a line

An implementation of the Java Sound API can provide any or all of these control types on its mixers and lines. It can also supply additional control types not defined in the Java Sound API. Such control types could be implemented via concrete subclasses of any of these four abstract subclasses, or via additional Control subclasses that don't inherit from any of these four abstract subclasses. An application program can query each line to find what controls it supports.

Getting a Line that Has the Desired Controls

In many cases, an application program will simply display whatever controls happen to be supported by the line in question. If the line doesn't have any controls, so be it. But what if it's important to find a line that has certain controls? In that case, you can use a Line.Info to obtain a line that has the right characteristics, as previously described under Getting a Line of a Desired Type.

For example, suppose you prefer an input port that lets the user set the volume of the sound input. The following code excerpt shows how one might query the default mixer to determine whether it has the desired port and control:

Port lineIn;
FloatControl volCtrl;
try {
  mixer = AudioSystem.getMixer(null);
  lineIn = (Port)mixer.getLine(Port.Info.LINE_IN);
  lineIn.open();
  volCtrl = (FloatControl) lineIn.getControl(

      FloatControl.Type.VOLUME);

  // Assuming getControl call succeeds,
  // we now have our LINE_IN VOLUME control.
} catch (Exception e) {
  System.out.println("Failed trying to find LINE_IN"
    + " VOLUME control: exception = " + e);
}
if (volCtrl != null)
  // ...

Getting the Controls from the Line

An application program that needs to expose controls in its user interface might simply query the available lines and controls, and then display an appropriate user-interface element for every control on every line of interest. In such a case, the program's only mission is to provide the user with "handles" on the control; not to know what those controls do to the audio signal. As long as the program knows how to map a line's controls into user-interface elements, the Java Sound API architecture of Mixer, Line, and Control will generally take care of the rest.

For example, suppose your program plays back sound. You're using a SourceDataLine, which you've obtained as previously described under Getting a Line of a Desired Type. You can access the line's controls by invoking the following Line method:

Control[] getControls()
Then, for each of the controls in this returned array, you then use the following Control method to get the control's type:
Control.Type getType()
Knowing the specific Control.Type instance, your program can display a corresponding user-interface element. Of course, choosing "a corresponding user-interface element" for a specific Control.Type depends on the approach taken by your program. On the one hand, you might use the same kind of element to represent all Control.Type instances of the same class. This would require you to query the class of the Control.Type instance using, for example, the Object.getClass method. Let's say the result matched BooleanControl.Type. In this case, your program might display a generic checkbox or toggle button, but if its class matched FloatControl.Type, then you might display a graphic slider.

On the other hand, your program might distinguish between different types of controls—even those of the same class—and use a different user-interface element for each one. This would require you to test the instance returned by Control's getType method. Then if, for example, the type matched BooleanControl.Type.APPLY_REVERB, your program might display a checkbox; while if the type matched BooleanControl.Type.MUTE, you might instead display a toggle button.

Using a Control to Change the Audio Signal

Now that you know how to access a control and determine its type, this section will describe how to use Controls to change aspects of the audio signal. This section doesn't cover every available control; rather, it provides a few examples in this area to show you how to get started. These example include:

  • Controlling a line's mute state
  • Changing a line's volume
  • Selecting among various reverberation presets

Suppose that your program has accessed all of its mixers, their lines and the controls on those lines, and that it has a data structure to manage the logical associations between the controls and their corresponding user-interface elements. Then, translating the user's manipulations of those controls into the corresponding Control methods becomes a fairly straightforward matter.

The following subsections describe some of the methods that must be invoked to affect the changes to specific controls.

Controlling a Line's Mute State

Controlling the mute state of any line is simply a matter of calling the following BooleanControl method:

void setValue(boolean value)
(Presumably, the program knows, by referring to its control-management data structures, that the mute is an instance of a BooleanControl.) To mute the signal that's passing through the line, the program invokes the method above, specifying true as the value. To turn muting off, permitting the signal to flow through the line, the program invokes the method with the parameter set to false.

Changing a Line's Volume

Let's assume your program associates a particular graphic slider with a particular line's volume control. The value of a volume control (i.e., FloatControl.Type.VOLUME) is set using the following FloatControl method:

void setValue(float newValue)
Detecting that the user moved the slider, the program gets the slider's current value and passes it, as the parameter newValue, to the method above. This changes the volume of the signal flowing though the line that "owns" the control.

Selecting among Various Reverberation Presets

Let's suppose that our program has a mixer with a line that has a control of type EnumControl.Type.REVERB. Calling the EnumControl method:

java.lang.Objects[] getValues()
on that control produces an array of ReverbType objects. If desired, the particular parameter settings of each of these objects can be accessed using the following ReverbType methods:
int getDecayTime()
int getEarlyReflectionDelay()
float getEarlyReflectionIntensity()
int getLateReflectionDelay()
float getLateReflectionIntensity()
For example, if a program only wants a single reverb setting that sounds like a cavern, it can iterate over the ReverbType objects until it finds one for which getDecayTime returns a value greater than 2000. For a thorough explanation of these methods, including a table of representative return values, see the API reference documentation for javax.sound.sampled.ReverbType.

Typically, though, a program will create a user-interface element, for example, a radio button, for each of the ReverbType objects within the array returned by the getValues method. When the user clicks on one of these radio buttons, the program invokes the EnumControl method

void setValue(java.lang.Object value)
where value is set to the ReverbType that corresponds to the newly engaged button. The audio signal sent through the line that "owns" this EnumControl will then be reverberated according to the parameter settings that constitute the control's current ReverbType (i.e., the particular ReverbType specified in the value argument of the setValue method).

So, from our application program's perspective, enabling a user to move from one reverberation preset (i.e., ReverbType) to another is simply a matter of connecting each element of the array returned by getValues to a distinct radio button.

Manipulating the Audio Data Directly

The Control API allows an implementation of the Java Sound API, or a third-party provider of a mixer, to supply arbitrary sorts of signal processing through controls. But what if no mixer offers the kind of signal processing you need? It will take more work, but you might be able to implement the signal processing in your program. Because the Java Sound API gives you access to the audio data as an array of bytes, you can alter these bytes in any way you choose.

If you're processing incoming sound, you can read the bytes from a TargetDataLine and then manipulate them. An algorithmically trivial example that can yield sonically intriguing results is to play a sound backwards by arranging its frames in reverse order. This trivial example may not be of much use for your program, but there are numerous sophisticated digital signal processing (DSP) techniques that might be more appropriate. Some examples are equalization, dynamic-range compression, peak limiting, and time stretching or compression, as well as special effects such as delay, chorus, flanging, distortion, and so on.

To play back processed sound, you can place your manipulated array of bytes into a SourceDataLine or Clip. Of course, the array of bytes need not be derived from an existing sound. You can synthesize sounds from scratch, although this requires some knowledge of acoustics or else access to sound-synthesis functions. For either processing or synthesis, you may want to consult an audio DSP textbook for the algorithms in which you're interested, or else import a third-party library of signal-processing functions into your program. For playback of synthesized sound, consider whether the Synthesizer API in the javax.sound.midi package meets your needs instead. You'll learn about more about javax.sound.midi later under Synthesizing Sound.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Capturing Audio
Next page: Using Files and Format Converters


Using Files and Format Converters (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Using Files and Format Converters

Most application programs that deal with sound need to read sound files or audio streams. This is common functionality, regardless of what the program may subsequently do with the data it reads (such as play, mix, or process it). Similarly, many programs need to write sound files (or streams). In some cases, the data that has been read (or that will be written) needs to be converted to a different format.

As was briefly mentioned in Accessing Audio System Resources, the Java Sound API provides application developers with various facilities for file input/output and format translations. Application programs can read, write, and translate between a variety of sound file formats and audio data formats.

Overview of the Sampled Package introduced the main classes related to sound files and audio data formats. As a review:

  • A stream of audio data, as might be read from or written to a file, is represented by an AudioInputStream object. (AudioInputStream inherits from java.io.InputStream.)

  • The format of this audio data is represented by an AudioFormat object.

    This format specifies how the audio samples themselves are arranged, but not the structure of a file that they might be stored in. In other words, an AudioFormat describes "raw" audio data, such as the system might hand your program after capturing it from a microphone input or after parsing it from a sound file. An AudioFormat includes such information as the encoding, the byte order, the number of channels, the sampling rate, and the number of bits per sample.

  • There are several well-known, standard formats for sound files, such as WAV, AIFF, or AU. The different types of sound file have different structures for storing audio data as well as for storing descriptive information about the audio data. A sound file format is represented in the Java Sound API by an AudioFileFormat object. The AudioFileFormat includes an AudioFormat object to describe the format of the audio data stored in the file, and also includes information about the file type and the length of the data in the file.

  • The AudioSystem class provides methods for (1) storing a stream of audio data from an AudioInputStream into an audio file of a particular type (in other words, writing a file), (2) extracting a stream of audio bytes (an AudioInputStream) from an audio file (in other words, reading a file), and (3) converting audio data from one data format to another. This page, which is divided into three sections, explains these three kinds of activity.

Note: an implementation of the Java Sound API does not necessarily provide comprehensive facilities for reading, writing, and converting audio in different data and file formats. It might support only the most common data and file formats. However, service providers can develop and distribute conversion services that extend this set, as you'll later see in Providing Sampled-Audio Services. The AudioSystem class supplies methods that allow application programs to learn what conversions are available, as described later under Converting File and Data Formats.

Reading Sound Files

The AudioSystem class provides two types of file-reading services:

  • Information about the format of the audio data stored in the sound file
  • A stream of formatted audio data that can be read from the sound file

The first of these is given by three variants of the getAudioFileFormat method:
static AudioFileFormat getAudioFileFormat (java.io.File file)
static AudioFileFormat getAudioFileFormat(java.io.InputStream stream)
static AudioFileFormat getAudioFileFormat (java.net.URL url)

As mentioned above, the returned AudioFileFormat object tells you the file type, the length of the data in the file, encoding, the byte order, the number of channels, the sampling rate, and the number of bits per sample.

The second type of file-reading functionality is given by these AudioSystem methods

static AudioInputStream getAudioInputStream (java.io.File file)
static AudioInputStream getAudioInputStream (java.net.URL url)
static AudioInputStream getAudioInputStream (java.io.InputStream stream)

These methods give you an object (an AudioInputStream) that lets you read the file's audio data, using one of the read methods of AudioInputStream. We'll see an example momentarily.

Suppose you're writing a sound-editing application that allows the user to load sound data from a file, display a corresponding waveform or spectrogram, edit the sound, play back the edited data, and save the result in a new file. Or perhaps your program will read the data stored in a file, apply some kind of signal processing (such as an algorithm that slows the sound down without changing its pitch), and then play the processed audio. In either case, you need to get access to the data contained in the audio file. Assuming that your program provides some means for the user to select or specify an input sound file, reading that file's audio data involves three steps:

  1. Get an AudioInputStream object from the file.
  2. Create a byte array in which you'll store successive chunks of data from the file.
  3. Repeatedly read bytes from the audio input stream into the array. On each iteration, do something useful with the bytes in the array (for example, you might play them, filter them, analyze them, display them, or write them to another file).

The following code snippet outlines these steps:

int totalFramesRead = 0;
File fileIn = new File(somePathName);
// somePathName is a pre-existing string whose value was
// based on a user selection.
try {
  AudioInputStream audioInputStream =
    AudioSystem.getAudioInputStream(fileIn);
  int bytesPerFrame =
    audioInputStream.getFormat().getFrameSize();
    if (bytesPerFrame == AudioSystem.NOT_SPECIFIED) {
    // some audio formats may have unspecified frame size
    // in that case we may read any amount of bytes
    bytesPerFrame = 1;
  }
  // Set an arbitrary buffer size of 1024 frames.
  int numBytes = 1024 * bytesPerFrame;
  byte[] audioBytes = new byte[numBytes];
  try {
    int numBytesRead = 0;
    int numFramesRead = 0;
    // Try to read numBytes bytes from the file.
    while ((numBytesRead =
      audioInputStream.read(audioBytes)) != -1) {
      // Calculate the number of frames actually read.
      numFramesRead = numBytesRead / bytesPerFrame;
      totalFramesRead += numFramesRead;
      // Here, do something useful with the audio data that's
      // now in the audioBytes array...
    }
  } catch (Exception ex) {
    // Handle the error...
  }
} catch (Exception e) {
  // Handle the error...
}
Let's take a look at what's happening in the above code sample. First, the outer try clause instantiates an AudioInputStream object through the call to the AudioSystem.getAudioInputStream(File) method. This method transparently performs all of the testing required to determine whether the specified file is actually a sound file of a type that is supported by the Java Sound API. If the file being inspected (fileIn in this example) is not a sound file, or is a sound file of some unsupported type, an UnsupportedAudioFileException exception is thrown. This behavior is convenient, in that the application programmer need not be bothered with testing file attributes, nor with adhering to any file-naming conventions. Instead, the getAudioInputStream method takes care of all the low-level parsing and verification that is required to validate the input file.

The outer try clause then creates a byte array, audioBytes, of an arbitrary fixed length. We make sure that its length in bytes equals an integral number of frames, so that we won't end up reading only part of a frame or, even worse, only part of a sample. This byte array will serve as a buffer to temporarily hold a chunk of audio data as it's read from the stream. If we knew we would be reading nothing but very short sound files, we could make this array the same length as the data in the file, by deriving the length in bytes from the length in frames, as returned by AudioInputStream's getFrameLength method. (Actually, we'd probably just use a Clip object instead.) But to avoid running out of memory in the general case, we instead read the file in chunks, one buffer at a time.

The inner try clause contains a while loop, which is where we read the audio data from the AudioInputStream into the byte array. You should add code in this loop to handle the audio data in this array in whatever way is appropriate for your program's needs. If you're applying some kind of signal processing to the data, you'll probably need to query the AudioInputStream's AudioFormat further, to learn the number of bits per sample and so on.

Note that the method AudioInputStream.read(byte[]) returns the number of bytes read—not the number of samples or frames. This method returns -1 when there's no more data to read. Upon detecting this condition, we break from the while loop.

Writing Sound Files

The previous section described the basics of reading a sound file, using specific methods of the AudioSystem and AudioInputStream classes. This section describes how to write audio data out to a new file.

The following AudioSystem method creates a disk file of a specified file type. The file will contain the audio data that's in the specified AudioInputStream:

static int write(AudioInputStream in,
  AudioFileFormat.Type fileType, File out)
Note that the second argument must be one of the file types supported by the system (for example, AU, AIFF, or WAV), otherwise the write method will throw an IllegalArgumentException. To avoid this, you can test whether or not a particular AudioInputStream may be written to a particular type of file, by invoking this AudioSystem method:
static boolean isFileTypeSupported
  (AudioFileFormat.Type fileType, AudioInputStream stream)
which will return true only if the particular combination is supported.

More generally, you can learn what types of file the system can write by invoking one of these AudioSystem methods:

static AudioFileFormat.Type[] getAudioFileTypes()
static AudioFileFormat.Type[]
  getAudioFileTypes(AudioInputStream stream)
The first of these returns all the types of file that the system can write, and the second returns only those that the system can write from the given audio input stream.

The following excerpt demonstrates one technique for creating an output file from an AudioInputStream using the write method mentioned above.

File fileOut = new File(someNewPathName);
AudioFileFormat.Type fileType = fileFormat.getType();
if (AudioSystem.isFileTypeSupported(fileType,
    audioInputStream)) {
  AudioSystem.write(audioInputStream, fileType, fileOut);
}
The first statement above, creates a new File object, fileOut, with a user- or program-specified pathname. The second statement gets a file type from a pre-existing AudioFileFormat object called fileFormat, which might have been obtained from another sound file, such as the one that was read in Reading Sound Files above. (You could instead supply whatever supported file type you want, instead of getting the file type from elsewhere. For example, you might delete the second statement and replace the other two occurrences of fileType in the code above with AudioFileFormat.Type.WAVE.)

The third statement tests whether a file of the designated type can be written from a desired AudioInputStream. Like the file format, this stream might have been derived from the sound file previously read. (If so, presumably you've processed or altered its data in some way, because otherwise there are easier ways to simply copy a file.) Or perhaps the stream contains bytes that have been freshly captured from the microphone input.

Finally, the stream, file type, and output file are passed to the AudioSystem.write method, to accomplish the goal of writing the file.

Converting File and Data Formats

Recall from What is Formatted Audio Data?, that the Java Sound API distinguishes between audio file formats and audio data formats. The two are more or less independent. Roughly speaking, the data format refers to the way in which the computer represents each raw data point (sample), while the file format refers to the organization of a sound file as stored on a disk. Each sound file format has a particular structure that defines, for example, the information stored in the file's header. In some cases, the file format also includes structures that contain some form of meta-data, in addition to the actual "raw" audio samples. The remainder of this page examines methods of the Java Sound API that enable a variety of file-format and data-format conversions.

Converting from One File Format to Another

This section covers the fundamentals of converting audio file types in the Java Sound API. Once again we pose a hypothetical program whose purpose, this time, is to read audio data from an arbitrary input file and write it into a file whose type is AIFF. Of course, the input file must be of a type that the system is capable of reading, and the output file must be of a type that the system is capable of writing. (In this example, we assume that the system is capable of writing AIFF files.) The example program doesn't do any data format conversion. If the input file's data format can't be represented as an AIFF file, the program simply notifies the user of that problem. On the other hand, if the input sound file is an already an AIFF file, the program notifies the user that there is no need to convert it.

The following function implements the logic just described:

public void ConvertFileToAIFF(String inputPath,
  String outputPath) {
  AudioFileFormat inFileFormat;
  File inFile;
  File outFile;
  try {
    inFile = new File(inputPath);
    outFile = new File(outputPath);
  } catch (NullPointerException ex) {
    System.out.println("Error: one of the
      ConvertFileToAIFF" +" parameters is null!");
    return;
  }
  try {
    // query file type
    inFileFormat = AudioSystem.getAudioFileFormat(inFile);
    if (inFileFormat.getType() != AudioFileFormat.Type.AIFF)
    {
      // inFile is not AIFF, so let's try to convert it.
      AudioInputStream inFileAIS =
        AudioSystem.getAudioInputStream(inFile);
      inFileAIS.reset(); // rewind
      if (AudioSystem.isFileTypeSupported(
             AudioFileFormat.Type.AIFF, inFileAIS)) {
         // inFileAIS can be converted to AIFF.
         // so write the AudioInputStream to the
         // output file.
         AudioSystem.write(inFileAIS,
           AudioFileFormat.Type.AIFF, outFile);
         System.out.println("Successfully made AIFF file, "
           + outFile.getPath() + ", from "
           + inFileFormat.getType() + " file, " +
           inFile.getPath() + ".");
         inFileAIS.close();
         return; // All done now
       } else
         System.out.println("Warning: AIFF conversion of "
           + inFile.getPath()
           + " is not currently supported by AudioSystem.");
    } else
      System.out.println("Input file " + inFile.getPath() +
          " is AIFF." + " Conversion is unnecessary.");
  } catch (UnsupportedAudioFileException e) {
    System.out.println("Error: " + inFile.getPath()
        + " is not a supported audio file type!");
    return;
  } catch (IOException e) {
    System.out.println("Error: failure attempting to read "
      + inFile.getPath() + "!");
    return;
  }
}

As mentioned, the purpose of this example function, ConvertFileToAIFF, is to query an input file to determine whether it's an AIFF sound file, and if it isn't, to try to convert it to one, producing a new copy whose pathname is specified by the second argument. (As an exercise, you might try making this function more general, so that instead of always converting to AIFF, the function converts to the file type specified by a new function argument.) Note that the audio data format of the copy—that is, the new file-mimics the audio data format of original input file.

Most of this function is self-explanatory and is not specific to the Java Sound API. There are, however, a few Java Sound API methods used by the routine that are crucial for sound file-type conversions. These method invocations are all found in the second try clause, above, and include the following:

  • AudioSystem.getAudioFileFormat: used here to determine whether the input file is already an AIFF type. If so, the function quickly returns; otherwise the conversion attempt proceeds.

  • AudioSystem.isFileTypeSupported: Indicates whether the system can write a file of the specified type that contains audio data from the specified AudioInputStream. In our example, this method returns true if the specified audio input file can be converted to AIFF audio file format. If AudioFileFormat.Type.AIFF isn't supported, ConvertFileToAIFF issues a warning that the input file can't be converted, then returns.

  • AudioSystem.write: used here to write the audio data from the AudioInputStream inFileAIS to the output file outFile.

The second of these methods, isFileTypeSupported, helps to determine, in advance of the write, whether a particular input sound file can be converted to a particular output sound file type. In the next section we will see how, with a few modifications to this ConvertFileToAIFF sample routine, we can convert the audio data format, as well as the sound file type.

Converting Audio between Different Data Formats

The previous section showed how to use the Java Sound API to convert a file from one file format (that is, one type of sound file) to another. This section explores some of the methods that enable audio data format conversions.

In the previous section, we read data from a file of an arbitrary type, and saved it in an AIFF file. Note that although we changed the type of file used to store the data, we didn't change the format of the audio data itself. (Most common audio file types, including AIFF, can contain audio data of various formats.) So if the original file contained CD-quality audio data (16-bit sample size, 44.1-kHz sample rate, and two channels), so would our output AIFF file.

Now suppose that we want to specify the data format of the output file, as well as the file type. For example, perhaps we are saving many long files for use on the Internet, and are concerned about the amount of disk space and download time required by our files. We might choose to create smaller AIFF files that contain lower-resolution data-for example, data that has an 8-bit sample size, an 8-kHz sample rate, and a single channel.

Without going into as much coding detail as before, let's explore some of the methods used for data format conversion, and consider the modifications that we would need to make to the ConvertFileToAIFF function to accomplish the new goal.

The principal method for audio data conversion is, once again, found in the AudioSystem class. This method is a variant of getAudioInputStream:

AudioInputStream getAudioInputStream(AudioFormat
    format, AudioInputStream stream)
This function returns an AudioInputStream that is the result of converting the AudioInputStream, stream, using the indicated AudioFormat, format. If the conversion isn't supported by AudioSystem, this function throws an IllegalArgumentException.

To avoid that, we can first check whether the system can perform the required conversion by invoking this AudioSystem method:

boolean isConversionSupported(AudioFormat targetFormat,
    AudioFormat sourceFormat)
In this case, we'd pass stream.getFormat() as the second argument.

To create a specific AudioFormat object, we use one of the two AudioFormat constructors shown below, either:

AudioFormat(float sampleRate, int sampleSizeInBits,
    int channels, boolean signed, boolean bigEndian)
which constructs an AudioFormat with a linear PCM encoding and the given parameters, or:
AudioFormat(AudioFormat.Encoding encoding,
    float sampleRate, int sampleSizeInBits, int channels,
    int frameSize, float frameRate, boolean bigEndian)
which also constructs an AudioFormat, but lets you specify the encoding, frame size, and frame rate, in addition to the other parameters.

Now, armed with the methods above, let's see how we might extend our ConvertFileToAIFF function to perform the desired "low-res" audio data format conversion. First, we would construct an AudioFormat object describing the desired output audio data format. The following statement would suffice and could be inserted near the top of the function:

AudioFormat outDataFormat = new AudioFormat((float) 8000.0,
(int) 8, (int) 1, true, false);
Since the AudioFormat constructor above is describing a format with 8-bit samples, the last parameter to the constructor, which specifies whether the samples are big or little endian, is irrelevant. (Big versus little endian is only an issue if the sample size is greater than a single byte.)

The following example shows how we would use this new AudioFormat to convert the AudioInputStream, inFileAIS, that we created from the input file:

AudioInputStream lowResAIS;
  if (AudioSystem.isConversionSupported(outDataFormat,
    inFileAIS.getFormat())) {
    lowResAIS = AudioSystem.getAudioInputStream
      (outDataFormat, inFileAIS);
  }
It wouldn't matter too much where we inserted this code, as long as it was after the construction of inFileAIS. Without the isConversionSupported test, the call would fail and throw an IllegalArgumentException if the particular conversion being requested was unsupported. (In this case, control would transfer to the appropriate catch clause in our function.)

So by this point in the process, we would have produced a new AudioInputStream, resulting from the conversion of the original input file (in its AudioInputStream form) to the desired low-resolution audio data format as defined by outDataFormat.

The final step to produce the desired low-resolution, AIFF sound file would be to replace the AudioInputStream parameter in the call to AudioSystem.write (that is, the first parameter) with our converted stream, lowResAIS, as follows:

AudioSystem.write(lowResAIS, AudioFileFormat.Type.AIFF,
  outFile);
These few modifications to our earlier function produce something that converts both the audio data and the file format of any specified input file, assuming of course that the system supports the conversion.

Learning What Conversions Are Available

Several AudioSystem methods test their parameters to determine whether the system supports a particular data format conversion or file-writing operation. (Typically, each method is paired with another that performs the data conversion or writes the file.) One of these query methods, AudioSystem.isFileTypeSupported, was used in our example function, ConvertFileToAIFF, to determine whether the system was capable of writing the audio data to an AIFF file. A related AudioSystem method, getAudioFileTypes(AudioInputStream), returns the complete list of supported file types for the given stream, as an array of AudioFileFormat.Type instances. The method:

boolean isConversionSupported(AudioFormat.Encoding encoding,
                              AudioFormat format)
is used to determine whether an audio input stream of the specified encoding can be obtained from an audio input stream that has the specified audio format. Similarly, the method:
boolean isConversionSupported(AudioFormat newFormat,
                              AudioFormat oldFormat)

tells us whether an AudioInputStream with the specified audio format, newFormat, can be obtained through the conversion of an AudioInputStream that has the audio format oldFormat. (This method was invoked in the previous section's code excerpt that created a low-resolution audio input stream, lowResAIS.)

These format-related queries help prevent errors when attempting to perform format conversions with the Java Sound API.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Processing Audio with Controls
Next page: Overview of the MIDI Package


Overview of the MIDI Package (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Overview of the MIDI Package

The introduction gave a glimpse into the MIDI capabilities of the Java Sound API. The discussion that follows provides a more detailed introduction to the Java Sound API's MIDI architecture, which is accessed through the javax.sound.midi package. Some basic features of MIDI itself are explained, as a refresher or introduction, to place the Java Sound API's MIDI features in context. It then goes on to discuss the Java Sound API's approach to MIDI, as a preparation for the programming tasks that are explained in subsequent sections. The following discussion of the MIDI API is divided into two main areas: data and devices.

A MIDI Refresher: Wires and Files

The Musical Instrument Digital Interface (MIDI) standard defines a communication protocol for electronic music devices, such as electronic keyboard instruments and personal computers. MIDI data can be transmitted over special cables during a live performance, and can also be stored in a standard type of file for later playback or editing.

This section reviews some MIDI basics, without reference to the Java Sound API. The discussion is intended as a refresher for readers acquainted with MIDI, and as a brief introduction for those who are not, to provide background for the subsequent discussion of the Java Sound API's MIDI package. If you have a thorough understanding of MIDI, you can safely skip this section. Before writing substantial MIDI applications, programmers who are unfamiliar with MIDI will probably need a fuller description of MIDI than can be included in this tutorial. See the Complete MIDI 1.0 Detailed Specification, which is available only in hard copy from http://www.midi.org (although you might find paraphrased or summarized versions on the Web).

MIDI is both a hardware specification and a software specification. To understand MIDI's design, it helps to understand its history. MIDI was originally designed for passing musical events, such as key depressions, between electronic keyboard instruments such as synthesizers. Hardware devices known as sequencers stored sequences of notes that could control a synthesizer, allowing musical performances to be recorded and subsequently played back. Later, hardware interfaces were developed that connected MIDI instruments to a computer's serial port, allowing sequencers to be implemented in software. More recently, computer sound cards have incorporated hardware for MIDI I/O and for synthesizing musical sound. Today, many users of MIDI deal only with sound cards, never connecting to external MIDI devices. CPUs have become fast enough that synthesizers, too, can be implemented in software. A sound card is needed only for audio I/O and, in some applications, for communicating with external MIDI devices.

The brief hardware portion of the MIDI specification prescribes the pinouts for MIDI cables and the jacks into which these cables are plugged. This portion need not concern us. Because devices that originally required hardware, such as sequencers and synthesizers, are now implementable in software, perhaps the only reason for most programmers to know anything about MIDI hardware devices is simply to understand the metaphors in MIDI. However, external MIDI hardware devices are still essential for some important music applications, and so the Java Sound API supports input and output of MIDI data.

The software portion of the MIDI specification is extensive. This portion concerns the structure of MIDI data and how devices such as synthesizers should respond to that data. It is important to understand that MIDI data can be streamed or sequenced. This duality reflects two different parts of the Complete MIDI 1.0 Detailed Specification:

  • MIDI 1.0
  • Standard MIDI Files

We'll explain what's meant by streaming and sequencing by examining the purpose of each of these two parts of the MIDI specification.

Streaming Data in the MIDI Wire Protocol

The first of these two parts of the MIDI specification describes what is known informally as "MIDI wire protocol." MIDI wire protocol, which is the original MIDI protocol, is based on the assumption that the MIDI data is being sent over a MIDI cable (the "wire"). The cable transmits digital data from one MIDI device to another. Each of the MIDI devices might be a musical instrument or a similar device, or it might be a general-purpose computer equipped with a MIDI-capable sound card or a MIDI-to-serial-port interface.

MIDI data, as defined by MIDI wire protocol, is organized into messages. The different kinds of message are distinguished by the first byte in the message, known as the status byte. (Status bytes are the only bytes that have the highest-order bit set to 1.) The bytes that follow the status byte in a message are known as data bytes. Certain MIDI messages, known as channel messages, have a status byte that contains four bits to specify the kind of channel message and another four bits to specify the channel number. There are therefore 16 MIDI channels; devices that receive MIDI messages can be set to respond to channel messages on all or only one of these virtual channels. Often each MIDI channel (which shouldn't be confused with a channel of audio) is used to send the notes for a different instrument. As an example, two common channel messages are Note On and Note Off, which start a note sounding and then stop it, respectively. These two messages each take two data bytes: the first specifies the note's pitch and the second its "velocity" (how fast the key is depressed or released, assuming a keyboard instrument is playing the note).

MIDI wire protocol defines a streaming model for MIDI data. A central feature of this protocol is that the bytes of MIDI data are delivered in real time—in other words, they are streamed. The data itself contains no timing information; each event is processed as it's received, and it's assumed that it arrives at the correct time. That model is fine if the notes are being generated by a live musician, but it's insufficient if you want to store the notes for later playback, or if you want to compose them out of real time. This limitation is understandable when you realize that MIDI was originally designed for musical performance, as a way for a keyboard musician to control more than one synthesizer, back in the days before many musicians used computers. (The first version of the specification was released in 1984.)

Sequenced Data in Standard MIDI Files

The Standard MIDI Files part of the MIDI specification addresses the timing limitation in MIDI wire protocol. A standard MIDI file is a digital file that contains MIDI events. An event is simply a MIDI message, as defined in the MIDI wire protocol, but with an additional piece of information that specifies the event's timing. (There are also some events that don't correspond to MIDI wire protocol messages, as we'll see in the next section.) The additional timing information is a series of bytes that indicates when to perform the operation described by the message. In other words, a standard MIDI file specifies not just which notes to play, but exactly when to play each of them. It's a bit like a musical score.

The information in a standard MIDI file is referred to as a sequence. A standard MIDI file contains one or more tracks. Each track typically contains the notes that a single instrument would play if the music were performed by live musicians. A sequencer is a software or hardware device that can read a sequence and deliver the MIDI messages contained in it at the right time. A sequencer is a bit like an orchestra conductor: it has the information for all the notes, including their timings, and it tells some other entity when to perform the notes.

The Java Sound API's Representation of MIDI Data

Now that we've sketched the MIDI specification's approach to streamed and sequenced musical data, let's examine how the Java Sound API represents that data.

MIDI Messages

MidiMessage is an abstract class that represents a "raw" MIDI message. A "raw" MIDI message is usually a message defined by the MIDI wire protocol. It can also be one of the events defined by the Standard MIDI Files specification, but without the event's timing information. There are three categories of raw MIDI message, represented in the Java Sound API by these three respective MidiMessage subclasses:

  • ShortMessages are the most common messages and have at most two data bytes following the status byte. The channel messages, such as Note On and Note Off, are all short messages, as are some other messages.
  • SysexMessages contain system-exclusive MIDI messages. They may have many bytes, and generally contain manufacturer-specific instructions.
  • MetaMessages occur in MIDI files, but not in MIDI wire protocol. Meta messages contain data, such as lyrics or tempo settings, that might be useful to sequencers but that are usually meaningless for synthesizers.

MIDI Events

As we've seen, standard MIDI files contain events that are wrappers for "raw" MIDI messages along with timing information. An instance of the Java Sound API's MidiEvent class represents an event such as might be stored in a standard MIDI file.

The API for MidiEvent includes methods to set and get the event's timing value. There's also a method to retrieve its embedded raw MIDI message, which is an instance of a subclass of MidiMessage, discussed next. (The embedded raw MIDI message can be set only when constructing the MidiEvent.)

Sequences and Tracks

As mentioned earlier, a standard MIDI file stores events that are arranged into tracks. Usually the file represents one musical composition, and usually each track represents a part such as might have been played by a single instrumentalist. Each note that the instrumentalist plays is represented by at least two events: a Note On that starts the note, and a Note Off that ends it. The track may also contain events that don't correspond to notes, such as meta-events (which were mentioned above).

The Java Sound API organizes MIDI data in a three-part hierarchy:

  • Sequence
  • Track
  • MidiEvent

A Track is a collection of MidiEvents, and a Sequence is a collection of Tracks. This hierarchy reflects the files, tracks, and events of the Standard MIDI Files specification. (Note: this is a hierarchy in terms of containment and ownership; it's not a class hierarchy in terms of inheritance. Each of these three classes inherits directly from java.lang.Object.)

Sequences can be read from MIDI files, or created from scratch and edited by adding Tracks to the Sequence (or removing them). Similarly, MidiEvents can be added to or removed from the tracks in the sequence.

The Java Sound API's Representation of MIDI Devices

The previous section explained how MIDI messages are represented in the Java Sound API. However, MIDI messages don't exist in a vacuum. They're typically sent from one device to another. A program that uses the Java Sound API can generate MIDI messages from scratch, but more often the messages are instead created by a software device, such as a sequencer, or received from outside the computer through a MIDI input port. Such a device usually sends these messages to another device, such as a synthesizer or a MIDI output port.

The MidiDevice Interface

In the world of external MIDI hardware devices, many devices can transmit MIDI messages to other devices and also receive messages from other devices. Similarly, in the Java Sound API, software objects that implement the MidiDevice interface can transmit and receive messages. Such an object can be implemented purely in software, or it can serve as an interface to hardware such as a sound card's MIDI capabilities. The base MidiDevice interface provides all the functionality generally required by a MIDI input or output port. Synthesizers and sequencers, however, further implement one of the subinterfaces of MidiDevice: Synthesizer or Sequencer , respectively.

The MidiDevice interface includes an API for opening and closing a device. It also includes an inner class called MidiDevice.Info that provides textual descriptions of the device, including its name, vendor, and version. If you've read the sampled-audio portion of this tutorial, this API will probably sound familiar, because its design is similar to that of the javax.sampled.Mixer interface, which represents an audio device and which has an analogous inner class, Mixer.Info.

Transmitters and Receivers

Most MIDI devices are capable of sending MidiMessages, receiving them, or both. The way a device sends data is via one or more transmitter objects that it "owns." Similarly, the way a device receives data is via one or more of its receiver objects. The transmitter objects implement the Transmitter interface, and the receivers implement the Receiver interface.

Each transmitter can be connected to only one receiver at a time, and vice versa. A device that sends its MIDI messages to multiple other devices simultaneously does so by having multiple transmitters, each connected to a receiver of a different device. Similarly, a device that can receive MIDI messages from more than one source at a time must do so via multiple receivers.

Sequencers

A sequencer is a device for capturing and playing back sequences of MIDI events. It has transmitters, because it typically sends the MIDI messages stored in the sequence to another device, such as a synthesizer or MIDI output port. It also has receivers, because it can capture MIDI messages and store them in a sequence. To its superinterface, MidiDevice, Sequencer adds methods for basic MIDI sequencing operations. A sequencer can load a sequence from a MIDI file, query and set the sequence's tempo, and synchronize other devices to it. An application program can register an object to be notified when the sequencer processes certain kinds of events.

Synthesizers

A Synthesizer is a device for generating sound. It's the only object in the javax.sound.midi package that produces audio data. A synthesizer device controls a set of MIDI channel objects — typically 16 of them, since the MIDI specification calls for 16 MIDI channels. These MIDI channel objects are instances of a class that implements the MidiChannel interface, whose methods represent the MIDI specification's "channel voice messages" and "channel mode messages."

An application program can generate sound by directly invoking methods of a synthesizer's MIDI channel objects. More commonly, though, a synthesizer generates sound in response to messages sent to one or more of its receivers. These messages might be sent by a sequencer or MIDI input port, for example. The synthesizer parses each message that its receivers get, and usually dispatches a corresponding command (such as noteOn or controlChange) to one of its MidiChannel objects, according to the MIDI channel number specified in the event.

The MidiChannel uses the note information in these messages to synthesize music. For example, a noteOn message specifies the note's pitch and "velocity" (volume). However, the note information is insufficient; the synthesizer also requires precise instructions on how to create the audio signal for each note. These instructions are represented by an Instrument. Each Instrument typically emulates a different real-world musical instrument or sound effect. The Instruments might come as presets with the synthesizer, or they might be loaded from soundbank files. In the synthesizer, the Instruments are arranged by bank number (these can be thought of as rows) and program number (columns).

This section has provided a background for understanding MIDI data, and it has introduced some of the important interfaces and classes related to MIDI in the Java Sound API. Subsequent sections show how you can access and use these objects in your application programs.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Files and Format Converters
Next page: Accessing MIDI System Resources


Accessing MIDI System Resources (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Accessing MIDI System Resources
The Java Sound API offers a flexible model for MIDI system configuration, just as it does for configuration of the sampled-audio system. An implementation of the Java Sound API can itself provide different sorts of MIDI devices, and additional ones can be supplied by service providers and installed by users. You can write your program in such a way that it makes few assumptions about which specific MIDI devices are installed on the computer. Instead, the program can take advantage of the MIDI system's defaults, or it can allow the user to select from whatever devices happen to be available.

This section shows how your program can learn what MIDI resources have been installed, and how to get access to the desired ones. After you've accessed and opened the devices, you can connect them to each other, as discussed later in Transmitting and Receiving MIDI Messages.

The MidiSystem Class

The role of the MidiSystem class in the Java Sound API's MIDI package is directly analogous to the role of AudioSystem in the sampled-audio package. MidiSystem acts as a clearinghouse for accessing the installed MIDI resources.

You can query the MidiSystem to learn what sorts of devices are installed, and then you can iterate over the available devices and obtain access to the desired ones. For example, an application program might start out by asking the MidiSystem what synthesizers are available, and then display a list of them, from which the user can select one. A simpler application program might just use the system's default synthesizer.

The MidiSystem class also provides methods for translating between MIDI files and Sequences. It can report the file format of a MIDI file and can write files of different types.

An application program can obtain the following resources from the MidiSystem:

  • Sequencers
  • Synthesizers
  • Transmitters (such as those associated with MIDI input ports)
  • Receivers (such as those associated with MIDI output ports)
  • Data from standard MIDI files
  • Data from soundbank files

This page focuses on the first four of these types of resource. The others are discussed later in this tutorial.

Obtaining Default Devices

A typical MIDI application program that uses the Java Sound API begins by obtaining the devices it needs, which can consist of one or more sequencers, synthesizers, input ports, or output ports.

There is a default synthesizer device, a default sequencer device, a default transmitting device, and a default receiving device. The latter two devices normally represent the MIDI input and output ports, respectively, if there are any available on the system. (It's easy to get confused about the directionality here. Think of the ports' transmission or reception in relation to the software, not in relation to any external physical devices connected to the physical ports. A MIDI input port transmits data from an external device to a Java Sound API Receiver, and likewise a MIDI output port receives data from a software object and relays the data to an external device.)

A simple application program might just use the default instead of exploring all the installed devices. The MidiSystem class includes the following methods for retrieving default resources:

    static Sequencer getSequencer()
    static Synthesizer getSynthesizer()
    static Receiver getReceiver()
    static Transmitter getTransmitter()

The first two of these methods obtain the system's default sequencing and synthesis resources, which either represent physical devices or are implemented wholly in software. The getReceiver method obtains a Receiver object that takes MIDI messages sent to it and relays them to the default receiving device. Similarly, the getTransmitter method obtains a Transmitter object that can send MIDI messages to some receiver on behalf of the default transmitting device.

Learning What Devices Are Installed

Instead of using the default devices, a more thorough approach is to select the desired devices from the full set of devices that are installed on the system. An application program can select the desired devices programmatically, or it can display a list of available devices and let the user select which ones to use. The MidiSystem class provides a method for learning which devices are installed, and a corresponding method to obtain a device of a given type.

Here is the method for learning about the installed devices:

    static MidiDevice.Info[] getMidiDeviceInfo()

As you can see, it returns an array of information objects. Each of these returned MidiDevice.Info objects identifies one type of sequencer, synthesizer, port, or other device that is installed. (Usually a system has at most one instance of a given type. For example, a given model of synthesizer from a certain vendor will be installed only once. ) The MidiDevice.Info includes the following strings to describe the device:

  • Name
  • Version number
  • Vendor (the company that created the device)
  • A description of the device

You can display these strings in your user interface to let the user select from the list of devices.

However, to use the strings programmatically to select a device (as opposed to displaying the strings to the user), you need to know in advance what they might be. The company that provides each device should include this information in its documentation. An application program that requires or prefers a particular device can use this information to locate that device. This approach has the drawback of limiting the program to device implementations that it knows about in advance.

Another, more general, approach is to go ahead and iterate over the MidiDevice.Info objects, obtaining each corresponding device, and determining programmatically whether it's suitable to use (or at least suitable to include in a list from which the user can choose). The next section describes how to do this.

Obtaining a Desired Device

Once an appropriate device's info object is found, the application program invokes the following MidiSystem method to obtain the corresponding device itself:

    static MidiDevice getMidiDevice(MidiDevice.Info info)

You can use this method if you've already found the info object describing the device you need. However, if you can't interpret the info objects returned by getMidiDeviceInfo to determine which device you need, and if you don't want to display information about all the devices to the user, you might be able to do the following instead: Iterate over all the MidiDevice.Info objects returned by getMidiDeviceInfo, get the corresponding devices using the method above, and test each device to see whether it's suitable. In other words, you can query each device for its class and its capabilities before including it in the list that you display to the user, or as a way to decide upon a device programmatically without involving the user. For example, if your program needs a synthesizer, you can obtain each of the installed devices, see which are instances of classes that implement the Synthesizer interface, and then display them in a list from which the user can choose one, as follows:

// Obtain information about all the installed synthesizers.
Vector synthInfos;
MidiDevice device;
MidiDevice.Info[] infos = MidiSystem.getMidiDeviceInfo();
for (int i = 0; i < infos.length; i++) {
    try {
        device = MidiSystem.getMidiDevice(infos[i]);
    } catch (MidiUnavailableException e) {
          // Handle or throw exception...
    }
    if (device instanceof Synthesizer) {
        synthInfos.add(infos[i]);
    }
}
// Now, display strings from synthInfos list in GUI.

As another example, you might choose a device programmatically, without involving the user. Let's suppose you want to obtain the synthesizer that can play the most notes simultaneously. You iterate over all the MidiDevice.Info objects, as above, but after determining that a device is a synthesizer, you query its capabilities by invoking the getMaxPolyphony method of Synthesizer. You reserve the synthesizer that has the greatest polyphony, as described in the next section. Even though you're not asking the user to choose a synthesizer, you might still display strings from the chosen MidiDevice.Info object, just for the user's information.

Opening Devices

The previous section showed how to get an installed device. However, a device might be installed but unavailable. For example, another application program might have exclusive use of it. To actually reserve a device for your program, you need to use the MidiDevice method open:

if (!(device.isOpen())) {
    try {
      device.open();
  } catch (MidiUnavailableException e) {
          // Handle or throw exception...
  }
}

Once you've accessed a device and reserved it by opening it, you'll probably want to connect it to one or more other devices to let MIDI data flow between them. This procedure is described in later in Transmitting and Receiving MIDI Messages.

When done with a device, you release it for other programs' use by invoking the close method of MidiDevice.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Overview of the MIDI Package
Next page: Transmitting and Receiving MIDI Messages


Transmitting and Receiving MIDI Messages (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Transmitting and Receiving MIDI Messages

Understanding Devices, Transmitters, and Receivers

The Java Sound API specifies a message-routing architecture for MIDI data that's flexible and easy to use, once you understand how it works. The system is based on a module-connection design: distinct modules, each of which performs a specific task, can be interconnected (networked), enabling data to flow from one module to another.

The base module in the Java Sound API's messaging system is the MidiDevice interface. MidiDevices include sequencers (which record, play, load, and edit sequences of time-stamped MIDI messages), synthesizers (which generate sounds when triggered by MIDI messages), and MIDI input and output ports, through which data comes from and goes to external MIDI devices. The functionality typically required of MIDI ports is described by the base MidiDevice interface. The Sequencer and Synthesizer interfaces extend the MidiDevice interface to describe the additional functionality characteristic of MIDI sequencers and synthesizers, respectively. Concrete classes that function as sequencers or synthesizers should implement these interfaces.

A MidiDevice typically owns one or more ancillary objects that implement the Receiver or Transmitter interfaces. These interfaces represent the "plugs" or "portals" that connect devices together, permitting data to flow into and out of them. By connecting a Transmitter of one MidiDevice to a Receiver of another, you can create a network of modules in which data flows from one to another.

The MidiDevice interface includes methods for determining how many transmitter and receiver objects the device can support concurrently, and other methods for accessing those objects. A MIDI output port normally has at least one Receiver through which the outgoing messages may be received; similarly, a synthesizer normally responds to messages sent to its Receiver or Receivers. A MIDI input port normally has at least one Transmitter, which propagates the incoming messages. A full-featured sequencer supports both Receivers, which receive messages during recording, and Transmitters, which send messages during playback.

The Transmitter interface includes methods for setting and querying the receivers to which the transmitter sends its MidiMessages. Setting the receiver establishes the connection between the two. The Receiver interface contains a method that sends a MidiMessage to the receiver. Typically, this method is invoked by a Transmitter. Both the Transmitter and Receiver interfaces include a close method that frees up a previously connected transmitter or receiver, making it available for a different connection.

We'll now examine how to use transmitters and receivers. Before getting to the typical case of connecting two devices (such as hooking a sequencer to a synthesizer), we'll examine the simpler case where you send a MIDI message directly from your application program to a device. Studying this simple scenario should make it easier to understand how the Java Sound API arranges for sending MIDI messages between two devices.

Sending a Message to a Receiver without Using a Transmitter

Let's say you want to create a MIDI message from scratch and then send it to some receiver. You can create a new, blank ShortMessage and then fill it with MIDI data using the following ShortMessage method:

void setMessage(int command, int channel, int data1,
         int data2)

Once you have a message ready to send, you can send it to a Receiver object, using this Receiver method:

void send(MidiMessage message, long timeStamp)

The time-stamp argument will be explained momentarily. For now, we'll just mention that its value can be set to -1 if you don't care about specifying a precise time. In this case, the device receiving the message will try to respond to the message as soon as possible.

An application program can obtain a receiver for a MidiDevice by invoking the device's getReceiver method. If the device can't provide a receiver to the program (typically because all the device's receivers are already in use), a MidiUnavailableException is thrown. Otherwise, the receiver returned from this method is available for immediate use by the program. When the program has finished using the receiver, it should call the receiver's close method. If the program attempts to invoke methods on a receiver after calling close, an IllegalStateException may be thrown.

As a concrete simple example of sending a message without using a transmitter, let's send a Note On message to the default receiver, which is typically associated with a device such as the MIDI output port or a synthesizer. We do this by creating a suitable ShortMessage and passing it as an argument to Receiver's send method:

  ShortMessage myMsg = new ShortMessage();
  // Start playing the note Middle C (60),
  // moderately loud (velocity = 93).
  myMsg.setMessage(ShortMessage.NOTE_ON, 0, 60, 93);
  long timeStamp = -1;
  Receiver	 rcvr = MidiSystem.getReceiver();
  rcvr.send(myMsg, timeStamp);

This code uses a static integer field of ShortMessage, namely, NOTE_ON, for use as the MIDI message's status byte. The other parts of the MIDI message are given explicit numeric values as arguments to the setMessage method. The zero indicates that the note is to be played using MIDI channel number 1; the 60 indicates the note Middle C; and the 93 is an arbitrary key-down velocity value, which typically indicates that the synthesizer that eventually plays the note should play it somewhat loudly. (The MIDI specification leaves the exact interpretation of velocity up to the synthesizer's implementation of its current instrument.) This MIDI message is then sent to the receiver with a time stamp of -1. We now need to examine exactly what the time stamp parameter means, which is the subject of the next section.

Understanding Time Stamps

As you already know, the MIDI specification has different parts. One part describes MIDI "wire" protocol (messages sent between devices in real time), and another part describes Standard MIDI Files (messages stored as events in "sequences"). In the latter part of the specification, each event stored in a standard MIDI file is tagged with a timing value that indicates when that event should be played. By contrast, messages in MIDI wire protocol are always supposed to be processed immediately, as soon as they're received by a device, so they have no accompanying timing values.

The Java Sound API adds an additional twist. It comes as no surprise that timing values are present in the MidiEvent objects that are stored in sequences (as might be read from a MIDI file), just as in the Standard MIDI Files specification. But in the Java Sound API, even the messages sent between devices—in other words, the messages that correspond to MIDI wire protocol—can be given timing values, known as time stamps. It is these time stamps that concern us here.

Time Stamps on Messages Sent to Devices

The time stamp that can optionally accompany messages sent between devices in the Java Sound API is quite different from the timing values in a standard MIDI file. The timing values in a MIDI file are often based on musical concepts such as beats and tempo, and each event's timing measures the time elapsed since the previous event. In contrast, the time stamp on a message sent to a device's Receiver object always measures absolute time in microseconds. Specifically, it measures the number of microseconds elapsed since the device that owns the receiver was opened.

This kind of time stamp is designed to help compensate for latencies introduced by the operating system or by the application program. It's important to realize that these time stamps are used for minor adjustments to timing, not to implement complex queues that can schedule events at completely arbitrary times (as MidiEvent timing values do).

The time stamp on a message sent to a device (through a Receiver) can provide precise timing information to the device. The device might use this information when it processes the message. For example, it might adjust the event's timing by a few milliseconds to match the information in the time stamp. On the other hand, not all devices support time stamps, so the device might completely ignore the message's time stamp.

Even if a device supports time stamps, it might not schedule the event for exactly the time that you requested. You can't expect to send a message whose time stamp is very far in the future and have the device handle it as you intended, and you certainly can't expect a device to correctly schedule a message whose time stamp is in the past! It's up to the device to decide how to handle time stamps that are too far off in the future or are in the past. The sender doesn't know what the device considers to be too far off, or whether the device had any problem with the time stamp. This ignorance mimics the behavior of external MIDI hardware devices, which send messages without ever knowing whether they were received correctly. (MIDI wire protocol is unidirectional.)

Some devices send time-stamped messages (via a Transmitter). For example, the messages sent by a MIDI input port might be stamped with the time the incoming message arrived at the port. On some systems, the event-handling mechanisms cause a certain amount of timing precision to be lost during subsequent processing of the message. The message's time stamp allows the original timing information to be preserved.

To learn whether a device supports time stamps, invoke the following method of MidiDevice:

    long getMicrosecondPosition()

This method returns -1 if the device ignores time stamps. Otherwise, it returns the device's current notion of time, which you as the sender can use as an offset when determining the time stamps for messages you subsequently send. For example, if you want to send a message with a time stamp for five milliseconds in the future, you can get the device's current position in microseconds, add 5000 microseconds, and use that as the time stamp. Keep in mind that the MidiDevice's notion of time always places time zero at the time the device was opened.

Now, with all that explanation of time stamps as a background, let's return to the send method of Receiver:

void send(MidiMessage message, long timeStamp)

The timeStamp argument is expressed in microseconds, according to the receiving device's notion of time. If the device doesn't support time stamps, it simply ignores the timeStamp argument. You aren't required to time-stamp the messages you send to a receiver. You can use -1 for the timeStamp argument to indicate that you don't care about adjusting the exact timing; you're just leaving it up to the receiving device to process the message as soon as it can. However, it's not advisable to send -1 with some messages and explicit time stamps with other messages sent to the same receiver. Doing so is likely to cause irregularities in the resultant timing.

Connecting Transmitters to Receivers

We've seen how you can send a MIDI message directly to a receiver, without using a transmitter. Now let's look at the more common case, where you aren't creating MIDI messages from scratch, but are simply connecting devices together so that one of them can send MIDI messages to the other.

Connecting to a Single Device

The specific case we'll take as our first example is connecting a sequencer to a synthesizer. After this connection is made, starting the sequencer running will cause the synthesizer to generate audio from the events in the sequencer's current sequence. For now, we'll ignore the process of loading a sequence from a MIDI file into the sequencer. Also, we won't go into the mechanism of playing the sequence. Loading and playing sequences is discussed in detail in Playing, Recording, and Editing MIDI Sequences. Loading instruments into the synthesizer is discussed in Synthesizing Sound. For now, all we're interested in is how to make the connection between the sequencer and the synthesizer. This will serve as an illustration of the more general process of connecting one device's transmitter to another device's receiver.

For simplicity, we'll use the default sequencer and the default synthesizer.

    Sequencer    	seq;
    Transmitter  	seqTrans;
    Synthesizer  	synth;
    Receiver	     synthRcvr;
    try {
          seq	  = MidiSystem.getSequencer();
          seqTrans = seq.getTransmitter();
          synth	  = MidiSystem.getSynthesizer();
          synthRcvr = synth.getReceiver();
          seqTrans.setReceiver(synthRcvr);
    } catch (MidiUnavailableException e) {
          // handle or throw exception
    }

An implementation might actually have a single object that serves as both the default sequencer and the default synthesizer. In other words, the implementation might use a class that implements both the Sequencer interface and the Synthesizer interface. In that case, it probably wouldn't be necessary to make the explicit connection that we did in the code above. For portability, though, it's safer not to assume such a configuration. If desired, you can test for this condition, of course:

if (seq instanceof Synthesizer)

although the explicit connection above should work in any case.

Connecting to More than One Device

The previous code example illustrated a one-to-one connection between a transmitter and a receiver. But, what if you need to send the same MIDI message to multiple receivers? For example, suppose you want to capture MIDI data from an external device to drive the internal synthesizer while simultaneously recording the data to a sequence. This form of connection, sometimes referred to as "fan out" or as a "splitter," is straightforward. The following statements show how to create a fan-out connection, through which the MIDI messages arriving at the MIDI input port are sent to both a Synthesizer object and a Sequencer object. We assume you've already obtained and opened the three devices: the input port, sequencer, and synthesizer. (To obtain the input port, you'll need to iterate over all the items returned by MidiSystem.getMidiDeviceInfo.)

    Synthesizer  synth;
    Sequencer    seq;
    MidiDevice   inputPort;
    // [obtain and open the three devices...]
    Transmitter	  inPortTrans1, inPortTrans2;
    Receiver     	synthRcvr;
    Receiver     	seqRcvr;
    try {
          inPortTrans1 = inputPort.getTransmitter();
          synthRcvr = synth.getReceiver();
          inPortTrans1.setReceiver(synthRcvr);
          inPortTrans2 = inputPort.getTransmitter();
          seqRcvr = seq.getReceiver();
          inPortTrans2.setReceiver(seqRcvr);
    } catch (MidiUnavailableException e) {
          // handle or throw exception
    }

This code introduces a dual invocation of the MidiDevice.getTransmitter method, assigning the results to inPortTrans1 and inPortTrans2. As mentioned earlier, a device can own multiple transmitters and receivers. Each time MidiDevice.getTransmitter() is invoked for a given device, another transmitter is returned, until no more are available, at which time an exception will be thrown.

To learn how many transmitters and receivers a device supports, you can use the following MidiDevice method:

    int getMaxTransmitters()
    int getMaxReceivers()

These methods return the total number owned by the device, not the number currently available.

A transmitter can transmit MIDI messages to only one receiver at a time. (Every time you call Transmitter's setReceiver method, the existing Receiver, if any, is replaced by the newly specified one. You can tell whether the transmitter currently has a receiver by invoking Transmitter.getReceiver.) However, if a device has multiple transmitters, it can send data to more than one device at a time, by connecting each transmitter to a different receiver, as we saw in the case of the input port above.

Similarly, a device can use its multiple receivers to receive from more than one device at a time. The multiple-receiver code that's required is straightforward, being directly analogous to the multiple-transmitter code above. It's also possible for a single receiver to receive messages from more than one transmitter at a time.

Closing Connections

Once you're done with a connection, you can free up its resources by invoking the close method for each transmitter and receiver that you've obtained. The Transmitter and Receiver interfaces each have a close method. Note that invoking Transmitter.setReceiver doesn't close the transmitter's current receiver. The receiver is left open, and it can still receive messages from any other transmitter that's connected to it.

If you're also done with the devices, you can similarly make them available to other application programs by invoking MidiDevice.close(). Closing a device automatically closes all its transmitters and receivers.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Accessing MIDI System Resources
Next page: Introduction to Sequencers


Introduction to Sequencers (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Introduction to Sequencers

In the world of MIDI, a sequencer is any hardware or software device that can precisely play or record a sequence of time-stamped MIDI messages. Similarly, in the Java Sound API, the Sequencer abstract interface defines the properties of an object that can play and record sequences of MidiEvent objects. A Sequencer typically loads these MidiEvent sequences from a standard MIDI file or saves them to such a file. Sequences can also be edited. The following pages explain how to use Sequencer objects, along with related classes and interfaces, to accomplish such tasks.

To develop an intuitive understanding of what a Sequencer is, think of it by analogy with a tape recorder, which a sequencer resembles in many respects. Whereas a tape recorder plays audio, a sequencer plays MIDI data. A sequence is a multi-track, linear, time-ordered recording of MIDI musical data, which a sequencer can play at various speeds, rewind, shuttle to particular points, record into, or copy to a file for storage.

Transmitting and Receiving MIDI Messages explained that devices typically have Receiver objects, Transmitter objects, or both. To play music, a device generally receives MidiMessages through a Receiver, which in turn has usually received them from a Transmitter that belongs to a Sequencer. The device that owns this Receiver might be a Synthesizer, which will generate audio directly, or it might be a MIDI output port, which transmits MIDI data through a physical cable to some external piece of equipment. Similarly, to record music, a series of time-stamped MidiMessages are generally sent to a Receiver owned by a Sequencer, which places them in a Sequence object. Typically the object sending the messages is a Transmitter associated with a hardware input port, and the port relays MIDI data that it gets from an external instrument. However, the device responsible for sending the messages might instead be some other Sequencer, or any other device that has a Transmitter. Furthermore, as previously described, a program can send messages without using any Transmitter at all.

A Sequencer itself has both Receivers and Transmitters. When it's recording, it actually obtains MidiMessages via its Receivers. During playback, it uses its Transmitters to send MidiMessages that are stored in the Sequence that it has recorded (or loaded from a file).

One way to think of the role of a Sequencer in the Java Sound API is as an aggregator and "de-aggregator" of MidiMessages. A series of separate MidiMessages, each of which is independent, is sent to the Sequencer along with its own time stamp that marks the timing of a musical event. These MidiMessages are encapsulated in MidiEvent objects and collected in Sequence objects through the action of the Sequencer.record method. A Sequence is a data structure containing aggregates of MidiEvents, and it usually represents a series of musical notes, often an entire song or composition. On playback, the Sequencer again extracts the MidiMessages from the MidiEvent objects in the Sequence and then transmits them to one or more devices that will either render them into sound, save them, modify them, or pass them on to some other device.

Some sequencers might have neither transmitters nor receivers. For example, they might create MidiEvents from scratch as a result of keyboard or mouse events, instead of receiving MidiMessages through Receivers. Similarly, they might play music by communicating directly with an internal synthesizer (which could actually be the same object as the sequencer) instead of sending MidiMessages to a Receiver associated with a separate object. However, the rest of this discussion assumes the normal case of a sequencer that uses Receivers and Transmitters.

When to Use a Sequencer

It's possible for an application program to send MIDI messages directly to a device, without using a sequencer, as was described in Transmitting and Receiving MIDI Messages. The program simply invokes the Receiver.send method each time it wants to send a message. This is a straightforward approach that's useful when the program itself creates the messages in real time. For example, consider a program that lets the user play notes by clicking on an onscreen piano keyboard. When the program gets a mouse-down event, it immediately sends the appropriate Note On message to the synthesizer.

As previously mentioned, the program can include a time stamp with each MIDI message it sends to the device's receiver. However, such time stamps are used only for fine-tuning the timing, to correct for processing latency. The caller can't generally set arbitrary time stamps; the time value passed to Receiver.send must be close to the present time, or the receiving device might not be able to schedule the message correctly. This means that if an application program wanted to create a queue of MIDI messages for an entire piece of music ahead of time (instead of creating each message in response to a real-time event), it would have to be very careful to schedule each invocation of Receiver.send for nearly the right time.

Fortunately, most application programs don't have to be concerned with such scheduling. Instead of invoking Receiver.send itself, a program can use a Sequencer object to manage the queue of MIDI messages for it. The sequencer takes care of scheduling and sending the messages—in other words, playing the music with the correct timing. Generally, it's advantageous to use a sequencer whenever you need to convert a non-real-time series of MIDI messages to a real-time series (as in playback), or vice versa (as in recording). Sequencers are most commonly used for playing data from MIDI files and for recording data from a MIDI input port.

Understanding Sequence Data

Before examining the Sequencer API, it helps to understand the kind of data that's stored in a sequence.

Sequences and Tracks

In the Java Sound API, sequencers closely follow the Standard MIDI Files specification in the way that they organize recorded MIDI data. As mentioned above, a Sequence is an aggregation of MidiEvents, organized in time. But there is more structure to a Sequence than just a linear series of MidiEvents: a Sequence actually contains global timing information plus a collection of Tracks, and it is the Tracks themselves that hold the MidiEvent data. So the data played by a sequencer consists of a three-level hierarchy of objects: Sequencer, Track, and MidiEvent.

In the conventional use of these objects, the Sequence represents a complete musical composition or section of a composition, with each Track corresponding to a voice or player in the ensemble. In this model, all the data on a particular Track would also therefore be encoded into a particular MIDI channel reserved for that voice or player.

This way of organizing data is convenient for purposes of editing sequences, but note that this is just a conventional way to use Tracks. There is nothing in the definition of the Track class that keeps it from containing a mix of MidiEvents on different MIDI channels. For example, an entire multi-channel MIDI composition can be mixed and recorded onto one Track. Also, standard MIDI files of Type 0 (as opposed to Type 1 and Type 2) contain by definition only one track; so a Sequence that's read from such a file will necessarily have a single Track object.

MidiEvents and Ticks

As discussed in Overview of the MIDI Package, the Java Sound API includes MidiMessage objects that correspond to the raw two- or three-byte sequences that make up most standard MIDI messages. A MidiEvent is simply a packaging of a MidiMessage along with an accompanying timing value that specifies when the event occurs. (We might then say that a sequence really consists of a four- or five-level hierarchy of data, rather than three-level, because the ostensible lowest level, MidiEvent, actually contains a lower-level MidiMessage, and likewise the MidiMessage object contains an array of bytes that comprises a standard MIDI message.)

In the Java Sound API, there are two different ways in which MidiMessages can be associated with timing values. One is the way mentioned above under "When to Use a Sequencer." This technique was described in detail under Sending a Message to a Receiver without Using a Transmitter and Understanding Time Stamps. There, we saw that the send method of Receiver takes a MidiMessage argument and a time-stamp argument. That kind of time stamp can only be expressed in microseconds.

The other way in which a MidiMessage can have its timing specified is by being encapsulated in a MidiEvent. In this case, the timing is expressed in slightly more abstract units called ticks.

What is the duration of a tick? It can vary between sequences (but not within a sequence), and its value is stored in the header of a standard MIDI file. The size of a tick is given in one of two types of units:

  • Pulses (ticks) per quarter note, abbreviated as PPQ
  • Ticks per frame, also known as SMPTE time code (a standard adopted by the Society of Motion Picture and Television Engineers)

If the unit is PPQ, the size of a tick is expressed as a fraction of a quarter note, which is a relative, not absolute, time value. A quarter note is a musical duration value that often corresponds to one beat of the music (a quarter of a measure in 4/4 time). The duration of a quarter note is dependent on the tempo, which can vary during the course of the music if the sequence contains tempo-change events. So if the sequence's timing increments (ticks) occur, say 96 times per quarter note, each event's timing value measures that event's position in musical terms, not as an absolute time value.

On the other hand, in the case of SMPTE, the units measure absolute time, and the notion of tempo is inapplicable. There are actually four different SMPTE conventions available, which refer to the number of motion-picture frames per second. The number of frames per second can be 24, 25, 29.97, or 30. With SMPTE time code, the size of a tick is expressed as a fraction of a frame.

In the Java Sound API, you can invoke Sequence.getDivisionType to learn which type of unit—namely, PPQ or one of the SMPTE units—is used in a particular sequence. You can then calculate the size of a tick after invoking Sequence.getResolution. The latter method returns the number of ticks per quarter note if the division type is PPQ, or per SMPTE frame if the division type is one of the SMPTE conventions. You can get the size of a tick using this formula in the case of PPQ:

ticksPerSecond =
    resolution * (currentTempoInBeatsPerMinute / 60.0);
tickSize = 1.0 / ticksPerSecond;

and this formula in the case of SMPTE:

framesPerSecond =
  (divisionType == Sequence.SMPTE_24 ? 24
    : (divisionType == Sequence.SMPTE_25 ? 25
      : (divisionType == Sequence.SMPTE_30 ? 30
        : (divisionType == Sequence.SMPTE_30DROP ?

            29.97))));
ticksPerSecond = resolution * framesPerSecond;
tickSize = 1.0 / ticksPerSecond;

The Java Sound API's definition of timing in a sequence mirrors that of the Standard MIDI Files specification. However, there's one important difference. The tick values contained in MidiEvents measure cumulative time, rather than delta time. In a standard MIDI file, each event's timing information measures the amount of time elapsed since the onset of the previous event in the sequence. This is called delta time. But in the Java Sound API, the ticks aren't delta values; they're the previous event's time value plus the delta value. In other words, in the Java Sound API the timing value for each event is always greater than that of the previous event in the sequence (or equal, if the events are supposed to be simultaneous). Each event's timing value measures the time elapsed since the beginning of the sequence.

To summarize, the Java Sound API expresses timing information in either MIDI ticks or microseconds. MidiEvents store timing information in terms of MIDI ticks. The duration of a tick can be calculated from the Sequence's global timing information and, if the sequence uses tempo-based timing, the current musical tempo. The time stamp associated with a MidiMessage sent to a Receiver, on the other hand, is always expressed in microseconds.

One goal of this design is to avoid conflicting notions of time. It's the job of a Sequencer to interpret the time units in its MidiEvents, which might have PPQ units, and translate these into absolute time in microseconds, taking the current tempo into account. The sequencer must also express the microseconds relative to the time when the device receiving the message was opened. Note that a sequencer can have multiple transmitters, each delivering messages to a different receiver that might be associated with a completely different device. You can see, then, that the sequencer has to be able to perform multiple translations at the same time, making sure that each device receives time stamps appropriate for its notion of time.

To make matters more complicated, different devices might update their notions of time based on different sources (such as the operating system's clock, or a clock maintained by a sound card). This means that their timings can drift relative to the sequencer's. To keep in synchronization with the sequencer, some devices permit themselves to be "slaves" to the sequencer's notion of time. Setting masters and slaves is discussed later under MidiEvent.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Transmitting and Receiving MIDI Messages
Next page: Using Sequencer Methods


Using Sequencer Methods (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Using Sequencer Methods
The Sequencer interface provides methods in several categories:

  • Methods to load sequence data from a MIDI file or a Sequence object, and to save the currently loaded sequence data to a MIDI file.
  • Methods analogous to the transport functions of a tape recorder, for stopping and starting playback and recording, enabling and disabling recording on specific tracks, and shuttling the current playback or recording position in a Sequence.
  • Advanced methods for querying and setting the synchronization and timing parameters of the object. A Sequencer may play at different tempos, with some Tracks muted, and in various synchronization states with other objects.
  • Advanced methods for registering "listener" objects that are notified when the Sequencer processes certain kinds of MIDI events.

Regardless of which Sequencer methods you'll invoke, the first step is to obtain a Sequencer device from the system and reserve it for your program's use.

Obtaining a Sequencer

An application program doesn't instantiate a Sequencer; after all, Sequencer is just an interface. Instead, like all devices in the Java Sound API's MIDI package, a Sequencer is accessed through the static MidiSystem object. As previously mentioned in Accessing MIDI System Resources, the following MidiSystem method can be used to obtain the default Sequencer:

static Sequencer getSequencer()

The following code fragment obtains the default Sequencer, acquires any system resources it needs, and makes it operational:

Sequencer sequencer;
// Get default sequencer.
sequencer = MidiSystem.getSequencer();
if (sequencer == null) {
    // Error -- sequencer device is not supported.
    // Inform user and return...
} else {
    // Acquire resources and make operational.
    sequencer.open();
}

The invocation of open reserves the sequencer device for your program's use. It doesn't make much sense to imagine sharing a sequencer, because it can play only one sequence at a time. When you're done using the sequencer, you can make it available to other programs by invoking close.

Non-default sequencers can be obtained as described in Accessing MIDI System Resources.

Loading a Sequence

Having obtained a sequencer from the system and reserved it, you then need load the data that the sequencer should play. There are three typical ways of accomplishing this:

  • Reading the sequence data from a MIDI file
  • Recording it in real time by receiving MIDI messages from another device, such as a MIDI input port
  • Building it programmatically "from scratch" by adding tracks to an empty sequence and adding MidiEvent objects to those tracks

We'll now look at the first of these ways of getting sequence data. (The other two ways are described below under Recording and Saving Sequences and Editing a Sequence, respectively.) This first way actually encompasses two slightly different approaches. One approach is to feed MIDI file data to an InputStream that you then read directly to the sequencer by means of Sequencer.setSequence(InputStream). With this approach, you don't explicitly create a Sequence object. In fact, the Sequencer implementation might not even create a Sequence behind the scenes, because some sequencers have a built-in mechanism for handling data directly from a file.

The other approach is to create a Sequence explicitly. You'll need to use this approach if you're going to edit the sequence data before playing it. With this approach, you invoke MidiSystem's overloaded method getSequence. The method is able to get the sequence from an InputStream, a File, or a URL. The method returns a Sequence object that can then be loaded into a Sequencer for playback. Expanding on the previous code excerpt, here's an example of obtaining a Sequence object from a File and loading it into our sequencer:

try {
    File myMidiFile = new File("seq1.mid");
    // Construct a Sequence object, and
    // load it into my sequencer.
    Sequence mySeq = MidiSystem.getSequence(myMidiFile);
    sequencer.setSequence(mySeq);
} catch (Exception e) {
   // Handle error and/or return
}

Like MidiSystem's getSequence method, setSequence may throw an InvalidMidiDataException—and, in the case of the InputStream variant, an IOException—if it runs into any trouble.

Playing a Sequence

Starting and stopping a Sequencer is accomplished using the following methods:

    void start()

and

    void stop()

The Sequencer.start method begins playback of the sequence. Note that playback starts at the current position in a sequence. Loading an existing sequence using the setSequence method, described above, initializes the sequencer's current position to the very beginning of the sequence. The stop method stops the sequencer, but it does not automatically rewind the current Sequence. Starting a stopped Sequence without resetting the position simply resumes playback of the sequence from the current position. In this case, the stop method has served as a pause operation. However, there are various Sequencer methods for setting the current sequence position to an arbitrary value before playback is started. (We'll discuss these methods below.)

As mentioned earlier, a Sequencer typically has one or more Transmitter objects, through which it sends MidiMessages to a Receiver. It is through these Transmitters that a Sequencer plays the Sequence, by emitting appropriately timed MidiMessages that correspond to the MidiEvents contained in the current Sequence. Therefore, part of the setup procedure for playing back a Sequence is to invoke the setReceiver method on the Sequencer's Transmitter object, in effect wiring its output to the device that will make use of the played-back data. For more details on Transmitters and Receivers, refer back to Transmitting and Receiving MIDI Messages.

Recording and Saving Sequences

To capture MIDI data to a Sequence, and subsequently to a file, you need to perform some additional steps beyond those described above. The following outline shows the steps necessary to set up for recording to a Track in a Sequence:

  1. Use MidiSystem.getSequencer to get a new sequencer to use for recording, as above.

  2. Set up the "wiring" of the MIDI connections. The object that is transmitting the MIDI data to be recorded should be configured, through its setReceiver method, to send data to a Receiver associated with the recording Sequencer.

  3. Create a new Sequence object, which will store the recorded data. When you create the Sequence object, you must specify the global timing information for the sequence. For example:
          Sequence mySeq;
      try{
          mySeq = new Sequence(Sequence.PPQ, 10);
      } catch (Exception ex) {
          ex.printStackTrace();
      }
    The constructor for Sequence takes as arguments a divisionType and a timing resolution. The divisionType argument specifies the units of the resolution argument. In this case, we've specified that the timing resolution of the Sequence we're creating will be 10 pulses per quarter note. An additional optional argument to the Sequence constructor is a number of tracks argument, which would cause the initial sequence to begin with the specified number of (initially empty) Tracks. Otherwise the Sequence will be created with no initial Tracks; they can be added later as needed.

  4. Create an empty Track in the Sequence, with Sequence.createTrack. This step is unnecessary if the Sequence was created with initial Tracks.

  5. Using Sequencer.setSequence, select our new Sequence to receive the recording. The setSequence method ties together an existing Sequence with the Sequencer, which is somewhat analogous to loading a tape onto a tape recorder.

  6. Invoke Sequencer.recordEnable for each Track to be recorded. If necessary, get a reference to the available Tracks in the Sequence by invoking Sequence.getTracks.

  7. Invoke startRecording on the Sequencer.

  8. When done recording, invoke Sequencer.stop or Sequencer.stopRecording.

  9. Save the recorded Sequence to a MIDI file with MidiSystem.write. The write method of MidiSystem takes a Sequence as one of its arguments, and will write that Sequence to a stream or file.

Editing a Sequence

Many application programs allow a sequence to be created by loading it from a file, and quite a few also allow a sequence to be created by capturing it from live MIDI input (that is, recording). Some programs, however, will need to create MIDI sequences from scratch, whether programmatically or in response to user input. Full-featured sequencer programs permit the user to manually construct new sequences, as well as to edit existing ones.

These data-editing operations are achieved in the Java Sound API not by Sequencer methods, but by methods of the data objects themselves: Sequence, Track, and MidiEvent. You can create an empty sequence using one of the Sequence constructors, and then add tracks to it by invoking the following Sequence method:

    Track createTrack()
If your program allows the user to edit sequences, you'll need this Sequence method to remove tracks:
    boolean deleteTrack(Track track)

Once the sequence contains tracks, you can modify the contents of the tracks by invoking methods of the Track class. The MidiEvents contained in the Track are stored as a java.util.Vector in the Track object, and Track provides a set of methods for accessing, adding, and removing the events in the list. The methods add and remove are fairly self-explanatory, adding or removing a specified MidiEvent from a Track. A get method is provided, which takes an index into the Track's event list and returns the MidiEvent stored there. In addition, there are size and tick methods, which respectively return the number of MidiEvents in the track, and the track's duration, expressed as a total number of Ticks.

To create a new event before adding it to the track, you'll of course use the MidiEvent constructor. To specify or modify the MIDI message embedded in the event, you can invoke the setMessage method of the appropriate MidiMessage subclass (ShortMessage, SysexMessage, or MetaMessage). To modify the time that the event should occur, invoke MidiEvent.setTick.

In combination, these low-level methods provide the basis for the editing functionality needed by a full-featured sequencer program.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Introduction to Sequencers
Next page: Using Advanced Sequencer Features


Using Advanced Sequencer Features (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Using Advanced Sequencer Features

So far, we've focused on simple playback and recording of MIDI data. This section will briefly describe some of the more advanced features available through methods of the Sequencer interface and the Sequence class.

Moving to an Arbitrary Position in the Sequence

There are two Sequencer methods that obtain the sequencer's current position in the sequence. The first of these:

long getTickPosition()

returns the position measured in MIDI ticks from the beginning of the sequence. The second method:

long getMicrosecondPosition()

returns the current position in microseconds. This method assumes that the sequence is being played at the default rate as stored in the MIDI file or in the Sequence. It does not return a different value if you've changed the playback speed as described below.

You can similarly set the sequencer's current position according to one unit or the other:

void setTickPosition(long tick)

or

void setMicrosecondPosition(long microsecond)

Changing the Playback Speed

As indicated earlier, a sequence's speed is indicated by its tempo, which can vary over the course of the sequence. A sequence can contain events that encapsulate standard MIDI tempo-change messages. When the sequencer processes such an event, it changes the speed of playback to reflect the indicated tempo. In addition, you can programmatically change the tempo by invoking any of these Sequencer methods:

    public void setTempoInBPM(float bpm)
    public void setTempoInMPQ(float mpq)
    public void setTempoFactor(float factor)
The first two of these methods set the tempo in beats per minute or microseconds per quarter note, respectively. The tempo will stay at the specified value until one of these methods is invoked again, or until a tempo-change event is encountered in the sequence, at which point the current tempo is overridden by the newly specified one.

The third method, setTempoFactor, is different in nature. It scales whatever tempo is set for the sequencer (whether by tempo-change events or by one of the first two methods above). The default scalar is 1.0 (no change). Although this method causes the playback or recording to be faster or slower than the nominal tempo (unless the factor is 1.0), it doesn't alter the nominal tempo. In other words, the tempo values returned by getTempoInBPM and getTempoInMPQ are unaffected by the tempo factor, even though the tempo factor does affect the actual rate of playback or recording. Also, if the tempo is changed by a tempo-change event or by one of the first two methods, it still gets scaled by whatever tempo factor was last set. If you load a new sequence, however, the tempo factor is reset to 1.0.

Note that all these tempo-change directives are ineffectual when the sequence's division type is one of the SMPTE types, instead of PPQ.

Muting or Soloing Individual Tracks in the Sequence

It's often convenient for users of sequencers to be able to turn off certain tracks, to hear more clearly exactly what is happening in the music. A full-featured sequencer program lets the user choose which tracks should sound during playback. (Speaking more precisely, since sequencers don't actually create sound themselves, the user chooses which tracks will contribute to the stream of MIDI messages that the sequencer produces.) Typically, there are two types of graphical controls on each track: a mute button and a solo button. If the mute button is activated, that track will not sound under any circumstances, until the mute button is deactivated. Soloing is a less well-known feature. It's roughly the opposite of muting. If the solo button on any track is activated, only tracks whose solo buttons are activated will sound. This feature lets the user quickly audition a small number of tracks without having to mute all the other tracks. The mute button typically takes priority over the solo button: if both are activated, the track doesn't sound.

Using Sequencer methods, muting or soloing tracks (as well as querying a track's current mute or solo state) is easily accomplished. Let's assume we have obtained the default Sequencer and that we've loaded sequence data into it. Muting the fifth track in the sequence would be accomplished as follows:

    sequencer.setTrackMute(4, true);
    boolean muted = sequencer.getTrackMute(4);
    if (!muted) {
        return;		// muting failed
    }
There are a couple of things to note about the above code snippet. First, tracks of a sequence are numbered starting with 0 and ending with the total number of tracks minus 1. Also, the second argument to setTrackMute is a boolean. If it's true, the request is to mute the track; otherwise the request is to unmute the specified track. Lastly, in order to test that the muting took effect, we invoke the Sequencer getTrackMute method, passing it the track number we're querying. If it returns true, as we'd expect in this case, then the mute request worked. If it returns false, then it failed.

Mute requests may fail for various reasons. For example, the track number specified in the setTrackMute call might exceed the total number of tracks, or the sequencer might not support muting. By calling getTrackMute, we can determine if our request succeeded or failed.

As an aside, the boolean that's returned by getTrackMute can, indeed, tell us if a failure occurred, but it can't tell us why it occurred. We could test to see if a failure was caused by passing an invalid track number to the setTrackMute method. To do this, we would call the getTracks method of Sequence, which returns an array containing all of the tracks in the sequence. If the track number specified in the setTrackMute call exceeds the length of this array, then we know we specified an invalid track number.

If the mute request succeeded, then in our example, the fifth track will not sound when the sequence is playing, nor will any other tracks that are currently muted.

The method and techniques for soloing a track are very similar to those for muting. To solo a track, invoke the setTrackSolo method of Sequence:

void setTrackSolo(int track, boolean bSolo)
As in setTrackMute, the first argument specifies the zero-based track number, and the second argument, if true, specifies that the track should be in solo mode; otherwise the track should not be soloed.

By default, a track is neither muted nor soloed.

Synchronizing with Other MIDI Devices

Sequencer has an inner class called Sequencer.SyncMode. A SyncMode object represents one of the ways in which a MIDI sequencer's notion of time can be synchronized with a master or slave device. If the sequencer is being synchronized to a master, the sequencer revises its current time in response to certain MIDI messages from the master. If the sequencer has a slave, the sequencer similarly sends MIDI messages to control the slave's timing.

There are three predefined modes that specify possible masters for a sequencer: INTERNAL_CLOCK, MIDI_SYNC, and MIDI_TIME_CODE. The latter two work if the sequencer receives MIDI messages from another device. In these two modes, the sequencer's time gets reset based on system real-time timing clock messages or MIDI time code (MTC) messages, respectively. (See the MIDI specification for more information about these types of message.) These two modes can also be used as slave modes, in which case the sequencer sends the corresponding types of MIDI messages to its receiver. A fourth mode, NO_SYNC, is used to indicate that the sequencer should not send timing information to its receivers.

By calling the setMasterSyncMode method with a supported SyncMode object as the argument, you can specify how the sequencer's timing is controlled. Likewise, the setSlaveSyncMode method determines what timing information the sequencer will send to its receivers. This information controls the timing of devices that use the sequencer as a master timing source.

Specifying Special Event Listeners

Each track of a sequence can contain many different kinds of MidiEvents. Such events include Note On and Note Off messages, program changes, control changes, and meta events. The Java Sound API specifies "listener" interfaces for the last two of these event types (control change events and meta events). You can use these interfaces to receive notifications when such events occur during playback of a sequence.

Objects that support the ControllerEventListener interface can receive notification when a Sequencer processes particular control-change messages. A control-change message is a standard type of MIDI message that represents a change in the value of a MIDI controller, such as a pitch-bend wheel or a data slider. (See the MIDI specification for the complete list of control-change messages.) When such a message is processed during playback of a sequence, the message instructs any device (probably a synthesizer) that's receiving the data from the sequencer to update the value of some parameter. The parameter usually controls some aspect of sound synthesis, such as the pitch of the currently sounding notes if the controller was the pitch-bend wheel. When a sequence is being recorded, the control-change message means that a controller on the external physical device that created the message has been moved, or that such a move has been simulated in software.

Here's how the ControllerEventListener interface is used. Let's assume that you've developed a class that implements the ControllerEventListener interface, meaning that your class contains the following method:

    void controlChange(ShortMessage msg)
Let's also assume that you've created an instance of your class and assigned it to a variable called myListener. If you include the following statements somewhere within your program:
    int[] controllersOfInterest = { 1, 2, 4 };
    sequencer.addControllerEventListener(myListener,
        controllersOfInterest);
then your class's controlChange method will be invoked every time the sequencer processes a control-change message for MIDI controller numbers 1, 2, or 4. In other words, when the Sequencer processes a request to set the value of any of the registered controllers, the Sequencer will invoke your class's controlChange method. (Note that the assignments of MIDI controller numbers to specific control devices is detailed in the MIDI 1.0 Specification.)

The controlChange method is passed a ShortMessage containing the controller number affected, and the new value to which the controller was set. You can obtain the controller number using the ShortMessage.getData1 method, and the new setting of the controller's value using the ShortMessage.getData2 method.

The other kind of special event listener is defined by the MetaEventListener interface. Meta messages, according to the Standard MIDI Files 1.0 specification, are messages that are not present in MIDI wire protocol but that can be embedded in a MIDI file. They are not meaningful to a synthesizer, but can be interpreted by a sequencer. Meta messages include instructions (such as tempo change commands), lyrics or other text, and other indicators (such as end-of-track).

The MetaEventListener mechanism is analogous to ControllerEventListener. Implement the MetaEventListener interface in any class whose instances need to be notified when a MetaMessage is processed by the sequencer. This involves adding the following method to the class:

void meta(MetaMessage msg)

You register an instance of this class by passing it as the argument to the Sequencer addMetaEventListener method:

boolean b = sequencer.addMetaEventListener
        (myMetaListener);
This is slightly different from the approach taken by the ControllerEventListener interface, because you have to register to receive all MetaMessages, not just selected ones of interest. If the sequencer encounters a MetaMessage in its sequence, it will invoke myMetaListener.meta, passing it the MetaMessage encountered. The meta method can invoke getType on its MetaMessage argument to obtain an integer from 0 to 127 that indicates the message type, as defined by the Standard MIDI Files 1.0 specification.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Sequencer Methods
Next page: Synthesizing Sound


Synthesizing Sound (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Synthesizing Sound

Most programs that avail themselves of the Java Sound API's MIDI package do so to synthesize sound. The entire apparatus of MIDI files, events, sequences, and sequencers, which was previously discussed, nearly always has the goal of eventually sending musical data to a synthesizer to convert into audio. (Possible exceptions include programs that convert MIDI into musical notation that can be read by a musician, and programs that send messages to external MIDI-controlled devices such as mixing consoles.)

The Synthesizer interface is therefore fundamental to the MIDI package. This page shows how to manipulate a synthesizer to play sound. Many programs will simply use a sequencer to send MIDI file data to the synthesizer, and won't need to invoke many Synthesizer methods directly. However, it's possible to control a synthesizer directly, without using sequencers or even MidiMessage objects, as explained near the end of this page.

The synthesis architecture might seem complex for readers who are unfamiliar with MIDI. Its API includes three interfaces:

  • Synthesizer
  • MidiChannel
  • Soundbank

and four classes:

  • Instrument
  • Patch
  • SoundbankResource
  • VoiceStatus

As orientation for all this API, the next section explains some of the basics of MIDI synthesis and how they're reflected in the Java Sound API. Subsequent sections give a more detailed look at the API.

Understanding MIDI Synthesis

How does a synthesizer generate sound? Depending on its implementation, it may use one or more sound-synthesis techniques. For example, many synthesizers use wavetable synthesis. A wavetable synthesizer reads stored snippets of audio from memory, playing them at different sample rates and looping them to create notes of different pitches and durations. For example, to synthesize the sound of a saxophone playing the note C#4 (MIDI note number 61), the synthesizer might access a very short snippet from a recording of a saxophone playing the note Middle C (MIDI note number 60), and then cycle repeatedly through this snippet at a slightly faster sample rate than it was recorded at, which creates a long note of a slightly higher pitch. Other synthesizers use techniques such as frequency modulation (FM), additive synthesis, or physical modeling, which don't make use of stored audio but instead generate audio from scratch using different algorithms.

Instruments

What all synthesis techniques have in common is the ability to create many sorts of sounds. Different algorithms, or different settings of parameters within the same algorithm, create different-sounding results. An instrument is a specification for synthesizing a certain type of sound. That sound may emulate a traditional musical instrument, such as a piano or violin; it may emulate some other kind of sound source, for instance, a telephone or helicopter; or it may emulate no "real-world" sound at all. A specification called General MIDI defines a standard list of 128 instruments, but most synthesizers allow other instruments as well. Many synthesizers provide a collection of built-in instruments that are always available for use; some synthesizers also support mechanisms for loading additional instruments.

An instrument may be vendor-specific—in other words, applicable to only one synthesizer or several models from the same vendor. This incompatibility results when two different synthesizers use different sound-synthesis techniques, or different internal algorithms and parameters even if the fundamental technique is the same. Because the details of the synthesis technique are often proprietary, incompatibility is common. The Java Sound API includes ways to detect whether a given synthesizer supports a given instrument.

An instrument can usually be considered a preset; you don't have to know anything about the details of the synthesis technique that produces its sound. However, you can still vary aspects of its sound. Each Note On message specifies the pitch and volume of an individual note. You can also alter the sound through other MIDI commands such as controller messages or system-exclusive messages.

Channels

Many synthesizers are multimbral (sometimes called polytimbral), meaning that they can play the notes of different instruments simultaneously. (Timbre is the characteristic sound quality that enables a listener to distinguish one kind of musical instrument from other kinds.) Multimbral synthesizers can emulate an entire ensemble of real-world instruments, instead of only one instrument at a time. MIDI synthesizers normally implement this feature by taking advantage of the different MIDI channels on which the MIDI specification allows data to be transmitted. In this case, the synthesizer is actually a collection of sound-generating units, each emulating a different instrument and responding independently to messages that are received on a different MIDI channel. Since the MIDI specification provides only 16 channels, a typical MIDI synthesizer can play up to 16 different instruments at once. The synthesizer receives a stream of MIDI commands, many of which are channel commands. (Channel commands are targeted to a particular MIDI channel; for more information, see the MIDI specification.) If the synthesizer is multitimbral, it routes each channel command to the correct sound-generating unit, according to the channel number indicated in the command.

In the Java Sound API, these sound-generating units are instances of classes that implement the MidiChannel interface. A synthesizer object has at least one MidiChannel object. If the synthesizer is multimbral, it has more than one, normally 16. Each MidiChannel represents an independent sound-generating unit.

Because a synthesizer's MidiChannel objects are more or less independent, the assignment of instruments to channels doesn't have to be unique. For example, all 16 channels could be playing a piano timbre, as though there were an ensemble of 16 pianos. Any grouping is possible—for instance, channels 1, 5, and 8 could be playing guitar sounds, while channels 2 and 3 play percussion and channel 12 has a bass timbre. The instrument being played on a given MIDI channel can be changed dynamically; this is known as a program change.

Even though most synthesizers allow only 16 or fewer instruments to be active at a given time, these instruments can generally be chosen from a much larger selection and assigned to particular channels as required.

Soundbanks and Patches

Instruments are organized hierarchically in a synthesizer, by bank number and program number. Banks and programs can be thought of as rows and columns in a two-dimensional table of instruments. A bank is a collection of programs. The MIDI specification allows up to 128 programs in a bank, and up to 128 banks. However, a particular synthesizer might support only one bank, or a few banks, and might support fewer than 128 programs per bank.

In the Java Sound API, there's a higher level to the hierarchy: a soundbank. Soundbanks can contain up to 128 banks, each containing up to 128 instruments. Some synthesizers can load an entire soundbank into memory.

To select an instrument from the current soundbank, you specify a bank number and a program number. The MIDI specification accomplishes this with two MIDI commands: bank select and program change. In the Java Sound API, the combination of a bank number and program number is encapsulated in a Patch object. You change a MIDI channel's current instrument by specifying a new patch. The patch can be considered the two-dimensional index of the instruments in the current soundbank.

You might be wondering if soundbanks, too, are indexed numerically. The answer is no; the MIDI specification does not provide for this. In the Java Sound API, a Soundbank object can be obtained by reading a soundbank file. If the soundbank is supported by the synthesizer, its instruments can be loaded into the synthesizer individually as desired, or all at once. Many synthesizers have a built-in or default soundbank; the instruments contained in this soundbank are always available to the synthesizer.

Voices

It's important to distinguish between the number of timbres a synthesizer can play simultaneously and the number of notes it can play simultaneously. The former was described above under "Channels." The ability to play multiple notes at once is referred to as polyphony. Even a synthesizer that isn't multitimbral can generally play more than one note at a time (all having the same timbre, but different pitches). For example, playing any chord, such as a G major triad or a B minor seventh chord, requires polyphony. Any synthesizer that generates sound in real time has a limitation on the number of notes it can synthesize at once. In the Java Sound API, the synthesizer reports this limitation through the getMaxPolyphony method.

A voice is a succession of single notes, such as a melody that a person can sing. Polyphony consists of multiple voices, such as the parts sung by a choir. A 32-voice synthesizer, for example, can play 32 notes simultaneously. (However, some MIDI literature uses the word "voice" in a different sense, similar to the meaning of "instrument" or "timbre.")

The process of assigning incoming MIDI notes to specific voices is known as voice allocation. A synthesizer maintains a list of voices, keeping track of which ones are active (meaning that they currently have notes sounding). When a note stops sounding, the voice becomes inactive, meaning that it's now free to accept the next note-on request that the synthesizer receives. An incoming stream of MIDI commands can easily request more simultaneous notes than the synthesizer is capable of generating. When all the synthesizer's voices are active, how should the next Note On request be handled? Synthesizers can implement different strategies: the most recently requested note can be ignored; or it can be played by discontinuing another note, such as the least recently started one.

Although the MIDI specification does not require it, a synthesizer can make public the contents of each of its voices. The Java Sound API includes a VoiceStatus class for this purpose.

A VoiceStatus reports on the voice's current active or inactive status, MIDI channel, bank and program number, MIDI note number, and MIDI volume.

With this background, let's examine the specifics of the Java Sound API for synthesis.

Managing Instruments and Soundbanks

In many cases, a program can make use of a Synthesizer object without explicitly invoking almost any of the synthesis API. For example, suppose you're playing a standard MIDI file. You load it into a Sequence object, which you play by having a sequencer send the data to the default synthesizer. The data in the sequence controls the synthesizer as intended, playing all the right notes at the right times.

However, there are cases when this simple scenario is inadequate. The sequence contains the right music, but the instruments sound all wrong! This unfortunate situation probably arose because the creator of the MIDI file had different instruments in mind than the ones that are currently loaded into the synthesizer.

The MIDI 1.0 Specification provides for bank-select and program-change commands, which affect which instrument is currently playing on each MIDI channel. However, the specification does not define what instrument should reside in each patch location (bank and program number). The more recent General MIDI specification addresses this problem by defining a bank containing 128 programs that correspond to specific instrument sounds. A General MIDI synthesizer uses 128 instruments that match this specified set. Different General MIDI synthesizers can sound quite different, even when playing what's supposed to be the same instrument. However, a MIDI file should for the most part sound similar (even if not identical), no matter which General MIDI synthesizer is playing it.

Nonetheless, not all creators of MIDI files want to be limited to the set of 128 timbres defined by General MIDI. This section shows how to change the instruments from the default set that the synthesizer comes with. (If there is no default, meaning that no instruments are loaded when you access the synthesizer, you'll have to use this API to start with in any case.)

Learning What Instruments Are Loaded

To learn whether the instruments currently loaded into the synthesizer are the ones you want, you can invoke this Synthesizer method:

Instrument[] getLoadedInstruments()
and iterate over the returned array to see exactly which instruments are currently loaded. Most likely, you would display the instruments' names in the user interface (using the getName method of Instrument), and let the user decide whether to use those instruments or load others. The Instrument API includes a method that reports which soundbank the instrument belongs to. The soundbank's name might help your program or the user ascertain exactly what the instrument is.

This Synthesizer method:

Soundbank getDefaultSoundbank()
gives you the default soundbank. The Soundbank API includes methods to retrieve the soundbank's name, vendor, and version number, by which the program or the user can verify the bank's identity. However, you can't assume when you first get a synthesizer that the instruments from the default soundbank have been loaded into the synthesizer. For example, a synthesizer might have a large assortment of built-in instruments available for use, but because of its limited memory it might not load them automatically.

Loading Different Instruments

The user might decide to load instruments that are different from the current ones (or you might make that decision programmatically). The following method tells you which instruments come with the synthesizer (versus having to be loaded from soundbank files):

Instrument[] getAvailableInstruments()
You can load any of these instruments by invoking:
boolean loadInstrument(Instrument instrument)
The instrument gets loaded into the synthesizer in the location specified by the instrument's Patch object (which can be retrieved using the getPatch method of Instrument).

To load instruments from other soundbanks, first invoke Synthesizer's isSupportedSoundbank method to make sure that the soundbank is compatible with this synthesizer (if it isn't, you can iterate over the system's synthesizers to try to find one that supports the soundbank). You can then invoke one of these methods to load instruments from the soundbank:

boolean loadAllInstruments(Soundbank soundbank)
boolean loadInstruments(Soundbank soundbank,
  Patch[] patchList)
As the names suggest, the first of these loads the entire set of instruments from a given soundbank, and the second loads selected instruments from the soundbank. You could also use Soundbank's getInstruments method to access all the instruments, then iterate over them and load selected instruments one at a time using loadInstrument.

It's not necessary for all the instruments you load to be from the same soundbank. You could use loadInstrument or loadInstruments to load certain instruments from one soundbank, another set from a different soundbank, and so on.

Each instrument has its own Patch object that specifies the location on the synthesizer where the instrument should be loaded. The location is defined by a bank number and a program number. There's no API to change the location by changing the patch's bank or program number.

However, it is possible to load an instrument into a location other than the one specified by its patch, using the following method of Synthesizer:

boolean remapInstrument(Instrument from, Instrument to)
This method unloads its first argument from the synthesizer, and places its second argument in whatever synthesizer patch location had been occupied by the first argument.

Unloading Instruments

Loading an instrument into a program location automatically unloads whatever instrument was already at that location, if any. You can also explicitly unload instruments without necessarily replacing them with new ones. Synthesizer includes three unloading methods that correspond to the three loading methods. If the synthesizer receives a program-change message that selects a program location where no instrument is currently loaded, there won't be any sound from the MIDI channel on which the program-change message was sent.

Accessing Soundbank Resources

Some synthesizers store other information besides instruments in their soundbanks. For example, a wavetable synthesizer stores audio samples that one or more instruments can access. Because the samples might be shared by multiple instruments, they're stored in the soundbank independently of any instrument. Both the Soundbank interface and the Instrument class provide a method call getSoundbankResources, which returns a list of SoundbankResource objects. The details of these objects are specific to the synthesizer for which the soundbank is designed. In the case of wavetable synthesis, a resource might be an object that encapsulates a series of audio samples, taken from one snippet of a sound recording. Synthesizers that use other synthesis techniques might store other kinds of objects in the synthesizer's SoundbankResources array.

Querying the Synthesizer's Capabilities and Current State

The Synthesizer interface includes methods that return information about the synthesizer's capabilities:

    public long getLatency()
    public int getMaxPolyphony()
The latency measures the worst-case delay between the time a MIDI message is delivered to the synthesizer and the time that the synthesizer actually produces the corresponding result. For example, it might take a synthesizer a few milliseconds to begin generating audio after receiving a note-on event.

The getMaxPolyphony method indicates how many notes the synthesizer can sound simultaneously, as discussed earlier under Voices. As mentioned in the same discussion, a synthesizer can provide information about its voices. This is accomplished through the following method:

public VoiceStatus[] getVoiceStatus()
Each VoiceStatus in the returned array reports the voice's current active or inactive status, MIDI channel, bank and program number, MIDI note number, and MIDI volume. The array's length should normally be the same number returned by getMaxPolyphony. If the synthesizer isn't playing, all its VoiceStatus objects have their active field set to false.

You can learn additional information about the current status of a synthesizer by retrieving its MidiChannel objects and querying their state. This is discussed more in the next section.

Using Channels

Sometimes it's useful or necessary to access a synthesizer's MidiChannel objects directly. This section discusses such situations.

Controlling the Synthesizer without Using a Sequencer

When using a sequence, such as one read from a MIDI file, you don't need to send MIDI commands to the synthesizer yourself. Instead, you just load the sequence into a sequencer, connect the sequencer to the synthesizer, and let it run. The sequencer takes care of scheduling the events, and the result is a predictable musical performance. This scenario works fine when the desired music is known in advance, which is true when it's read from a file.

In some situations, however, the music is generated on the fly as it's playing. For example, the user interface might display a musical keyboard or a guitar fretboard and let the user play notes at will by clicking with the mouse. As another example, an application might use a synthesizer not to play music per se, but to generate sound effects in response to the user's actions. This scenario is typical of games. As a final example, the application might indeed be playing music that's read from a file, but the user interface allows the user to interact with the music, altering it dynamically. In all these cases, the application sends commands directly to the synthesizer, since the MIDI messages need to be delivered immediately, instead of being scheduled for some determinate point in the future.

There are at least two ways of sending a MIDI message to the synthesizer without using a sequencer. The first is to construct a MidiMessage and pass it to the synthesizer using the send method of Receiver. For example, to produce a Middle C (MIDI note number 60) on MIDI channel 5 (one-based) immediately, you could do the following:

    ShortMessage myMsg = new ShortMessage();
    // Play the note Middle C (60) moderately loud
    // (velocity = 93)on channel 4 (zero-based).
    myMsg.setMessage(ShortMessage.NOTE_ON, 4, 60, 93);
    Synthesizer synth = MidiSystem.getSynthesizer();
    Receiver synthRcvr = synth.getReceiver();
    synthRcvr.send(myMsg, -1); // -1 means no time stamp
The second way is to bypass the message-passing layer (that is, the MidiMessage and Receiver API) altogether, and interact with the synthesizer's MidiChannel objects directly. You first need to retrieve the synthesizer's MidiChannel objects, using the following Synthesizer method:
public MidiChannel[] getChannels()
after which you can invoke the desired MidiChannel methods directly. This is a more immediate route than sending the corresponding MidiMessages to the synthesizer's Receiver and letting the synthesizer handle the communication with its own MidiChannels. For example, the code corresponding to the preceding example would be:
    Synthesizer synth = MidiSystem.getSynthesizer();
    MidiChannel chan[] = synth.getChannels();
    // Check for null; maybe not all 16 channels exist.
    if (chan[4] != null) {
         chan[4].noteOn(60, 93);
    }

Getting a Channel's Current State

The MidiChannel interface provides methods that correspond one-to-one to each of the "channel voice" or "channel mode" messages defined by the MIDI specification. We saw one case with the use of the noteOn method in the previous example. However, in addition to these canonical methods, the Java Sound API's MidiChannel interface adds some "get" methods to retrieve the value most recently set by corresponding voice or mode "set" methods:

    int       getChannelPressure()
    int       getController(int controller)
    boolean   getMono()
    boolean   getOmni()
    int	      getPitchBend()
    int	      getPolyPressure(int noteNumber)
    int	      getProgram()
These methods might be useful for displaying channel state to the user, or for deciding what values to send subsequently to the channel.

Muting and Soloing a Channel

The Java Sound API adds the notions of per-channel solo and mute, which are not required by the MIDI specification. These are similar to the solo and mute on the tracks of a MIDI sequence.

If mute is on, this channel will not sound, but other channels are unaffected. If solo is on, this channel, and any other soloed channel, will sound (if it isn't muted), but no other channels will sound. A channel that is both soloed and muted will not sound. The MidiChannel API includes four methods:

    boolean	 getMute()
    boolean	 getSolo()
    void	 setMute(boolean muteState)
    void	 setSolo(boolean soloState)

Permission to Play Synthesized Sound

The audio produced by any installed MIDI synthesizer is typically routed through the sampled-audio system. If your program doesn't have permission to play audio, the synthesizer's sound won't be heard, and a security exception will be thrown. For more information on audio permissions, see the previous discussion of Permission to Use Audio Resources Permission to Use Audio Resources.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Advanced Sequencer Features
Next page: Introduction to the Service Provider Interfaces


Introduction to the Service Provider Interfaces (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Introduction to the Service Provider Interfaces

What Are Services?

Services are units of sound-handling functionality that are automatically available when an application program makes use of an implementation of the Java Sound API. They consist of objects that do the work of reading, writing, mixing, processing, and converting audio and MIDI data. An implementation of the Java Sound API generally supplies a basic set of services, but mechanisms are also included in the API to support the development of new sound services by third-party developers (or by the vendor of the implementation itself). These new services can be "plugged into" an existing installed implementation to expand its functionality without requiring a new release. In the Java Sound API architecture, third-party services are integrated into the system in such a way that an application program's interface to them is the same as the interface to the "built-in" services. In some cases, application developers who use the javax.sound.sampled and javax.sound.midi packages might not even be aware that they are employing third-party services.

Examples of potential third-party, sampled-audio services include:

  • Sound file readers and writers
  • Converters that translate between different audio data formats
  • New audio mixers and input/output devices, whether implemented purely in software, or in hardware with a software interface
Third-party MIDI services might consist of:

  • MIDI file readers and writers
  • Readers for various types of soundbank files (which are often specific to particular synthesizers)
  • MIDI-controlled sound synthesizers, sequencers, and I/O ports, whether implemented purely in software, or in hardware with a software interface

How Services Work

The javax.sound.sampled and javax.sound.midi packages provide functionality to application developers who wish to include sound services in their application programs. These packages are for consumers of sound services, providing interfaces to get information about, control, and access audio and MIDI services. In addition, the Java Sound API also supplies two packages that define abstract classes to be used by providers of sound services: the javax.sound.sampled.spi and javax.sound.midi.spi packages.

Developers of new sound services implement concrete subclasses of the appropriate classes in the SPI packages. These subclasses, along with any additional classes required to support the new service, are placed in a Java Archive (JAR) archive file with a description of the included service or services. When this JAR file is installed in the user's CLASSPATH, the runtime system automatically makes the new service available, extending the functionality of the Java platform's runtime system.

Once the new service is installed, it can be accessed just like any previously installed service. Consumers of services can get information about the new service, or obtain instances of the new service class itself, by invoking methods of the AudioSystem and MidiSystem classes (in the javax.sound.sampled and javax.sound.midi packages, respectively) to return information about the new services, or to return instances of new or existing service classes themselves. Application programs need not—and should not—reference the classes in the SPI packages (and their subclasses) directly to make use of the installed services.

For example, suppose a hypothetical service provider called Acme Software, Inc. is interested in supplying a package that allows application programs to read a new format of sound file (but one whose audio data is in a standard data format). The SPI class AudioFileReader can be subclassed into a class called, say, AcmeAudioFileReader. In the new subclass, Acme would supply implementations of all the methods defined in AudioFileReader; in this case there are only two methods (with argument variants), getAudioFileFormat and getAudioInputStream. Then when an application program attempted to read a sound file that happened to be in Acme's file format, it would invoke methods of the AudioSystem class in javax.sound.sampled to access the file and information about it. The methods AudioSystem.getAudioInputStream and AudioSystem.getAudioFileFormat provide a standard API to read audio streams; with the AcmeAudioFileReader class installed, this interface is extended to support the new file type transparently. Application developers don't need direct access to the newly registered SPI classes: the AudioSystem object methods pass the query on to the installed AcmeAudioFileReader class.

What's the point of having these "factory" classes? Why not permit the application developer to get access directly to newly provided services? That is a possible approach, but having all management and instantiation of services pass through gatekeeper system objects shields the application developer from having to know anything about the identity of installed services. Application developers just use services of value to them, perhaps without even realizing it. At the same time this architecture permits service providers to effectively manage the available resources in their packages.

Often the use of new sound services is transparent to the application program. For example, imagine a situation where an application developer wants to read in a stream of audio from a file. Assuming that thePathName identifies an audio input file, the program does this:

    File theInFile = new File(thePathName);
    AudioInputStream theInStream = AudioSystem.getAudioInputStream(theInFile);
Behind the scenes, the AudioSystem determines what installed service can read the file and asks it to supply the audio data as an AudioInputStream object. The developer might not know or even care that the input audio file is in some new file format (such as Acme's), supported by installed third-party services. The program's first contact with the stream is through the AudioSystem object, and all its subsequent access to the stream and its properties are through the methods of AudioInputStream. Both of these are standard objects in the javax.sound.sampled API; the special handling that the new file format may require is completely hidden.

How Providers Prepare New Services

Service providers supply their new services in specially formatted JAR files, which are to be installed in a directory on the user's system where the Java runtime will find them. JAR files are archive files, each containing sets of files that might be organized in hierarchical directory structures within the archive. Details about the preparation of the class files that go into these archives are discussed in the next few pages, which describe the specifics of the audio and MIDI SPI packages; here we'll just give an overview of the process of JAR file creation.

The JAR file for a new service or services should contain a class file for each service supported in the JAR file. Following the Java platform's convention, each class file has the name of the newly defined class, which is a concrete subclass of one of the abstract service provider classes. The JAR file also must include any supporting classes required by the new service implementation. So that the new service or services can be located by the runtime system's service provider mechanism, the JAR file must also contain special files (described below) that map the SPI class names to the new subclasses being defined.

To continue from our example above, say Acme Software, Inc. is distributing a package of new sampled-audio services. Let's suppose this package consists of two new services:

  • The AcmeAudioFileReader class, which was mentioned above, and which is a subclass of AudioFileReader
  • A subclass of AudioFileWriter called AcmeAudioFileWriter, which will write sound files in Acme's new format
Starting from an arbitrary directory—let's call it /devel—where we want to do the build, we create subdirectories and put the new class files in them, organized in such a manner as to give the desired pathname by which the new classes will be referenced:

    com/acme/AcmeAudioFileReader.class
    com/acme/AcmeAudioFileWriter.class
In addition, for each new SPI class being subclassed, we create a mapping file in a specially named directory META-INF/services. The name of the file is the name of the SPI class being subclassed, and the file contains the names of the new subclasses of that SPI abstract class.

We create the file

META-INF/services/javax.sound.sampled.spi.AudioFileReader, which consists of

    # Providers of sound file-reading services
    # (a comment line begins with a pound sign)
    com.acme.AcmeAudioFileReader

and also the file

META-INF/services/javax.sound.sampled.spi.AudioFileWriter, which consists of

   # Providers of sound file-writing services
    com.acme.AcmeAudioFileWriter

Now we run jar from any directory with the command line:

jar cvf acme.jar -C /devel .
The -C option causes jar to switch to the /devel directory, instead of using the directory in which the command is executed. The final period argument instructs jar to archive all the contents of that directory (namely, /devel), but not the directory itself.

This run will create the file acme.jar with the contents:

com/acme/AcmeAudioFileReader.class
com/acme/AcmeAudioFileWriter.class
META-INF/services/javax.sound.sampled.spi.AudioFileReader
META-INF/services/javax.sound.sampled.spi.AudioFileWriter
META-INF/Manifest.mf
The file Manifest.mf, which is generated by the jar utility itself, is a list of all the files contained in the archive.

How Users Install New Services

For end users (or system administrators) who wish to get access to a new service through their application programs, installation is simple. They place the provided JAR file in a directory in their CLASSPATH. Upon execution, the Java runtime will find the referenced classes when needed.

It's not an error to install more than one provider for the same service. For example, two different service providers might supply support for reading the same type of sound file. In such a case, the system arbitrarily chooses one of the providers. Users who care which provider is chosen should install only the desired one.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Synthesizing Sound
Next page: Providing Sampled-Audio Services


Providing Sampled-Audio Services (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Providing Sampled-Audio Services

As you know, the Java Sound API includes two packages, javax.sound.sampled.spi and javax.sound.midi.spi, that define abstract classes to be used by developers of sound services. By implementing and installing a subclass of one of these abstract classes, a service provider registers the new service, extending the functionality of the runtime system. This page tells you how to go about using the javax.sound.sampled.spi package to provide new services for handling sampled audio.

There are four abstract classes in the javax.sound.sampled.spi package, representing four different types of services that you can provide for the sampled-audio system:

  • AudioFileWriter provides sound file-writing services. These services make it possible for an application program to write a stream of audio data to a file of a particular type.

  • AudioFileReader provides file-reading services. These services enable an application program to ascertain a sound file's characteristics, and to obtain a stream from which the file's audio data can be read.

  • FormatConversionProvider provides services for converting audio data formats. These services allow an application program to translate audio streams from one data format to another.

  • MixerProvider provides management of a particular kind of mixer. This mechanism allows an application program to obtain information about, and access instances of, a given kind of mixer.

To recapitulate earlier discussions, service providers can extend the functionality of the runtime system. A typical SPI class has two types of methods: ones that respond to queries about the types of services available from a particular provider, and ones that either perform the new service directly, or return instances of objects that actually provide the service. The runtime environment's service-provider mechanism provides registration of installed services with the audio system, and management of the new service provider classes.

In essence there is a double isolation of the service instances from the application developer. An application program never directly creates instances of the service objects, such as mixers or format converters, that it needs for its audio processing tasks. Nor does the program even directly request these objects from the SPI classes that administer them. The application program makes requests to the AudioSystem object in the javax.sound.sampled package, and AudioSystem in turn uses the SPI objects to process these queries and service requests.

The existence of new audio services might be completely transparent to both the user and the application programmer. All application references are through standard objects of the javax.sound.sampled package, primarily AudioSystem, and the special handling that new services might be providing is often completely hidden.

In this discussion, we'll continue the previous convention of referring to new SPI subclasses by names like AcmeMixer and AcmeMixerProvider.

Providing Audio File-Writing Services

Let's start with AudioFileWriter, one of the simpler SPI classes.

A subclass that implements the methods of AudioFileWriter must provide implementations of a set of methods to handle queries about the file formats and file types supported by the class, as well as provide methods that actually write out a supplied audio data stream to a File or OutputStream.

AudioFileWriter includes two methods that have concrete implementations in the base class:

boolean isFileTypeSupported(AudioFileFormat.Type fileType)
boolean isFileTypeSupported(AudioFileFormat.Type fileType, AudioInputStream stream)
The first of these methods informs the caller whether this file writer can write sound files of the specified type. This method is a general inquiry, it will return true if the file writer can write that kind of file, assuming the file writer is handed appropriate audio data. However, the ability to write a file can depend on the format of the specific audio data that's handed to the file writer. A file writer might not support every audio data format, or the constraint might be imposed by the file format itself. (Not all kinds of audio data can be written to all kinds of sound files.) The second method is more specific, then, asking whether a particular AudioInputStream can be written to a particular type of file.

Generally, you won't need to override these two concrete methods. Each is simply a wrapper that invokes one of two other query methods and iterates over the results returned. These other two query methods are abstract and therefore need to be implemented in the subclass:

abstract AudioFileFormat.Type[] getAudioFileTypes()
abstract AudioFileFormat.Type[] getAudioFileTypes(AudioInputStream stream)
These methods correspond directly to the previous two. Each returns an array of all the supported file types-all that are supported in general, in the case of the first method, and all that are supported for a specific audio stream, in the case of the second method. A typical implementation of the first method might simply return an array that the file writer's constructor initializes. An implementation of the second method might test the stream's AudioFormat object to see whether it's a data format that the requested type of file supports.

The final two methods of AudioFileWriter do the actual file-writing work:

abstract int write(AudioInputStream stream,
     AudioFileFormat.Type fileType, java.io.File out)
abstract int write(AudioInputStream stream,
     AudioFileFormat.Type fileType, java.io.OutputStream out)
These methods write a stream of bytes representing the audio data to the stream or file specified by the third argument. The details of how this is done depend on the structure of the specified type of file. The write method must write the file's header and the audio data in the manner prescribed for sound files of this format (whether it's a standard type of sound file or a new, possibly proprietary one).

Providing Audio File-Reading Services

The AudioFileReader class consists of six abstract methods that your subclass needs to implement-actually, two different overloaded methods, each of which can take a File, URL, or InputStream argument. The first of these overloaded methods accepts queries about the file format of a specified file:

abstract AudioFileFormat getAudioFileFormat(java.io.File file)
abstract AudioFileFormat getAudioFileFormat(java.io.InputStream stream)
abstract AudioFileFormat getAudioFileFormat(java.net.URL url)
A typical implementation of getAudioFileFormat method reads and parses the sound file's header to ascertain its file format. See the description of the AudioFileFormat class to see what fields need to be read from the header, and refer to the specification for the particular file type to figure out how to parse the header.

Because the caller providing a stream as an argument to this method expects the stream to be unaltered by the method, the file reader should generally start by marking the stream. After reading to the end of the header, it should reset the stream to its original position.

The other overloaded AudioFileReader method provides file-reading services, by returning an AudioInputStream from which the file's audio data can be read:

abstract AudioInputStream getAudioInputStream(java.io.File file)
abstract AudioInputStream getAudioInputStream(java.io.InputStream stream)
abstract AudioInputStream getAudioInputStream(java.net.URL url)
Typically, an implementation of getAudioInputStream returns an AudioInputStream wound to the beginning of the file's data chunk (after the header), ready for reading. It would be conceivable, though, for a file reader to return an AudioInputStream whose audio format represents a stream of data that is in some way decoded from what is contained in the file. The important thing is that the method return a formatted stream from which the audio data contained in the file can be read. The AudioFormat encapsulated in the returned AudioInputStream object will inform the caller about the stream's data format, which is usually, but not necessarily, the same as the data format in the file itself.

Generally, the returned stream is an instance of AudioInputStream; it's unlikely you would ever need to subclass AudioInputStream.

Providing Format-Conversion Services

A FormatConversionProvider subclass transforms an AudioInputStream that has one audio data format into one that has another format. The former (input) stream is referred to as the source stream, and the latter (output) stream is referred to as the target stream. Recall that an AudioInputStream contains an AudioFormat, and the AudioFormat in turn contains a particular type of data encoding, represented by an AudioFormat.Encoding object. The format and encoding in the source stream are called the source format and source encoding, and those in the target stream are likewise called the target format and target encoding.

The work of conversion is performed in the overloaded abstract method of FormatConversionProvider called getAudioInputStream. The class also has abstract query methods for learning about all the supported target and source formats and encodings. There are concrete wrapper methods for querying about a specific conversion.

The two variants of getAudioInputStream are:

abstract AudioInputStream getAudioInputStream(AudioFormat.Encoding targetEncoding,
     AudioInputStream sourceStream)
and
abstract AudioInputStream getAudioInputStream(AudioFormat targetFormat,
     AudioInputStream sourceStream)
These differ in the first argument, according to whether the caller is specifying a complete target format or just the format's encoding.

A typical implementation of getAudioInputStream works by returning a new subclass of AudioInputStream that wraps around the original (source) AudioInputStream and applies a data format conversion to its data whenever a read method is invoked. For example, consider the case of a new FormatConversionProvider subclass called AcmeCodec, which works with a new AudioInputStream subclass called AcmeCodecStream.

The implementation of AcmeCodec's second getAudioInputStream method might be:

public AudioInputStream getAudioInputStream
      (AudioFormat outputFormat, AudioInputStream stream) {
        AudioInputStream cs = null;
        AudioFormat inputFormat = stream.getFormat();
        if (inputFormat.matches(outputFormat) ) {
            cs = stream;
        } else {
            cs = (AudioInputStream)
                (new AcmeCodecStream(stream, outputFormat));
            tempBuffer = new byte[tempBufferSize];
        }
        return cs;
    }
The actual format conversion takes place in new read methods of the returned AcmeCodecStream, a subclass of AudioInputStream. Again, application programs that access this returned AcmeCodecStream simply operate on it as an AudioInputStream, and don't need to know the details of its implementation.

The other methods of a FormatConversionProvider all permit queries about the input and output encodings and formats that the object supports. The following four methods, being abstract, need to be implemented:

abstract AudioFormat.Encoding[] getSourceEncodings()
abstract AudioFormat.Encoding[] getTargetEncodings()
abstract AudioFormat.Encoding[] getTargetEncodings(
    AudioFormat sourceFormat)
abstract  AudioFormat[] getTargetFormats(
    AudioFormat.Encoding targetEncoding,
    AudioFormat sourceFormat)

As in the query methods of the AudioFileReader class discussed above, these queries are typically handled by checking private data of the object and, for the latter two methods, comparing them against the argument(s).

The remaining four FormatConversionProvider methods are concrete and generally don't need to be overridden:

boolean isConversionSupported(
    AudioFormat.Encoding targetEncoding,
    AudioFormat sourceFormat)
boolean isConversionSupported(AudioFormat targetFormat,
    AudioFormat sourceFormat)
boolean isSourceEncodingSupported(
    AudioFormat.Encoding sourceEncoding)
boolean isTargetEncodingSupported(
    AudioFormat.Encoding targetEncoding)
As with AudioFileWriter.isFileTypeSupported(), the default implementation of each of these methods is essentially a wrapper that invokes one of the other query methods and iterates over the results returned.

Providing New Types of Mixers

As its name implies, a MixerProvider supplies instances of mixers. Each concrete MixerProvider subclass acts as a factory for the Mixer objects used by an application program. Of course, defining a new MixerProvider only makes sense if one or more new implementations of the Mixer interface are also defined. As in the FormatConversionProvider example above, where our getAudioInputStream method returned a subclass of AudioInputStream that performed the conversion, our new class AcmeMixerProvider has a method getMixer that returns an instance of another new class that implements the Mixer interface. We'll call the latter class AcmeMixer. Particularly if the mixer is implemented in hardware, the provider might support only one static instance of the requested device. If so, it should return this static instance in response to each invocation of getMixer.

Since AcmeMixer supports the Mixer interface, application programs don't require any additional information to access its basic functionality. However, if AcmeMixer supports functionality not defined in the Mixer interface, and the vendor wants to make this extended functionality accessible to application programs, the mixer should of course be defined as a public class with additional, well-documented public methods, so that a program that wishes to make use of this extended functionality can import AcmeMixer and cast the object returned by getMixer to this type.

The other two methods of MixerProvider are:

abstract Mixer.Info[] getMixerInfo()
and
boolean isMixerSupported(Mixer.Info info)
These methods allow the audio system to determine whether this particular provider class can produce a device that an application program needs. In other words, the AudioSystem object can iterate over all the installed MixerProviders to see which ones, if any, can supply the device that the application program has requested of the AudioSystem. The getMixerInfo method returns an array of objects containing information about the kinds of mixer available from this provider object. The system can pass these information objects, along with those from other providers, to an application program.

A single MixerProvider can provide more than one kind of mixer. When the system invokes the MixerProvider's getMixerInfo method, it gets a list of information objects identifying the different kinds of mixer that this provider supports. The system can then invoke MixerProvider.getMixer(Mixer.Info) to obtain each mixer of interest.

Your subclass needs to implement getMixerInfo, as it's abstract. The isMixerSupported method is concrete and doesn't generally need to be overridden. The default implementation simply compares the provided Mixer.Info to each one in the array returned by getMixerInfo.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Introduction to the Service Provider Interfaces
Next page: Providing MIDI Services


Providing MIDI Services (The Java™ Tutorials > Sound)

Trail: Sound
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
Home Page > Sound
« Previous • Trail • Next »
Providing MIDI Services

Introduction to the Service Provider Interfaces explained that the javax.sound.sampled.spi and javax.sound.midi.spi packages define abstract classes to be used by developers of sound services. By implementing a subclass of one of these abstract classes, a service provider can create a new service that extends the functionality of the runtime system. The previous section covered the use of the javax.sound.sampled.spi package. This section discusses how to use the javax.sound.midi.spi package to provide new services for handling MIDI devices and files.

There are four abstract classes in the javax.sound.midi.spi package, which represent four different types of services that you can provide for the MIDI system:

  • MidiFileWriter provides MIDI file-writing services. These services make it possible for an application program to save, to a MIDI file, a MIDI Sequence that it has generated or processed.

  • MidiFileReader provides file-reading services that return a MIDI Sequence from a MIDI file for use in an application program.

  • MidiDeviceProvider supplies instances of one or more specific types of MIDI device, possibly including hardware devices.

  • SoundbankReader supplies soundbank file-reading services. Concrete subclasses of SoundbankReader parse a given soundbank file, producing a Soundbank object that can be loaded into a Synthesizer.

An application program will not directly create an instance of a service object—whether a provider object, such as a MidiDeviceProvider, or an object, such as a Synthesizer, that is supplied by the provider object. Nor will the program directly refer to the SPI classes. Instead, the application program makes requests to the MidiSystem object in the javax.sound.midi package, and MidiSystem in turn uses concrete subclasses of the javax.sound.midi.spi classes to process these requests.

Providing MIDI File-Writing Services

There are three standard MIDI file formats, all of which an implementation of the Java Sound API can support: Type 0, Type 1, and Type 2. These file formats differ in their internal representation of the MIDI sequence data in the file, and are appropriate for different kinds of sequences. If an implementation doesn't itself support all three types, a service provider can supply the support for the unimplemented ones. There are also variants of the standard MIDI file formats, some of them proprietary, which similarly could be supported by a third-party vendor.

The ability to write MIDI files is provided by concrete subclasses of MidiFileWriter. This abstract class is directly analogous to javax.sampled.spi.AudioFileWriter. Again, the methods are grouped into query methods for learning what types of files can be written, and methods for actually writing a file. As with AudioFileWriter, two of the query methods are concrete:

boolean isFileTypeSupported(int fileType)
boolean isFileTypeSupported(int fileType, Sequence sequence)
The first of these provides general information about whether the file writer can ever write the specified type of MIDI file type. The second method is more specific: it asks whether a particular Sequence can be written to the specified type of MIDI file. Generally, you don't need to override either of these two concrete methods. In the default implementation, each invokes one of two other corresponding query methods and iterates over the results returned. Being abstract, these other two query methods need to be implemented in the subclass:
abstract int[] getMidiFileTypes()
abstract int[] getMidiFileTypes(Sequence sequence)
The first of these returns an array of all the file types that are supported in general. A typical implementation might initialize the array in the file writer's constructor and return the array from this method. From that set of file types, the second method finds the subset to which the file writer can write the given Sequence. In accordance with the MIDI specification, not all types of sequences can be written to all types of MIDI files.

The write methods of a MidiFileWriter subclass perform the encoding of the data in a given Sequence into the correct data format for the requested type of MIDI file, writing the coded stream to either a file or an output stream:

abstract int write(Sequence in, int fileType,
                   java.io.File out)
abstract int write(Sequence in, int fileType,
                   java.io.OutputStream out)
To do this, the write method must parse the Sequence by iterating over its tracks, construct an appropriate file header, and write the header and tracks to the output. The MIDI file's header format is, of course, defined by the MIDI specification. It includes such information as a "magic number" identifying this as a MIDI file, the header's length, the number of tracks, and the sequence's timing information (division type and resolution). The rest of the MIDI file consists of the track data, in the format defined by the MIDI specification.

Let's briefly look at how the application program, MIDI system, and service provider cooperate in writing a MIDI file. In a typical situation, an application program has a particular MIDI Sequence to save to a file. The program queries the MidiSystem object to see what MIDI file formats, if any, are supported for the particular Sequence at hand, before attempting to write the file. The MidiSystem.getMidiFileTypes(Sequence) method returns an array of all the MIDI file types to which the system can write a particular sequence. It does this by invoking the corresponding getMidiFileTypes method for each of the installed MidiFileWriter services, and collecting and returning the results in an array of integers that can be thought of as a master list of all file types compatible with the given Sequence. When it comes to writing the Sequence to a file, the call to MidiSystem.write is passed an integer representing a file type, along with the Sequence to be written and the output file; MidiSystem uses the supplied type to decide which installed MidiFileWriter should handle the write request, and dispatches a corresponding write to the appropriate MidiFileWriter.

Providing MIDI File-Reading Services

The MidiFileReader abstract class is directly analogous to javax.sampled.spi.AudioFileReader class. Both consist of two overloaded methods, each of which can take a File, URL, or InputStream argument. The first of the overloaded methods returns the file format of a specified file. In the case of MidiFileReader, the API is:

abstract MidiFileFormat getMidiFileFormat(java.io.File file)
abstract MidiFileFormat getMidiFileFormat(
    java.io.InputStream stream)
abstract MidiFileFormat getMidiFileFormat(java.net.URL url)
Concrete subclasses must implement these methods to return a filled-out MidiFileFormat object describing the format of the specified MIDI file (or stream or URL), assuming that the file is of a type supported by the file reader and that it contains valid header information. Otherwise, an InvalidMidiDataException should be thrown.

The other overloaded method returns a MIDI Sequence from a given file, stream, or URL :

abstract Sequence getSequence(java.io.File file)
abstract Sequence getSequence(java.io.InputStream stream)
abstract Sequence getSequence(java.net.URL url)
The getSequence method performs the actual work of parsing the bytes in the MIDI input file and constructing a corresponding Sequence object. This is essentially the inverse of the process used by MidiFileWriter.write. Because there is a one-to-one correspondence between the contents of a MIDI file as defined by the MIDI specification and a Sequence object as defined by the Java Sound API, the details of the parsing are straightforward. If the file passed to getSequence contains data that the file reader can't parse (for example, because the file has been corrupted or doesn't conform to the MIDI specification), an InvalidMidiDataException should be thrown.

Providing Particular MIDI Devices

A MidiDeviceProvider can be considered a factory that supplies one or more particular types of MIDI device. The class consists of a method that returns an instance of a MIDI device, as well as query methods to learn what kinds of devices this provider can supply.

As with the other javax.sound.midi.spi services, application developers get indirect access to a MidiDeviceProvider service through a call to MidiSystem methods, in this case MidiSystem.getMidiDevice and MidiSystem.getMidiDeviceInfo. The purpose of subclassing MidiDeviceProvider is to supply a new kind of device, so the service developer must also create an accompanying class for the device being returned—just as we saw with MixerProvider in the javax.sound.sampled.spi package. There, the returned device's class implemented the javax.sound.sampled.Mixer interface; here it implements the javax.sound.midi.MidiDevice interface. It might also implement a subinterface of MidiDevice, such as Synthesizer or Sequencer.

Because a single subclass of MidiDeviceProvider can provide more than one type of MidiDevice, the getDeviceInfo method of the class returns an array of MidiDevice.Info objects enumerating the different MidiDevices available:

abstract MidiDevice.Info[] getDeviceInfo()

The returned array can contain a single element, of course. A typical implementation of the provider might initialize an array in its constructor and return it here. This allows MidiSystem to iterate over all installed MidiDeviceProviders to construct a list of all installed devices. MidiSystem can then return this list (MidiDevice.Info[] array) to an application program.

MidiDeviceProvider also includes a concrete query method:

boolean isDeviceSupported(MidiDevice.Info info)
This method permits the system to query the provider about a specific kind of device. Generally, you don't need to override this convenience method. The default implementation iterates over the array returned by getDeviceInfo and compares the argument to each element.

The third and final MidiDeviceProvider method returns the requested device:

abstract MidiDevice getDevice(MidiDevice.Info info)
This method should first test the argument to make sure it describes a device that this provider can supply. If it doesn't, it should throw an IllegalArgumentException. Otherwise, it returns the device.

Providing Soundbank File-Reading Services

A SoundBank is a set of Instruments that can be loaded into a Synthesizer. An Instrument is an implementation of a sound-synthesis algorithm that produces a particular sort of sound, and includes accompanying name and information strings. A SoundBank roughly corresponds to a bank in the MIDI specification, but it's a more extensive and addressable collection; it can perhaps better be thought of as a collection of MIDI banks.

SoundbankReader consists of a single overloaded method, which the system invokes to read a Soundbank object from a soundbank file:

abstract Soundbank getSoundbank(java.io.File file)
abstract Soundbank getSoundbank(java.io.InputStream stream)
abstract Soundbank getSoundbank(java.net.URL url)

Concrete subclasses of SoundbankReader will work in tandem with particular provider-defined implementations of SoundBank, Instrument, and Synthesizer to allow the system to load a SoundBank from a file into an instance of a particular Synthesizer class. Synthesis techniques may differ wildly from one Synthesizer to another, and, as a consequence, the data stored in an Instrument or SoundBank providing control or specification data for the synthesis process of a Synthesizer can take a variety of forms. One synthesis technique may require only a few bytes of parameter data; another may be based on extensive sound samples. The resources present in a SoundBank will depend upon the nature of the Synthesizer into which they get loaded, and therefore the implementation of the getSoundbank method of a SoundbankReader subclass has access to knowledge of a particular kind of SoundBank. In addition, a particular subclass of SoundbankReader understands a particular file format for storing the SoundBank data. That file format may be vendor-specific and proprietary.

SoundBank is just an interface, with only weak constraints on the contents of a SoundBank object. The methods an object must support to implement this interface (getResources, getInstruments, getVendor, getName, etc.) impose loose requirements on the data that the object contains. For example, getResources and getInstruments can return empty arrays. The actual contents of a subclassed SoundBank object, in particular its instruments and its non-instrument resources, are defined by the service provider. Thus, the mechanism of parsing a soundbank file depends entirely on the specification of that particular kind of soundbank file.

Soundbank files are created outside the Java Sound API, typically by the vendor of the synthesizer that can load that kind of soundbank. Some vendors might supply end-user tools for creating such files.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Providing Sampled-Audio Services
Next page: End of Trail


Trail: JavaBeans(TM) (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: JavaBeans(TM)

JavaBeans™ is a portable, platform-independent component model written in the Java programming language. The JavaBeans architecture was built through a collaborative industry effort and enables developers to write reusable components in the Java programming language.

With the JavaBeans API you can create reuseable, platform-independent components. Using JavaBeans-compliant application builder tools, you can combine these components into applets, applications, or composite components.

JavaBean components are known as beans. Beans are dynamic in that they can be changed or customized. Through the design mode of a builder tool, you use the property sheet or bean customizer to customize the bean and then save (persist) your customized beans.

Note: This tutorial covers the Java Beans functionality available in the Beans module of the NetBeans IDE. Due to this module has been removed from the NetBeans IDE 6.0 (see the NetBeans project page for more information) it is recommended to use version 5.5.1 to obtain the full range of the Java Beans features.

This trail is represented in the following lessons:

JavaBeans Concepts describes the basic notion of JavaBeans and what makes a bean.

Using the NetBeans GUI Builder describes the NetBeans GUI Builder within the scope of operating with bean objects.

Writing a Simple Bean walks you through creating a rudimentary bean, saving the bean, adding the bean to the Palette of the NetBeans GUI Builder and inspecting the bean's properties and events.

Bean Properties explains how to give your beans properties: bean appearance and behavior characteristics that are customizable at design time.

Manipulating Events describes the JavaBeans event manipulating capabilities. If you are not familiar with event handling, you might want to read up on Writing Event Listeners to prepare for this material.

Bean Persistence explains how to save and restore beans to their customized state.

Long Term Persistence explains how to save and load your beans in the XML format using the XMLDecoder and XMLEncoder classes.

Introspection describes how methods, properties, and events are discovered in the beans that you write.

Bean Customization introduces you to property editors, and the Customizer interface.

Using the BeanContext API covers The Extensible Runtime Containment and Services Protocol, also known as beancontext.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: JavaBeans Concepts


Lesson: JavaBeans Concepts (The Java™ Tutorials > JavaBeans(TM))

Trail: JavaBeans(TM)
Home Page > JavaBeans(TM)
« Previous • Trail • Next »
Lesson: JavaBeans Concepts

The JavaBeans™ architecture is based on a component model which enables developers to create software units called components. Components are self-contained, reusable software units that can be visually assembled into composite components, applets, applications, and servlets using visual application builder tools. JavaBean components are known as beans.

A set of APIs describes a component model for a particular language. The JavaBeans API specificationdescribes the core detailed elaboration for the JavaBeans component architecture.

Beans are dynamic in that they can be changed or customized. Through the design mode of a builder tool you can use the Properties window of the bean to customize the bean and then save (persist) your beans using visual manupulation. You can select a bean from the toolbox, drop it into a form, modify its appearance and behavior, define its interaction with other beans, and combine it and other beans into an applet, application, or a new bean.

The following list briefly describes key bean concepts.

  • Builder tools discover a bean's features (that is, its properties, methods, and events) by a process known as introspection. Beans support introspection in two ways:
    • By adhering to specific rules, known as design patterns, when naming bean features. The Introspector class examines beans for these design patterns to discover bean features. The Introspector class relies on the core reflection API. The trail The Reflection API is an excellent place to learn about reflection.
    • By explicitly providing property, method, and event information with a related bean information class. A bean information class implements the BeanInfo interface. A BeanInfo class explicitly lists those bean features that are to be exposed to application builder tools.
  • Properties are the appearance and behavior characteristics of a bean that can be changed at design time. Builder tools introspect on a bean to discover its properties and expose those properties for manipulation.

  • Beans expose properties so they can be customized at design time. Customization is supported in two ways: by using property editors, or by using more sophisticated bean customizers.

  • Beans use events to communicate with other beans. A bean that is to receive events (a listener bean) registers with the bean that fires the event (a source bean). Builder tools can examine a bean and determine which events that bean can fire (send) and which it can handle (receive).

  • Persistence enables beans to save and restore their state. After changing a bean's properties, you can save the state of the bean and restore that bean at a later time with the property changes intact. The JavaBeans architecture uses Java Object Serialization to support persistence.

  • A bean's methods are no different from Java methods, and can be called from other beans or a scripting environment. By default all public methods are exported.

Beans vary in functionality and purpose. You have probably met some of the following beans in your programming practice:

  • GUI (graphical user interface)
  • Non-visual beans, such as a spelling checker
  • Animation applet
  • Spreadsheet application

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: Using the NetBeans GUI Builder


Lesson: Using the NetBeans GUI Builder (The Java™ Tutorials > JavaBeans(TM))

Trail: JavaBeans(TM)
Home Page > JavaBeans(TM)
« Previous • Trail • Next »
Lesson: Using the NetBeans GUI Builder
Note: This tutorial covers the Java Beans functionality available in the Beans module of the NetBeans IDE. Due to this module has been removed from the NetBeans IDE 6.0 (see the NetBeans project page for more information) it is recommended to use version 5.5.1 to obtain the full range of the Java Beans features.

This lesson explains how to use the NetBeans IDE GUI Builder to work with beans. In preparation for working with the GUI Builder, you should be first familiar with the key NetBeans concepts which are explained in the Using NetBeans IDE Guide.

This lesson guides you through the process of creating a bean pattern in the NetBeans projects, introduces the user interface of the GUI Builder, and explains how to add your bean object to the palette.

Creating a New Project

In the NetBeans IDE, you always work in a project where you store sources and files. To create a new project, perform the following steps:

  1. Select New Project from the File menu. You can also click the New Project button in the IDE toolbar.
  2. In the Categories pane, select the General node. In the Projects pane, choose the Java Application type. Click the Next button.
  3. Enter MyBean in the Project Name field and specify the project location. Do not create a Main class here, because later you will create a new Java class in this project.
  4. Click the Finish button.

This figure represents the expanded MyBean node in the Projects list.

This figure represents the expanded MyBean node in the Projects list

Creating a New Form

After creating a new project, the next step is to create a form within which the JavaBeans components and other required GUI components, will be placed.

To create a new form, perform the following sequence of actions:

  1. In the Projects list, expand the MyBean node, right-click on the <default package> node and choose New|JFrame Form from the pop-up menu.
  2. Enter MyForm as the Class Name.
  3. Click the Finish button.
The IDE creates the MyForm form and the MyForm class within the MyBean application and opens the MyForm form in the GUI Builder.

This figure represents the Projects list, where the MyForm class is located.

This figure represents the Projects list, where the MyForm class is

The GUI Builder Interface

When the JFrame form is added to your application, the IDE opens the newly-created form in an Editor tab with a toolbar containing the following buttons:

  • The Selection Mode button – Selection Mode enables you to select one or more objects in the Design Area.
  • The Connection Mode command – Connection Mode enables you to set a connection between objects by specifying an event.
  • The Preview Design command – Preview Design enables you to preview the form layout.
  • The Align Left in Column command The Align Right in Column command The Align Up in Row command The Align Down in Row command – Align commands enable you to align selected objects.
  • The Change Horizontal Resizability command The Change Vertical Resizability command – Change Resizability enables you to set up vertical and horizontal resizing.

When the MyForm form opens in the GUI Builder's Design view, three additional windows appear, enabling you to navigate, organize, and edit GUI forms. These windows include the following:

  • Design Area. The primary window for creating and editing Java GUI forms. Source and Design toggle buttons enable you to switch between view a class's source code and a graphical view of the GUI components. Click on an object to select it in the Design Area. For a multiple selection, hold down the Ctrl key while clicking on objects.
  • Inspector. Representation of a tree hierarchy of all the components in your application. The Inspector highlights the component in the tree that is currently being edited.
  • Palette. A customizable list of available components containing groups for Swing, AWT, Borders, and Beans components. This window enables you to create, remove, and rearrange the categories displayed in the palette using the customizer.
  • Properties Window. A display of the properties of the component currently selected in the GUI Builder, Inspector window, Projects window, or Files window.

If you click the Source button, the IDE displays the application's Java source code in the editor. Sections of code that are automatically generated by the GUI Builder are indicated by blue areas. These blue areas are protected from editing in the Source view. You can only edit code appearing in the white areas of the editor when in Source view. When you make your changes in the Design View, the IDE updates the file's sources.

Creating a Bean

To create your own bean object and add it to the palette for the bean group, execute the following procedure:

  1. Select the <default package> node in the MyBean project.
  2. Choose New|Java Class from the pop-up menu.
  3. Specify the name for the new class, for example, MyBean, then press the Finish button.
  4. Expand the MyBean.java and MyBean node and select the Bean Patterns node.
  5. Right-click on the Bean Patterns node and choose Add|Property from the pop-up menu.
  6. Enter YourName in the PropertyName field as shown in the following figure, then press OK:

    7. Adding a new property

  7. Now you can analyze the automatically generated code. Notice that set and get methods were included:
    8. public class MyBean {

    /** Creates a new instance of MyBean */
    public MyBean() {
    }

    /**
     * Holds value of property yourName.
     */
    private String yourName;

    /**
     * Getter for property yourName.
     * @return Value of property yourName.
     */
    public String getYourName() {
        return this.yourName;
    }

    /**
     * Setter for property yourName.
     * @param yourName New value of property yourName.
     */
    public void setYourName(String yourName) {
        this.yourName = yourName;
    }

}
  8. Right-click the MyBean node in the MyBean project tree and choose Tools |Add to Palette from the pop-up menu.
  9. Select the Beans group in the Palette tree to add your bean.

Now you can switch to the Palette window by choosing Palette from the Windows menu and make sure that the MyBean component was added to the Beans group.

So far you have created a bean, set the YourName property, and added this bean as a component to the palette.

Adding Components to the Form

Now you can use the Free Design of the GUI Builder and add the MyBean component and other standard Swing components to MyForm.
  1. Select the MyForm node in the project tree.
  2. Drag the JLabel Swing component from the Palette window to the Design Area. Double-click the component and change the text property to "Enter your name:".
  3. Drag the JTextField component from the Palette window to the Design Area. Double-click the component and empty the text field.
  4. Drag the JButton component from the Palette window to the Design Area. Double-click the component and enter "OK" as the text property.
  5. Add another button and enter "Cancel" as its text property.
  6. Align components by using the appropriate align commands.
  7. Before you drag the MyBean component from the Pallete you must compile your project because the MyBean component is non-visual and cannot be operated as a visual component. When you Drag and Drop the MyBean component it will not appear in the Design Area. However, you can view it in the Inspector window by expanding the Other Components node, as shown in the following figure.

  8. Adding a new bean

To summarize, in the previous steps you created a project, developed a JFrame form, added a bean object and included it in your project as a non-visual component. Later in this trail you will learn how to change properties for the bean component and handle events by using the NetBeans GUI Builder.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Writing a Simple Bean


Lesson: Writing a Simple Bean (The Java™ Tutorials > JavaBeans(TM))

Trail: JavaBeans(TM)
Home Page > JavaBeans(TM)
« Previous • Trail • Next »
Lesson: Writing a Simple Bean
Note: This tutorial covers the Java Beans functionality available in the Beans module of the NetBeans IDE. Due to this module has been removed from the NetBeans IDE 6.0 (see the NetBeans project page for more information) it is recommended to use version 5.5.1 to obtain the full range of the Java Beans features.
In this section you will learn more about beans by performing the following actions:
  • Creating a simple bean
  • Compiling the bean
  • Generating a Java Archive (JAR) file
  • Loading the bean into the GUI Builder of the NetBeans IDE
  • Inspecting the bean's properties and events

Your bean will be named SimpleBean. Here are the steps to create it:

  1. Write the SimpleBean code. Put it in a file named SimpleBean.java, in the directory of your choice. Here's the code:
    import java.awt.Color;
import java.beans.XMLDecoder;
import javax.swing.JLabel;
import java.io.Serializable;

public class SimpleBean extends JLabel
                        implements Serializable {
    public SimpleBean() {
        setText( "Hello world!" );
        setOpaque( true );
        setBackground( Color.RED );
        setForeground( Color.YELLOW );
        setVerticalAlignment( CENTER );
        setHorizontalAlignment( CENTER );
    }
}

    SimpleBean extends the javax.swing.JLabel graphic component and inherits its properties, which makes the SimpleBean a visual component. SimpleBean also implements the java.io.Serializable interface. Your bean may implement either the Serializable or the Externalizable interface.

  2. Create a manifest, the JAR file, and the class file SimpleBean.class. Use the Apache Ant tool to create these files. Apache Ant is a Java-based build tool that enables you to generate XML-based configurations files as follows:
     <?xml version="1.0" encoding="ISO-8859-1"?>

 <project default="build">

  <dirname property="basedir" file="${ant.file}"/>

  <property name="beanname" value="SimpleBean"/>
  <property name="jarfile" value="${basedir}/${beanname}.jar"/>

  <target name="build" depends="compile">
      <jar destfile="${jarfile}" basedir="${basedir}" includes="*.class">
          <manifest>
              <section name="${beanname}.class">
                 <attribute name="Java-Bean" value="true"/>
              </section>
          </manifest>
      </jar>
  </target>

  <target name="compile">
      <javac destdir="${basedir}">
          <src location="${basedir}"/>
      </javac>
  </target>

  <target name="clean">
      <delete file="${jarfile}">
          <fileset dir="${basedir}" includes="*.class"/>
      </delete>
  </target>

</project>

    It is recommended to save an XML script in the build.xml file, because Ant recognizes this file name automatically.

  3. Load the JAR file. Use the NetBeans IDE GUI Builder to load the jar file as follows:
    1. Start NetBeans.
    2. From the File menu select "New Project" to create a new application for your bean. You can use "Open Project" to add your bean to an existing application.
    3. Create a new application using the New Project Wizard.
    4. Select a newly created project in the List of Projects, expand the Source Packages node, and select the Default Package element.
    5. Click the right mouse button and select New|JFrameForm from the pop-up menu.
    6. Select the newly created Form node in the Project Tree. A blank form opens in the GUI Builder view of an Editor tab.
    7. Open the Palette Manager for Swing/AWT components by selecting Palette Manager in the Tools menu.
    8. In the Palette Manager window select the beans components in the Palette tree and press the "Add from JAR" button.
    9. Specify a location for your SimpleBean JAR file and follow the Add from JAR Wizard instructions.
    10. Select the Palette and Properties options from the Windows menu.
    11. Expand the beans group in the Palette window. The SimpleBean object appears. Drag the SimpleBean object to the GUI Builder panel.

    The following figure represents the SimpleBean object loaded in the GUI Builder panel:

    This figure represents the SimpleBean object loaded in the GUI Builder panel,

  4. Inspect Properties and Events. The SimpleBean properties will appear in the Properties window. For example, you can change a background property by selecting another color. To preview your form, use the Preview Design button of the GUI Builder toolbar. To inspect events associated with the SimpleBean object, switch to the Events tab of the Properties window. You will learn more about bean properties and events in the lessons that follow.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Properties


Lesson: Properties (The Java™ Tutorials > JavaBeans(TM))

Properties
Simple Properties
Bound Properties
Constrained Properties
Indexed Properties
Trail: JavaBeans(TM)
Home Page > JavaBeans(TM)
« Previous • Trail • Next »
Lesson: Properties

In the following sections you will learn how to implement bean properties. A bean property is a named attribute of a bean that can affect its behavior or appearance. Examples of bean properties include color, label, font, font size, and display size.

The JavaBeans™ specification defines the following types of bean properties:

  • Simple – A bean property with a single value whose changes are independent of changes in any other property.

  • Indexed – A bean property that supports a range of values instead of a single value.

  • Bound – A bean property for which a change to the property results in a notification being sent to some other bean.

  • Constrained – A bean property for which a change to the property results in validation by another bean. The other bean may reject the change if it is not appropriate.

Bean properties can also be classified as follows:

  • Writable – A bean property that can be changed
    • Standard
    • Expert
    • Preferred
  • Read Only – A bean property that cannot be changed.
  • Hidden – A bean property that can be changed. However, these properties are not disclosed with the BeanInfo class
BeanBuilder uses this schema to group and represent properties in the Properties window.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Simple Properties


Simple Properties (The Java™ Tutorials > JavaBeans(TM) > Properties)

Trail: JavaBeans(TM)
Lesson: Properties
Properties
Simple Properties
Bound Properties
Constrained Properties
Indexed Properties
Home Page > JavaBeans(TM) > Properties
« Previous • Trail • Next »
Simple Properties
Note: This tutorial covers the Java Beans functionality available in the Beans module of the NetBeans IDE. Due to this module has been removed from the NetBeans IDE 6.0 (see the NetBeans project page for more information) it is recommended to use version 5.5.1 to obtain the full range of the Java Beans features.

To add simple properties to a bean, add appropriate getXXX and setXXX methods (or isXXX and setXXX methods for a boolean property).

The names of these methods follow specific rules called design patterns. These design pattern-based method names allow builder tools such as the NetBeans GUI Builder, to provide the following features:

  • Discover a bean's properties
  • Determine the properties' read/write attributes
  • Determine the properties' types
  • Locate the appropriate property editor for each property type
  • Display the properties (usually in the Properties window)
  • Alter the properties (at design time)

Adding a Title Property

In previous lessons you learned how to create a simple property by using the NetBeans GUI Builder. The following procedure shows how to create a simple property in detail:

  1. Right-click on the Bean Patterns node in the MyBean class hierarchy.
  2. Select Add|Property from the pop-up menu.
  3. Fill out the New Property Pattern form as shown in the following figure and click OK.

    Creating a simple property with the title name.

  4. The following code is automatically generated:
    public class MyBean {

    /** Creates a new instance of MyBean */
    public MyBean() {
    }

    /**
     * Holds value of property title.
     */
    private String title;

    /**
     * Getter for property title.
     * @return Value of property title.
     */
    public String getTitle() {
        return this.title;
    }

    /**
     * Setter for property title.
     * @param title New value of property title.
     */
    public void setTitle(String title) {
        this.title = title;
    }

}
  5. Now make your bean visual by extending the JComponent class and implement the Serializable interface. Then, add the paintComponent method to represent your bean.
    import java.awt.Graphics;
import java.io.Serializable;
import javax.swing.JComponent;

/**
 * Bean with a simple property "title".
 */
public class MyBean
        extends JComponent
        implements Serializable
{
    private String title;

    public String getTitle()
    {
        return this.title;
    }

    public void setTitle( String title )
    {
        this.title = title;
    }

    protected void paintComponent( Graphics g )
    {
        g.setColor( getForeground() );

        int height = g.getFontMetrics().getHeight();
        if ( this.title != null )
            g.drawString(this.title, 0, height );
       }
   }

Inspecting Properties

Select the MyBean component in the Other Components node in the Inspector window. Now you can analyze the title property in the Properties window and change it. To change the title property press the "..." button and enter any string you wish.

The following figure represents the title property set to the "The title" value.

the title property was set to the title.

The NetBeans GUI Builder enables you to restrict the changing of a property value. To restrict the changing of the title property, right-click the title property in the Bean Patterns node of the MyBean project. Select Properties from the pop-up menu and the Properties window appears. Choose one of the following property access types from the Mode combo box:

  • Read/Write
  • Read only
  • Write only

The Read only property has only the get method only, while the Write only property has only the set method only. The Read/Write type property has both of these methods.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Properties
Next page: Bound Properties


Bound Properties (The Java™ Tutorials > JavaBeans(TM) > Properties)

Trail: JavaBeans(TM)
Lesson: Properties
Properties
Simple Properties
Bound Properties
Constrained Properties
Indexed Properties
Home Page > JavaBeans(TM) > Properties
« Previous • Trail • Next »
Bound Properties
Note: This tutorial covers the Java Beans functionality available in the Beans module of the NetBeans IDE. Due to this module has been removed from the NetBeans IDE 6.0 (see the NetBeans project page for more information) it is recommended to use version 5.5.1 to obtain the full range of the Java Beans features.

Bound properties support the PropertyChangeListener (in the API reference documentation) class.

Sometimes when a Bean property changes, another object might need to be notified of the change, and react to the change.

Whenever a bound property changes, notification of the change is sent to interested listeners.

The accessor methods for a bound property are defined in the same way as those for simple properties. However, you also need to provide the event listener registration methods forPropertyChangeListener classes and fire a PropertyChangeEvent (in the API reference documentation) event to the PropertyChangeListener objects by calling their propertyChange methods

The convenience PropertyChangeSupport (in the API reference documentation) class enables your bean to implement these methods. Your bean can inherit changes from the PropertyChangeSupportclass, or use it as an inner class.

In order to listen for property changes, an object must be able to add and remove itself from the listener list on the bean containing the bound property. It must also be able to respond to the event notification method that signals a property change.

The PropertyChangeEvent class encapsulates property change information, and is sent from the property change event source to each object in the property change listener list with the propertyChange method.

Implementing Bound Property Support Within a Bean

To implement a bound property in your application, follow these steps:

  1. Import the java.beans package. This gives you access to the PropertyChangeSupport class.
  2. Instantiate a PropertyChangeSupport object. This object maintains the property change listener list and fires property change events. You can also make your class a PropertyChangeSupport subclass.
  3. Implement methods to maintain the property change listener list. Since a PropertyChangeSupport subclass implements these methods, you merely wrap calls to the property-change support object's methods.
  4. Modify a property's set method to fire a property change event when the property is changed.

Creating a Bound Property

To create the title property as a bound property for the MyBean component in the NetBeans GUI Builder, perform the following sequence of operations:
  1. Right-click the Bean Patterns node in the MyBean class hierarchy.
  2. Select Add|Property from the pop-up menu.
  3. Fill the New Property Pattern form as shown on the following figure and click OK.

    Creating a bound property.

  4. Note that the title property and the multicast event source pattern PropertyChangeListener were added to the Bean Patterns structure.

You can also modify existing code generated in the previous lesson to convert the title and lines properties to the bound type as follows (where newly added code is shown in bold):

import java.awt.Graphics;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.io.Serializable;
import javax.swing.JComponent;

/**
 * Bean with bound properties.
 */
public class MyBean
        extends JComponent
        implements Serializable
{
    private String title;
    private String[] lines = new String[10];

    private final PropertyChangeSupport pcs = new PropertyChangeSupport( this );

    public String getTitle()
    {
        return this.title;
    }

    public void setTitle( String title )
    {
        String old = this.title;
        this.title = title;
        this.pcs.firePropertyChange( "title", old, title );
    }

    public String[] getLines()
    {
        return this.lines.clone();
    }

    public String getLines( int index )
    {
        return this.lines[index];
    }

    public void setLines( String[] lines )
    {
        String[] old = this.lines;
        this.lines = lines;
        this.pcs.firePropertyChange( "lines", old, lines );
    }

    public void setLines( int index, String line )
    {
        String old = this.lines[index];
        this.lines[index] = line;
        this.pcs.fireIndexedPropertyChange( "lines", index, old, lines );
    }

    public void addPropertyChangeListener( PropertyChangeListener listener )
    {
        this.pcs.addPropertyChangeListener( listener );
    }

    public void removePropertyChangeListener( PropertyChangeListener listener )
    {
        this.pcs.removePropertyChangeListener( listener );
    }

    protected void paintComponent( Graphics g )
    {
        g.setColor( getForeground() );

        int height = g.getFontMetrics().getHeight();
        paintString( g, this.title, height );

        if ( this.lines != null )
        {
            int step = height;
            for ( String line : this.lines )
                paintString( g, line, height += step );
        }
    }

    private void paintString( Graphics g, String str, int height )
    {
        if ( str != null )
            g.drawString( str, 0, height );
    }
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Simple Properties
Next page: Constrained Properties


Constrained Properties (The Java™ Tutorials > JavaBeans(TM) > Properties)

Trail: JavaBeans(TM)
Lesson: Properties
Properties
Simple Properties
Bound Properties
Constrained Properties
Indexed Properties
Home Page > JavaBeans(TM) > Properties
« Previous • Trail • Next »
Constrained Properties
Note: This tutorial covers the Java Beans functionality available in the Beans module of the NetBeans IDE. Due to this module has been removed from the NetBeans IDE 6.0 (see the NetBeans project page for more information) it is recommended to use version 5.5.1 to obtain the full range of the Java Beans features.

A bean property is constrained if the bean supports the VetoableChangeListener(in the API reference documentation) and PropertyChangeEvent(in the API reference documentation) classes, and if the set method for this property throws a PropertyVetoException(in the API reference documentation).

Constrained properties are more complicated than bound properties because they also support property change listeners which happen to be vetoers.

The following operations in the setXXX method for the constrained property must be implemented in this order:

  1. Save the old value in case the change is vetoed.
  2. Notify listeners of the new proposed value, allowing them to veto the change.
  3. If no listener vetoes the change (no exception is thrown), set the property to the new value.

The accessor methods for a constrained property are defined in the same way as those for simple properties, with the addition that the setXXX method throws a PropertyVetoException exception. The syntax is as follows:

    public void setPropertyName(PropertyType pt)
    throws PropertyVetoException {code}

Handling Vetoes

If a registered listener vetoes a proposed property change by throwing a PropertyVetoException exception, the source bean with the constrained property is responsible for the following actions:
  • Catching exceptions.
  • Reverting to the old value for the property.
  • Issuing a new VetoableChangeListener.vetoableChange call to all listeners to report the reversion.
The VetoableChangeListener class throws a PropertyVetoException and handles the PropertyChangeEvent event fired by the bean with the constrained property.

The VetoableChangeSupport provides the following operations:

  • Keeping track of VetoableChangeListener objects.
  • Issuing the vetoableChange method on all registered listeners.
  • Catching any vetoes (exceptions) thrown by listeners.
  • Informing all listeners of a veto by calling vetoableChange again, but with the old property value as the proposed "new" value.

Creating a Constrained Property

To create a constrained property, set the appropriate option in the New Property Pattern form as shown on the following figure.

Setting a constrained option for the radius property.

Note that the Multicast Source Event Pattern - vetoableChangeListener was added to the Bean Patterns hierarchy.

You can also modify the existing code generated in the previous lesson to make the title and lines properties constrained as follows (where newly added code is shown in bold):

import java.io.Serializable;
import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.beans.VetoableChangeSupport;
import java.awt.Graphics;
import javax.swing.JComponent;

/**
 * Bean with constrained properties.
 */
public class MyBean
        extends JComponent
        implements Serializable
{
    private String title;
    private String[] lines = new String[10];

    private final PropertyChangeSupport pcs = new PropertyChangeSupport( this );
    private final VetoableChangeSupport vcs = new VetoableChangeSupport( this );

    public String getTitle()
    {
        return this.title;
    }
/**
 * This method was modified to throw the PropertyVetoException
 * if some vetoable listeners reject the new title value
 */
    public void setTitle( String title )
            throws PropertyVetoException
    {
        String old = this.title;
        this.vcs.fireVetoableChange( "title", old, title );
        this.title = title;
        this.pcs.firePropertyChange( "title", old, title );
    }

    public String[] getLines()
    {
        return this.lines.clone();
    }

    public String getLines( int index )
    {
        return this.lines[index];
    }
/**
 * This method throws the PropertyVetoException
 * if some vetoable listeners reject the new lines value
 */
    public void setLines( String[] lines )
            throws PropertyVetoException
    {
        String[] old = this.lines;
        this.vcs.fireVetoableChange( "lines", old, lines );
        this.lines = lines;
        this.pcs.firePropertyChange( "lines", old, lines );
    }

    public void setLines( int index, String line )
            throws PropertyVetoException
    {
        String old = this.lines[index];
        this.vcs.fireVetoableChange( "lines", old, line );
        this.lines[index] = line;
        this.pcs.fireIndexedPropertyChange( "lines", index, old, line );
    }

    public void addPropertyChangeListener( PropertyChangeListener listener )
    {
        this.pcs.addPropertyChangeListener( listener );
    }

    public void removePropertyChangeListener( PropertyChangeListener listener )
    {
        this.pcs.removePropertyChangeListener( listener );
    }
/**
 * Registration of the VetoableChangeListener
 */
    public void addVetoableChangeListener( VetoableChangeListener listener )
    {
        this.vcs.addVetoableChangeListener( listener );
    }

    public void removeVetoableChangeListener( VetoableChangeListener listener )
    {
        this.vcs.removeVetoableChangeListener( listener );
    }

    protected void paintComponent( Graphics g )
    {
        g.setColor( getForeground() );

        int height = g.getFontMetrics().getHeight();
        paintString( g, this.title, height );

        if ( this.lines != null )
        {
            int step = height;
            for ( String line : this.lines )
                paintString( g, line, height += step );
        }
    }

    private void paintString( Graphics g, String str, int height )
    {
        if ( str != null )
            g.drawString( str, 0, height );
    }
}

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Bound Properties
Next page: Indexed Properties


Indexed Properties (The Java™ Tutorials > JavaBeans(TM) > Properties)

Trail: JavaBeans(TM)
Lesson: Properties
Properties
Simple Properties
Bound Properties
Constrained Properties
Indexed Properties
Home Page > JavaBeans(TM) > Properties
« Previous • Trail • Next »
Indexed Properties
Note: This tutorial covers the Java Beans functionality available in the Beans module of the NetBeans IDE. Due to this module has been removed from the NetBeans IDE 6.0 (see the NetBeans project page for more information) it is recommended to use version 5.5.1 to obtain the full range of the Java Beans features.

An indexed property is an array of properties or objects that supports a range of values and enables the accessor to specify an element of a property to read or write.

Indexed properties are specified by the following methods:

    //Methods to access individual values
        public PropertyElement getPropertyName(int index)
    public void setPropertyName(int index, PropertyElement element)
and
    //Methods to access the entire indexed property array
        public PropertyElement[] getPropertyName()
    public void setPropertyName(PropertyElement element[])
Note that the distinction between the get and set methods for indexed properties is subtle. The get method either has an argument that is the array index of the property, or returns an array. The set method either has two arguments, namely an integer array index and the property element object that is being set, or has the entire array as an argument.

Creating an Indexed Property

To create an indexed property for your MyBean component, right-click the Bean Patterns node and select Add|Indexed Property from the pop-up menu. Set up Non-Index Options as shown in the following figure.

Setting a Non-Indexed options for the property.

The code in the Source window will be changed automatically as follows:

import java.awt.Graphics;
import java.io.Serializable;
import javax.swing.JComponent;

/**
 * Bean with simple property 'title'.
 */
public class MyBean
        extends JComponent
        implements Serializable
{
    private String title;

    public String getTitle()
    {
        return this.title;
    }

    public void setTitle( String title )
    {
        this.title = title;
    }

    protected void paintComponent( Graphics g )
    {
        g.setColor( getForeground() );

        int height = g.getFontMetrics().getHeight();
        if ( this.title != null )
            g.drawString(this.title, 0, height );
       }

    /**
     * Holds value of property lines.
     */
    private String[] lines;

    /**
     * Indexed getter for property lines.
     * @param index Index of the property.
     * @return Value of the property at index.
     */
    public String getLines(int index) {
        return this.lines[index];
    }

    /**
     * Getter for property lines.
     * @return Value of property lines.
     */
    public String[] getLines() {
        return this.lines;
    }

    /**
     * Indexed setter for property lines.
     * @param index Index of the property.
     * @param lines New value of the property at index.
     */
    public void setLines(int index, String lines) {
        this.lines[index] = lines;
    }

    /**
     * Setter for property lines.
     * @param lines New value of property lines.
     */
    public void setLines(String[] lines) {
        this.lines = lines;
    }
   }
Add the following code to the MyBean.java component to present the user with a list of choices. You can provide and change these choices at design time. (Newly added code is shown in bold.)
import java.awt.Graphics;
import java.io.Serializable;
import javax.swing.JComponent;

/**
 * Bean with a simple property "title"
 * and an indexed property "lines".
 */
public class MyBean
        extends JComponent
        implements Serializable
{
    private String title;
    private String[] lines = new String[10];

    public String getTitle()
    {
        return this.title;
    }

    public void setTitle( String title )
    {
        this.title = title;
    }

    public String[] getLines()
    {
        return this.lines.clone();
    }

    public String getLines( int index )
    {
        return this.lines[index];
    }

    public void setLines( String[] lines )
    {
        this.lines = lines;
    }

    public void setLines( int index, String line )
    {
        this.lines[index] = line;
    }

    protected void paintComponent( Graphics g )
    {
        g.setColor( getForeground() );

        int height = g.getFontMetrics().getHeight();
        paintString( g, this.title, height );

        if ( this.lines != null )
        {
            int step = height;
            for ( String line : this.lines )
                paintString( g, line, height += step );
        }
    }

    private void paintString( Graphics g, String str, int height )
    {
        if ( str != null )
            g.drawString( str, 0, height );
    }
}

The following figure represents the lines property in the Properties window.

The indexed lines property is set to null.

Notice that this property has a null value. To set up an alternative value, press the "..." button. The form shown in the following figure enables you to add ten items for the lines property list. First remove the default null items. Then add custom items to the list by entering each item value into the Item field and pressing the Add button each time.

Creating a list of choices for the lines property.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Constrained Properties
Next page: Manipulating Events


Lesson: Manipulating Events (The Java™ Tutorials > JavaBeans(TM))

Trail: JavaBeans(TM)
Home Page > JavaBeans(TM)
« Previous • Trail • Next »
Lesson: Manipulating Events
Note: This tutorial covers the Java Beans functionality available in the Beans module of the NetBeans IDE. Due to this module has been removed from the NetBeans IDE 6.0 (see the NetBeans project page for more information) it is recommended to use version 5.5.1 to obtain the full range of the Java Beans features.

Event passing is the means by which components communicate with each other. Components broadcast events, and the underlying framework delivers the events to the components that are to be notified. The notified components usually perform some action based on the event that took place.

The event model was designed to accommodate the JavaBeans™ architecture. To understand how events and event handling work in the JavaBeans component model, you must understand the concepts of events, listeners, and sources. To refresh your knowledge in these areas, read the Writing Event Listeners lesson of the Swing tutorial.

The event model that is used by the JavaBeans architecture is a delegation model. This model is composed of three main parts: sources, events, and listeners.

The source of an event is the object that originates or fires the event. The source must define the events it will fire, as well as the methods for registering listeners of those events. A listener is an object that indicates that it is to be notified of events of a particular type. Listeners register for events using the methods defined by the sources of those events.

From the Properties lesson you discovered two event listeners. The PropertyChangeListener(in the API reference documentation) interface provides a notification whenever a bound property value is changed and the VetoableChangeListener(in the API reference documentation) creates a notification whenever a bean changes a constrained property value.

Simple Event Example

This example represents an application that performs an action when a button is clicked. Button components are defined as sources of an event type called ActionEvent(in the API reference documentation). Listeners of events of this type must register for these events using the addActionListener method.

Therefore, the addActionListener method is used to register the ButtonHandler object as a listener of the ActionEvent event that is fired by the button.

In addition, according to the requirements of the ActionListener class, you must define an actionPerformed method, which is the method that is called when the button is clicked.

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JTextArea;
import java.awt.BorderLayout;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.WindowConstants;

public class ButtonHandler implements ActionListener {
   /**
   * Component that will contain messages about
   * events generated.
   */
   private JTextArea output;
   /**
   * Creates an ActionListener that will put messages in
   * JTextArea everytime event received.
   */
    public ButtonHandler( JTextArea output )
    {
        this.output = output;
    }

   /**
   * When receives action event notification, appends
   * message to the JTextArea passed into the constructor.
   */
    public void actionPerformed( ActionEvent event )
    {
        this.output.append( "Action occurred: " + event + '\n' );
    }
}

class ActionTester {
    public static void main(String args[]) {
        JFrame frame = new JFrame( "Button Handler" );
        JTextArea area = new JTextArea( 6, 80 );
        JButton button = new JButton( "Fire Event" );
        button.addActionListener( new ButtonHandler( area ) );
        frame.add( button, BorderLayout.NORTH );
        frame.add( area, BorderLayout.CENTER );
        frame.pack();
        frame.setDefaultCloseOperation( WindowConstants.DISPOSE_ON_CLOSE );
        frame.setLocationRelativeTo( null );
        frame.setVisible( true );
    }
}

Using Introspection to Discover the Events A Bean Fires

The JavaBeans API provides event-oriented design patterns to give introspecting tools the ability to discover what events a bean can fire. For a bean to be the source of an event, it must implement methods that add and remove listener objects for that type of event. The design patterns for these methods are the following:

public void add<EventListenerType>(<EventListenerType> a)
public void remove<EventListenerType>(<EventListenerType> a)
These methods let a source bean know where to fire events. The source bean then fires events at those listener beans using the methods for those particular interfaces. For example, if a source bean registers ActionListener objects, it will fire events at those objects by calling the actionPerformed method on those listeners.
package java.awt.event;
import java.util.EventListener;

  public interface ActionListener extends EventListener {

  public void actionPerformed(ActionEvent e);
}

Using the NetBeans GUI Builder to Set Events

In the lesson "Using the NetBeans GUI Builder," you learned how to create a MyBean component, add the yourName property, and design a simple form. Now you will set an event by which a value entered in the JTextField component is stored in the yourName property. Use the GUI Builder as follows to set such an event:

  1. Left click the MyForm node.
  2. Switch to the Connection Mode by clicking the appropriate button on the GUI Builder toolbar.
  3. In the Design Area or Inspector window select the OK button (jButton1). Notice that the button is highlighted in red when it is selected.
  4. In the Inspector window select the myBean1 component.
  5. In the Connection wizard's Select Source Event page, select the action|actionPerformed[jButton1ActionPerformed1] event by expanding the event type directory nodes, as represented in the following figure.

    Selecting the action|actionPerformed[jButton1ActionPerformed1] event.

  6. Click the Next button.
  7. In the Specify Target Operation page, specify the yourName property in the MyBean component, and click the Next button.
  8. In the Enter Parameters page, specify the target property by selecting the Property radio button.
  9. Press the ellipsis (...) button to display the Select Property dialog box.
  10. In the Select Property dialog box select the jTextField component from the Component combobox and choose the text property from the list that is presented, as shown on the following figure.

    Selecting the action|actionPerformed[jButton1ActionPerformed1] event.

  11. Click the Finish button.

The Source Editor window is now displayed. Since the GUI Builder automatically generates the code to connect the form's components, the following code will be added to the MyForm class:

    private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
        myBean1.setYourName(jTextField1.getText());
    }
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Bean Persistence


Lesson: Bean Persistence (The Java™ Tutorials > JavaBeans(TM))

Trail: JavaBeans(TM)
Home Page > JavaBeans(TM)
« Previous • Trail • Next »
Lesson: Bean Persistence

A bean has the property of persistence when its properties, fields, and state information are saved to and retrieved from storage. Component models provide a mechanism for persistence that enables the state of components to be stored in a non-volatile place for later retrieval.

The mechanism that makes persistence possible is called serialization. Object serialization means converting an object into a data stream and writing it to storage. Any applet, application, or tool that uses that bean can then "reconstitute" it by deserialization. The object is then restored to its original state.

For example, a Java application can serialize a Frame window on a Microsoft Windows machine, the serialized file can be sent with e-mail to a Solaris machine, and then a Java application can restore the Frame window to the exact state which existed on the Microsoft Windows machine.

Any applet, application, or tool that uses that bean can then "reconstitute" it by deserialization.

All beans must persist. To persist, your beans must support serialization by implementing either the java.io.Serializable(in the API reference documentation) interface, or the java.io.Externalizable(in the API reference documentation) interface. These interfaces offer you the choices of automatic serialization and customized serialization. If any class in a class's inheritance hierarchy implements Serializable or Externalizable, then that class is serializable.

Classes That Are Serializable

Any class is serializable as long as that class or a parent class implements the java.io.Serializable interface. Examples of serializable classes include Component, String, Date, Vector, and Hashtable. Thus, any subclass of the Component class, including Applet, can be serialized. Notable classes not supporting serialization include Image, Thread, Socket, and InputStream. Attempting to serialize objects of these types will result in an NotSerializableException.

The Java Object Serialization API automatically serializes most fields of a Serializable object to the storage stream. This includes primitive types, arrays,and strings. The API does not serialize or deserialize fields that are marked transient or static.

Controlling Serialization

You can control the level of serialization that your beans undergo. Three ways to control serilization are:

  • Automatic serialization, implemented by the Serializable interface. The Java serialization software serializes the entire object, except transient and static fields.
  • Customized serialization. Selectively exclude fields you do not want serialized by marking with the transient (or static) modifier.
  • Customized file format, implemented by the Externalizable interface and its two methods. Beans are written in a specific file format.

Default Serialization: The Serializable Interface

The Serializable interface provides automatic serialization by using the Java Object Serialization tools. Serializable declares no methods; it acts as a marker, telling the Object Serialization tools that your bean class is serializable. Marking your class Serializable means you are telling the Java Virtual Machine (JVM) that you have made sure your class will work with default serialization. Here are some important points about working with the Serializable interface:

  • Classes that implement Serializable must have an access to a no-argument constructor of supertype. This constructor will be called when an object is "reconstituted" from a .ser file.
  • You don't need to implement Serializable in your class if it is already implemented in a superclass.
  • All fields except static and transient fields are serialized. Use the transient modifier to specify fields you do not want serialized, and to specify classes that are not serializable.

Selective Serialization Using the transient Keyword

To exclude fields from serialization in a Serializable object from serialization, mark the fields with the transient modifier.

transient int status;
Default serialization will not serialize transient and static fields.

Selective Serialization: writeObject and readObject

If your serializable class contains either of the following two methods (the signatures must be exact), then the default serialization will not take place.

private void writeObject(java.io.ObjectOutputStream out)
    throws IOException;
private void readObject(java.io.ObjectInputStream in)
    throws IOException, ClassNotFoundException;

You can control how more complex objects are serialized, by writing your own implementations of the writeObject and readObject methods. Implement writeObject when you need to exercise greater control over what gets serialized when you need to serialize objects that default serialization cannot handle, or when you need to add data to the serialization stream that is not an object data member. Implement readObject to reconstruct the data stream you wrote with writeObject.

The Externalizable Interface

Use the Externalizable interface when you need complete control over your bean's serialization (for example, when writing and reading a specific file format). To use the Externalizable interface you need to implement two methods: readExternal and writeExternal. Classes that implement Externalizable must have a no-argument constructor.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Long Term Persistence


Lesson: Long Term Persistence (The Java™ Tutorials > JavaBeans(TM))

Trail: JavaBeans(TM)
Home Page > JavaBeans(TM)
« Previous • Trail • Next »
Lesson: Long Term Persistence

Long-term persistence is a model that enables beans to be saved in XML format.

Information on the XML format and on how to implement long-term persistence for non-beans can be found in XML Schema and Using XMLEncoder .

Encoder and Decoder

The XMLEncoder class is assigned to write output files for textual representation of Serializable objects. The following code fragment is an example of writing a Java bean and its properties in XML format:

     XMLEncoder encoder = new XMLEncoder(
                new BufferedOutputStream(
                        new FileOutputStream( "Beanarchive.xml" ) ) );

        encoder.writeObject( object );
        encoder.close();

The XMLDecoder class reads an XML document that was created with XMLEncoder:

      XMLDecoder decoder = new XMLDecoder(
                new BufferedInputStream(
                        new FileInputStream( "Beanarchive.xml" ) ) );

        Object object = decoder.readObject();
        decoder.close();

What's in XML?

An XML bean archive has its own specific syntax, which includes the following tags to represent each bean element:

  • an XML preamble to describe a version of XML and type of encoding
  • a <java> tag to embody all object elements of the bean
  • an <object> tag to represent a set of method calls needed to reconstruct an object from its serialized form
        <object class="javax.swing.JButton" method="new">
             <string>Ok</string>
        </object>
    or statements
        <object class="javax.swing.JButton">
             <void method="setText">
             <string>Cancel</string>
             </void>
        </object>
  • tags to define appropriate primitive types:
    • <boolean>
    • <byte>
    • <char>
    • <short>
    • <int>
    • <long>
    • <float>
    • <double>
            <int>5555</int>
  • a <class> tag to represent an instance of Class.
        <class>java.swing.JFrame</class>
  • an <array> tag to define an array
        <array class="java.lang.String" length="5">
        </array>

The following code represents an XML archive that will be generated for the SimpleBean component:

<?xml version="1.0" encoding="UTF-8" ?>
<java>
  <object class="javax.swing.JFrame">
    <void method="add">
      <object class="java.awt.BorderLayout" field="CENTER"/>
      <object class="SimpleBean"/>
    </void>
    <void property="defaultCloseOperation">
      <object class="javax.swing.WindowConstants" field="DISPOSE_ON_CLOSE"/>
    </void>
    <void method="pack"/>
    <void property="visible">
      <boolean>true</boolean>
    </void>
  </object>
</java>
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Introspection


Lesson: Introspection (The Java™ Tutorials > JavaBeans(TM))

Trail: JavaBeans(TM)
Home Page > JavaBeans(TM)
« Previous • Trail • Next »
Lesson: Introspection

Introspection is the automatic process of analyzing a bean's design patterns to reveal the bean's properties, events, and methods. This process controls the publishing and discovery of bean operations and properties. This lesson explains the purpose of introspection, introduces the Introspection API, and gives an example of introspection code.

Purpose of Introspection

A growing number of Java object repository sites exist on the Internet in answer to the demand for centralized deployment of applets, classes, and source code in general. Any developer who has spent time hunting through these sites for licensable Java code to incorporate into a program has undoubtedly struggled with issues of how to quickly and cleanly integrate code from one particular source into an application.

The way in which introspection is implemented provides great advantages, including:

  1. Portability - Everything is done in the Java platform, so you can write components once, reuse them everywhere. There are no extra specification files that need to be maintained independently from your component code. There are no platform-specific issues to contend with. Your component is not tied to one component model or one proprietary platform. You get all the advantages of the evolving Java APIs, while maintaining the portability of your components.
  2. Reuse - By following the JavaBeans design conventions, implementing the appropriate interfaces, and extending the appropriate classes, you provide your component with reuse potential that possibly exceeds your expectations.

Introspection API

The JavaBeans API architecture supplies a set of classes and interfaces to provide introspection.

The BeanInfo (in the API reference documentation) interface of the java.beans package defines a set of methods that allow bean implementors to provide explicit information about their beans. By specifying BeanInfo for a bean component, a developer can hide methods, specify an icon for the toolbox, provide descriptive names for properties, define which properties are bound properties, and much more.

The getBeanInfo(beanName) (in the API reference documentation) of the Introspector (in the API reference documentation) class can be used by builder tools and other automated environments to provide detailed information about a bean. The getBeanInfo method relies on the naming conventions for the bean's properties, events, and methods. A call to getBeanInfo results in the introspection process analyzing the bean’s classes and superclasses.

The Introspector class provides descriptor classes with information about properties, events, and methods of a bean. Methods of this class locate any descriptor information that has been explicitly supplied by the developer through BeanInfo classes. Then the Introspector class applies the naming conventions to determine what properties the bean has, the events to which it can listen, and those which it can send.

The following figure represents a hierarchy of the FeatureDescriptor classes:

This figure represents a hierarchy of descriptor classes beginning with the FeatureDescriptor class

Each class represented in this group describes a particular attribute of the bean. For example, the isBound method of the PropertyDescriptor class indicates whether a PropertyChangeEvent event is fired when the value of this property changes.

Editing Bean Info with the NetBeans BeanInfo Editor

Note: This tutorial covers the Java Beans functionality available in the Beans module of the NetBeans IDE. Due to this module has been removed from the NetBeans IDE 6.0 (see the NetBeans project page for more information) it is recommended to use version 5.5.1 to obtain the full range of the Java Beans features.

To open the BeanInfo dialog box, expand the appropriate class hierarchy to the bean Patterns node. Right-click the bean Patterns node and choose BeanInfo Editor from the pop-up menu. All elements of the selected class that match bean-naming conventions will be displayed at the left in the BeanInfo Editor dialog box as shown in the following figure:

This figure shows the BeanInfo Editor dialog box and expanded Properties node

Select one of the following nodes to view and edit its properties at the right of the dialog box:

  • BeanInfo
  • Bean
  • Properties
  • Methods
  • Event Sources

Special symbols (green and red) appear next to the subnode to indicate whether an element will be included or excluded from the BeanInfo class.

If the Get From Introspection option is not selected, the node's subnodes are available for inclusion in the BeanInfo class. To include all subnodes, right-click a node and choose Include All. You can also include each element individually by selecting its subnode and setting the Include in BeanInfo property. If the Get From Introspection option is selected, the setting the properties of subnodes has no effect in the generated BeanInfo code.

The following attributes are available for the nodes for each bean, property, event sources, and method:

  • Name - A name of the selected element as it appears in code.
  • Preferred - An attribute to specify where this property appears in the Inspector window under the Properties node.
  • Expert - An attribute to specify where this property appears in the Inspector window under the Other Properties node.
  • Hidden - An attribute to mark an element for tool use only.
  • Display Name Code - A display name of the property.
  • Short Description Code - A short description of the property.
  • Include in BeanInfo - An attribute to include the selected element in the BeanInfo class.
  • Bound - An attribute to make the bean property bound.
  • Constrained - An attribute to make the bean property constrained.
  • Mode - An attribute to set the property's mode and generate getter and setter methods.
  • Property Editor Class - An attribute to specify a custom class to act as a property editor for the property.

For Event Source nodes, the following Expert properties are available:

  • Unicast (read-only)
  • In Default Event Set

Introspection Sample

The following example represents code to perform introspection:
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;

public class SimpleBean
{
    private final String name = "SimpleBean";
    private int size;

    public String getName()
    {
        return this.name;
    }

    public int getSize()
    {
        return this.size;
    }

    public void setSize( int size )
    {
        this.size = size;
    }

    public static void main( String[] args )
            throws IntrospectionException
    {
        BeanInfo info = Introspector.getBeanInfo( SimpleBean.class );
        for ( PropertyDescriptor pd : info.getPropertyDescriptors() )
            System.out.println( pd.getName() );
    }
}

This example creates a non-visual bean and displays the following properties derived from the BeanInfo object:

  • class
  • name
  • size

Note that a class property was not defined in the SimpleBean class. This property was inherited from the Object class. To get properties defined only in the SimpleBean class, use the following form of the getBeanInfo method:

    Introspector.getBeanInfo( SimpleBean.class, Object.class );
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Bean Customization


Lesson: Bean Customization (The Java™ Tutorials > JavaBeans(TM))

Trail: JavaBeans(TM)
Home Page > JavaBeans(TM)
« Previous • Trail • Next »
Lesson: Bean Customization
Note: This tutorial covers the Java Beans functionality available in the Beans module of the NetBeans IDE. Due to this module has been removed from the NetBeans IDE 6.0 (see the NetBeans project page for more information) it is recommended to use version 5.5.1 to obtain the full range of the Java Beans features.

Customization provides a means for modifying the appearance and behavior of a bean within an application builder so it meets your specific needs. There are several levels of customization available for a bean developer to allow other developers to get maximum benefit from a bean’s potential functionality.

The following links are useful for learning about property editors and customizers:
  • PropertyEditor(in the API reference documentation) interface
  • PropertyEditorSupport(in the API reference documentation) class
  • PropertyEditorManager(in the API reference documentation) class
  • Customizer(in the API reference documentation) interface
  • BeanInfo(in the API reference documentation) interface

A bean's appearance and behavior can be customized at design time within beans-compliant builder tools. There are two ways to customize a bean:

  • By using a property editor. Each bean property has its own property editor. The NetBeans GUI Builder usually displays a bean's property editors in the Properties window. The property editor that is associated with a particular property type edits that property type.
  • By using customizers. Customizers give you complete GUI control over bean customization. Customizers are used where property editors are not practical or applicable. Unlike a property editor, which is associated with a property, a customizer is associated with a bean.

Property Editors

A property editor is a tool for customizing a particular property type. Property editors are activated in the Properties window. This window determines a property's type, searches for a relevant property editor, and displays the property's current value in a relevant way.

Property editors must implement the PropertyEditor interface, which provides methods to specify how a property should be displayed in a property sheet. The following figure represents the Properties window containing myBean1 properties:

This figure represents myBean1 properties in the Property window

You begin the process of editing these properties by clicking the property entry. Clicking most of these entries will bring up separate panels. For example, to set up the foreground or background use selection boxes with choices of colors, or press the "..." button to work with a standard ColorEditor window. Clicking on the toolTipText property opens a StringEditor window.

The support class PropertyEditorSupport provides a default implementation of the PropertyEditor interface. By subclassing your property editor from PropertyEditorSupport, you can simply override the methods you need.

To display the current property value "sample" within the Properties window, you need to override isPaintable to return true. You then must override paintValue to paint the current property value in a rectangle in the property sheet. Here's how ColorEditor implements paintValue:

public void paintValue(java.awt.Graphics gfx, java.awt.Rectangle box) {
    Color oldColor = gfx.getColor();
    gfx.setColor(Color.black);
    gfx.drawRect(box.x, box.y, box.width-3, box.height-3);
    gfx.setColor(color);
    gfx.fillRect(box.x+1, box.y+1, box.width-4, box.height-4);
    gfx.setColor(oldColor);
}

To support the custom property editor, override two more methods. Override supportsCustomEditor to return true, and then override getCustomEditor to return a custom editor instance. ColorEditor.getCustomEditor returns this.

In addition, the PropertyEditorSupport class maintains a PropertyChangeListener list, and fires property change event notifications to those listeners when a bound property is changed.

How Property Editors are Associated with Properties

Property editors are discovered and associated with a given property in the following ways:

  • Explicit association by way of a BeanInfo object. The editor of the title's property is set with the following line of code:
    pd.setPropertyEditorClass(TitleEditor.class);

  • Explicit registration by way of the java.beans.PropertyEditorManager.registerEditor method. This method takes two arguments: the bean class type, and the editor class to be associated with that type.

  • Name search. If a class has no explicitly associated property editor, then the PropertyEditorManager searchs for that class's property editor in the following ways:
    • Appending "Editor" to the fully qualified class name. For example, for the my.package.ComplexNumber class, the property editor manager would search for the my.package.ComplexNumberEditor class.
    • Appending "Editor" to the class name and searching a class path.

Customizers

You have learned that builder tools provide support for you to create your own property editors. What other needs should visual builders meet for complex, industrial-strength beans? Often it is undesirable to have all the properties of a bean revealed on a single (sometimes huge) property sheet. What if one single root choice about the type of the bean rendered half the properties irrelevant? The JavaBeans specification provides for user-defined customizers, through which you can define a higher level of customization for bean properties than is available with property editors.

When you use a bean Customizer, you have complete control over how to configure or edit a bean. A Customizer is an application that specifically targets a bean's customization. Sometimes properties are insufficient for representing a bean's configurable attributes. Customizers are used where sophisticated instructions would be needed to change a bean, and where property editors are too primitive to achieve bean customization.

All customizers must:

  • Extend java.awt.Component or one of its subclasses.
  • Implement the java.beans.Customizer interface This means implementing methods to register PropertyChangeListener objects, and firing property change events at those listeners when a change to the target bean has occurred.
  • Implement a default constructor.
  • Associate the customizer with its target class via BeanInfo.getBeanDescriptor.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Using the BeanContext API


Lesson: Using the BeanContext API (The Java™ Tutorials > JavaBeans(TM))

Using the BeanContext API
Overview of the BeanContext API
Bean Context #1: Containment Only
Bean Context #2: Containment and Services
AWT Containers and the BeanContextProxy Interface
Trail: JavaBeans(TM)
Home Page > JavaBeans(TM)
« Previous • Trail • Next »
Lesson: Using the BeanContext API

As stated in the specification, the purpose of the Extensible Runtime Containment and Services Protocol is "to introduce the concept of a relationship between a Component and its environment, or Container, wherein a newly instantiated Component is provided with a reference to its Container or Embedding Context. The Container, or Embedding Context not only establishes the hierarchy or logical structure, but it also acts as a service provider that Components may interrogate in order to determine, and subsequently employ, the services provided by their Context."

Overview of the BeanContext API

This section introduces extensible mechanisms and represents inheritance diagram of the BeanContext API.

Bean Context #1: Containment Only

This section teaches how to use the BeanContextSupport class to provide the basic BeanContext functionality.

Bean Context #2: Containment and Services

This section teaches how to use service capability defined by the BeanContextServices interface.

AWT Containers and the BeanContextProxy Interface

This section describes how an AWT Container can act as a BeanContext.

Additional Resources

  • The Extensible Runtime Containment and Services Protocol Specification
  • The java.beans.beancontext API documentation
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Overview of the BeanContext API


Overview of the BeanContext API (The Java™ Tutorials > JavaBeans(TM) > Using the BeanContext API)

Trail: JavaBeans(TM)
Lesson: Using the BeanContext API
Using the BeanContext API
Overview of the BeanContext API
Bean Context #1: Containment Only
Bean Context #2: Containment and Services
AWT Containers and the BeanContextProxy Interface
Home Page > JavaBeans(TM) > Using the BeanContext API
« Previous • Trail • Next »
Overview of the BeanContext API

The Extensible Runtime Containment and Services Protocol supports extensible mechanisms that:

  • Introduce an abstraction for the environment, or context, in which a JavaBean logically functions during its life-cycle, that is a hierarchy of JavaBeans
  • Enable the dynamic addition of arbitrary services to a JavaBean's environment
  • Provide a single service discovery mechanism through which JavaBeans may interrogate their environment in order both to ascertain the availability of particular services and to subsequently employ those services.
  • Provide better support for JavaBeans that are also Applets.

In English, this means that there now exists a standard mechanism through which Java developers can logically group a set of related JavaBeans into a "context" that the beans can become aware of and/or interact with. This context, or "containing environment", is known as the BeanContext.

There are two distinct types of BeanContext included in this protocol: one which supports membership only (interface java.beans.beancontext.BeanContext) and one which supports membership and offers services (interface java.beans.beancontext.BeanContextServices) to its JavaBeans nested within.

To orient yourself with the classes and interfaces of java.beans.beancontext, take a minute to look over the following hierarchy diagram. You will notice that the majority of the package is defined as interfaces, which allow for multiple inheritance.

Inheritance Diagram of the BeanContext API

The classes and interfaces relevant to the BeanContext API are listed in the following diagrams. As you study the diagrams, take note of the BeanContext and BeanContextServices interfaces, and that each has its own concrete implementation that you can subclass or instantiate directly (classes java.beans.beancontext.BeanContextSupport and java.beans.beancontext.BeanContextServicesSupport respectively). Also take note of the location of the java.beans.beancontext.BeanContextChild interface. This is the interface that allows nested JavaBeans to become aware of their enclosing BeanContext.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using the BeanContext API
Next page: Bean Context #1: Containment Only


Bean Context #1: Containment Only (The Java™ Tutorials > JavaBeans(TM) > Using the BeanContext API)

Trail: JavaBeans(TM)
Lesson: Using the BeanContext API
Using the BeanContext API
Overview of the BeanContext API
Bean Context #1: Containment Only
Bean Context #2: Containment and Services
AWT Containers and the BeanContextProxy Interface
Home Page > JavaBeans(TM) > Using the BeanContext API
« Previous • Trail • Next »
Bean Context #1: Containment Only

The "containment" portion of the Extensible Runtime Containment and Services Protocol is defined by the BeanContext interface. In its most basic form, a BeanContext is used to logically group a set of related java beans, bean contexts, or arbitrary objects. JavaBeans nested into a BeanContext are known as "child" beans. Once nested, a child bean can query its BeanContext for various membership information, as illustrated in the following examples.

Here are some possible BeanContext containment scenarios:

The sample code presented in this chapter uses instances of the BeanContextSupport helper class to provide the basic BeanContext functionality. A BeanContextSupport object is simply a concrete implementation of the BeanContext interface.

With a BeanContextSupport instance, it is possible to:

  • Add an object, bean, or BeanContext: boolean add(Object o)
  • Remove an object, bean, or BeanContext: boolean remove(Object o)
  • Add a BeanContextMembershipListener: void addBeanContextMembershipListener(BeanContextMembershipListener bcml)
  • Remove a BeanContextMembershipListener: void removeBeanContextMembershipListener(BeanContextMembershipListener bcml)
  • Get all JavaBean or BeanContext instances currently nested in this BeanContext as an array or as an Iterator: Object[] toArray(), Object[] toArray(Object[] a), and Iterator iterator()
  • Determine whether or not a specified object is currently a child of the BeanContext: boolean contains(Object o)
  • Get the number of children currently nested in this BeanContext: int size()
  • Determine whether or not the BeanContext currently has zero children: boolean isEmpty()
  • Instantiate a new JavaBean instance as a child of the target BeanContext: Object instantiateChild(String beanName)

The following test programs, which are run from the command line, illustrate the use of these methods.

The comments in the source code explain the purpose of each.

File: Example1.java
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.beans.beancontext.*;

/**
 * A test program that adds a bean to a beancontext, and
 * reports on various aspects of the context's membership state.
 * This program also shows that a bean's getBeanContext() method
 * can be called to get a reference to its enclosing context.
 */
public class Example1 {
    private static BeanContextSupport context = new BeanContextSupport(); // The BeanContext
    private static BeanContextChildSupport bean = new BeanContextChildSupport(); // The JavaBean

    public static void main(String[] args) {
        report();

        // Add the bean to the context
        System.out.println("Adding bean to context...");
        context.add(bean);

        report();
    }

    private static void report() {
        // Print out a report of the context's membership state.
        System.out.println("=============================================");

        // Is the context empty?
        System.out.println("Is the context empty? " + context.isEmpty());

        // Has the context been set for the child bean?
        boolean result = (bean.getBeanContext()!=null);
        System.out.println("Does the bean have a context yet? " + result);

        // Number of children in the context
        System.out.println("Number of children in the context: " + context.size());

        // Is the specific bean a member of the context?
        System.out.println("Is the bean a member of the context? " + context.contains(bean));

        // Equality test
        if (bean.getBeanContext() != null) {
            boolean isEqual = (bean.getBeanContext()==context); // true means both references point to the same object
            System.out.println("Contexts are the same? " + isEqual);
        }
        System.out.println("=============================================");
    }
}
Output:
=============================================
Is the context empty? true
Does the bean have a context yet? false
Number of children in the context: 0
Is the bean a member of the context? false
=============================================
Adding bean to context...
=============================================
Is the context empty? false
Does the bean have a context yet? true
Number of children in the context: 1
Is the bean a member of the context? true
Contexts are the same? true
=============================================
File: Example2.java
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.beans.beancontext.*;

/**
 * Test program that adds 100 beans to a context,
 * and calls size() to report the number of beans
 * currently nested. Finally,
 * this test calls toArray() to get references to
 * all child beans.
 */
public class Example2 {
    public static void main(String[] args) {

        // A BeanContext
        BeanContextSupport context = new BeanContextSupport();

        // Many JavaBeans
        BeanContextChildSupport[] beans = new BeanContextChildSupport[100];

        System.out.println("Number of children in the context: " + context.size());

        // Create the beans and add them to the context
        for (int i = 0; i < beans.length; i++) {
            beans[i] = new BeanContextSupport();
            context.add(beans[i]);
        }
        System.out.println("Number of children in the context: " + context.size());

        // Context now has 100 beans in it, get references to them all
        Object[] children = context.toArray();
        System.out.println("Number of objects retrieved from the context: " + children.length);
    }
}
Output:
Number of children in the context: 0
Number of children in the context: 100
Number of objects retrieved from the context: 100
File: Example3.java
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.beans.beancontext.*;
import java.io.*;

/**
 * An example of how to use the instantiateChild() convenience method
 * to create a bean automatically nested into a bean context.
 */
public class Example3 {
    public static void main(String[] args) {
        BeanContextSupport context = new BeanContextSupport();
        System.out.println("Number of children nested into the context: " + context.size());

        BeanContextChildSupport child = null;
        try {
            child = (BeanContextChildSupport)context.instantiateChild("java.beans.beancontext.BeanContextChildSupport");
        }
        catch(IOException e){
            System.out.println("IOException occurred: " + e.getMessage());
        }
        catch(ClassNotFoundException e){
            System.out.println("Class not found: " + e.getMessage());
        }
        System.out.println("Number of children nested into the context: " + context.size());
    }
}
Output:
Number of children nested into the context: 0
Number of children nested into the context: 1

BeanContextMembershipEvent Notification

The BeanContext API uses the standard Java event model to register listeners and deliver events. For an overview of this standard event model, refer to Writing Event Listeners. For details about handling specific events, see Writing Event Listeners.

In a basic BeanContext, the event classes and interfaces involved are:

  • java.beans.beancontext.BeanContextMembershipEvent: Encapsulates the list of children added to, or removed from, the membership of a particular BeanContext. An instance of this event is fired whenever a successful add(), remove(), retainAll(), removeAll(), or clear() is invoked on a given BeanContext instance.
  • java.beans.BeanContextMembershipListener: Objects wishing to receive BeanContextMembershipEvents implement this interface. It defines methods void childrenAdded(BeanContextMembershipEvent bcme) and void childrenRemoved(BeanContextMembershipEvent bcme), which are called when a child is added to or removed from a given BeanContext instance.

BeanContextMembershipEvent Notification: Sample Code

File: MembershipTest.java
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.beans.beancontext.*;

/**
 * A simple test program to illustrate delivery
 * of the BeanContextMembershipEvent.
 */
public class MembershipTest {
    public static void main(String[] args) {
        BeanContextSupport context = new BeanContextSupport(); // the context
        MyMembershipListener listener = new MyMembershipListener();
        BeanContextChildSupport bean = new BeanContextChildSupport(); // a JavaBean
        context.addBeanContextMembershipListener(listener); // now listening!
        context.add(bean);
        context.remove(bean);
    }
}

/**
 * A custom implementation of the BeanContextMembershipListener interface.
 */
class MyMembershipListener implements BeanContextMembershipListener {
    public void childrenAdded(BeanContextMembershipEvent bcme) {
        System.out.println("Another bean has been added to the context.");
    }

    public void childrenRemoved(BeanContextMembershipEvent bcme) {
        System.out.println("A bean has been removed from the context.");
    }
}
Output:
Another bean has been added to the context.
A bean has been removed from the context.

The same example, implemented using an anonymous inner class

import java.beans.beancontext.*;

public class MembershipTest {
    public static void main(String[] args) {
        BeanContextSupport context = new BeanContextSupport();
        context.addBeanContextMembershipListener(new BeanContextMembershipListener() {
            public void childrenAdded(BeanContextMembershipEvent bcme) {
                System.out.println("Another bean has been added to the context.");
            }

            public void childrenRemoved(BeanContextMembershipEvent bcme) {
                System.out.println("A bean has been removed from the context.");
            }
        });
        BeanContextChildSupport bean = new BeanContextChildSupport();
        context.add(bean);
        context.remove(bean);
    }
}
Output:
Another bean has been added to the context.
A bean has been removed from the context.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Overview of the BeanContext API
Next page: Bean Context #2: Containment and Services


Bean Context #2: Containment and Services (The Java™ Tutorials > JavaBeans(TM) > Using the BeanContext API)

Trail: JavaBeans(TM)
Lesson: Using the BeanContext API
Using the BeanContext API
Overview of the BeanContext API
Bean Context #1: Containment Only
Bean Context #2: Containment and Services
AWT Containers and the BeanContextProxy Interface
Home Page > JavaBeans(TM) > Using the BeanContext API
« Previous • Trail • Next »
Bean Context #2: Containment and Services

As mentioned in the introduction, the BeanContext API also provides a standard mechanism through which JavaBeans can discover and utilize the services offered by their enclosing BeanContext. Service capability is defined by the BeanContextServices interface. Because this interface is a BeanContext extension, it inherits all BeanContext membership capabilities. The discovery and requesting of services can be summarized in the following steps:

  1. A JavaBean that implements the java.beans.beancontext.BeanContextServicesListener interface joins the bean context (the context itself is a BeanContextServices implementation), and registers its intent to be notified of new services via the context's addBeanContextServicesListener(BeanContextServicesListener bcsl) method.
  2. A java.beans.beancontext.BeanContextServiceProvider registers a new service with the context via the context's addService() method. The context notifies all currently registered listeners that this new service has been added.
  3. After being notified of the newly available service, the listening JavaBean requests an instance of the service from the context.
  4. The context tells the service provider to deliver the service to the requesting JavaBean.

BeanContextServices: Service Related Methods

Using a java.beans.beancontext.BeanContextServicesSupport object as the bean context, it is possible to:
  • Add a service to this BeanContext: boolean addService(java.lang.Class serviceClass, BeanContextServiceProvider serviceProvider)
  • Add a service to this BeanContext: boolean addService(Class serviceClass, BeanContextServiceProvider bcsp, boolean fireEvent)
  • Revoke a service: void revokeService(java.lang.Class serviceClass, BeanContextServiceProvider serviceProvider, boolean revokeCurrentServicesNow)
  • Release a BeanContextChild's (or any arbitrary object associated with a BeanContextChild) reference to the specified service: void releaseService(BeanContextChild child, java.lang.Object requestor, java.lang.Object service)
  • Add a BeanContextServicesListener void addBeanContextServicesListener(BeanContextServicesListener bcsl)
  • Remove a BeanContextServicesListener: void removeBeanContextServicesListener(BeanContextServicesListener bcsl)
  • Get the currently available services for this context: Iterator getCurrentServiceClasses()
  • Determine whether or not a given service is currently available from this context: boolean hasService(java.lang.Class serviceClass)
  • Get a service from the context: Object getService(BeanContextChild child, java.lang.Object requestor, java.lang.Class serviceClass, java.lang.Object serviceSelector, BeanContextServiceRevokedListener bcsrl)
  • Get the list of service dependent service parameters (Service Selectors) for the specified service: Iterator getCurrentServiceSelectors(java.lang.Class serviceClass)

Service Event Notification

JavaBeans nested into a BeanContextServices implement BeanContextServicesListener to listen for new services being added, and/or BeanContextServiceRevokedListener to listen for services being revoked.

There are two event types that may be intercepted by such listeners:

  • BeanContextServiceAvailableEvent: received by the BeanContextServicesListener in order to identify the service being registered.
  • BeanContextServiceRevokedEvent: received by the BeanContextServiceRevokedListener in order to identify the service being revoked.

The Service Provider

JavaBeans can query their enclosing bean context for a list of available services, or ask for a specific service by name. The service itself, however, is actually delivered by a BeanContextServiceProvider. The provider can be any object that implements the java.beans.beancontext.BeanContextServiceProvider interface. Services become available in a context via the bean context's addService() registration method.

BeanContextServiceProvider offers the following three methods, which will be automatically called when a bean requests (or releases) a service from its context:

  • Object getService(BeanContextServices bcs, java.lang.Object requestor, java.lang.Class serviceClass, java.lang.Object serviceSelector)
  • Iterator getCurrentServiceSelectors(BeanContextServices bcs, java.lang.Class serviceClass)
  • public void releaseService(BeanContextServices bcs, java.lang.Object requestor, java.lang.Object service) Release a service from any object that currently has a reference to it

The Service

The service itself is best described by this paragraph from the specification:

A service, represented by a Class object, is typically a reference to either an interface, or to an implementation that is not publicly instantiable. This Class defines an interface protocol or contract between a BeanContextServiceProvider, the factory of the service, and an arbitrary object associated with a BeanContextChild that is currently nested within the BeanContext the service is registered with.

The following section presents a sample application that uses a word counting service to count the number of words in a given text file.

A Word Counting Service Example

The classes defined in this sample application are:
  • DocumentBean.java: A JavaBean that encapsulates a File object. Create an instance of this bean by passing it a String indicating the name of the text file to represent. This bean extends BeanContextChildSupport, which allows it to listen for addition/revocation of services in its context. When the bean detects that a WordCount service has been added to the context, it requests the service to count the number of words it contains.
  • WordCountServiceProvider.java: A class that acts as the factory for delivering the WordCount service. This class implements the BeanContextServiceProvider interface.
  • WordCount.java: This interface defines the service itself.
  • DocumentTester.java: The main test program.

File: DocumentBean.java

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.beans.beancontext.*;
import java.io.*;
import java.util.*;

/**
 * A JavaBean that encapsulates a text file. When added to a bean context,
 * this bean listens for a WordCount service to become available. When
 * the service does become available, the DocumentBean requests an
 * instance of the service. The service then counts the number of words in the file,
 * and prints a report to standard output.
 */
public final class DocumentBean extends BeanContextChildSupport {

    private File document;
    private BeanContextServices context;

    /**
     * Creates a new DocumentBean given the name of the file to read from.
     * @param fileName the name of the file to read from
     */
    public DocumentBean(String fileName) {
        document = new File(fileName);
    }

    /**
     * Called when this bean detects that a new service
     * has been registered with its context.
     *
     * @param bcsae the BeanContextServiceAvailableEvent
     */
    public void serviceAvailable(BeanContextServiceAvailableEvent bcsae) {
        System.out.println("[Detected a service being added to the context]");

        // Get a reference to the context
        BeanContextServices context = bcsae.getSourceAsBeanContextServices();
        System.out.println("Is the context offering a WordCount service? "
                           + context.hasService(WordCount.class));

        // Use the service, if it's available
        if (context.hasService(WordCount.class)) {
            System.out.println("Attempting to use the service...");
            try {
                WordCount service = (WordCount)context.getService(this, this,
                                                   WordCount.class, document, this);
                System.out.println("Got the service!");
                service.countWords();
            } catch(Exception e) { }
        }
    }

    /**
     * Called when this bean detects that a service
     * has been revoked from the context.
     *
     * @param bcsre the BeanContextServiceRevokedEvent
     */
    public void serviceRevoked(BeanContextServiceRevokedEvent bcsre) {
        System.out.println("[Detected a service being revoked from the context]");
    }
}

File: WordCountServiceProvider.java

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.beans.beancontext.*;
import java.util.*;
import java.io.*;

/**
 * This class is the factory that delivers a word counting service.
 * The 3 methods defined in this class are the concrete implementations
 * of the BeanContextServiceProvider interface. For this demonstration, the primary
 * method of interest is getService(). The getService() methods returns a new
 * WordCount instance. It is called by the bean context when a nested
 * JavaBean requests the service.
 */
public final class WordCountServiceProvider implements BeanContextServiceProvider {

    public Object getService(BeanContextServices bcs,
                             Object requestor,
                             Class serviceClass,
                             Object serviceSelector) {

        // For this demo, we know that the cast from serviceSelector
        // to File will always work.
        final File document = (File)serviceSelector;

        /*  Return an instance of the service. The service itself is
         *  the WordCount interface, which is implemented here using
         *  an anonymous inner class.
         */
        return new WordCount() {
            public void countWords() {
                try {
                    // Create a Reader to the DocumentBean's File
                    BufferedReader br = new BufferedReader(new FileReader(document));
                    String line = null;
                    int wordCount = 0;
                    while ((line = br.readLine()) != null) {
                        StringTokenizer st = new StringTokenizer(line);
                        while (st.hasMoreTokens()) {
                            System.out.println("Word " + (++wordCount)
                                               + " is: " + st.nextToken());
                        }
                    }
                    System.out.println("Total number of words in the document: "
                                       + wordCount);
                    System.out.println("[WordCount service brought to you by WordCountServiceProvider]");
                    br.close();
                 } catch(Exception e) { }
            }
        };
    }

    public void releaseService(BeanContextServices bcs,
                               Object requestor,
                               Object service) {
        // do nothing
    }

    public Iterator getCurrentServiceSelectors(BeanContextServices bcs, Class serviceClass) {
        return null; // do nothing
    }
}

File: WordCount.java

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

/**
 * The WordCount service. Implementations of the
 * countWords() method are provided by the
 * WordCountServiceProvider class.
 */
public interface WordCount {

     /**
      * Counts the number of words in the file.
      */
     public abstract void countWords();

}

File: DocumentTester.java

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.beans.beancontext.*;
import java.util.*;

/**
 * A test program that creates all of the objects,
 * a tests the service capabilities. Run this program
 * from the command line using java DocumentTester
 */
public class DocumentTester {

     public static void main(String[] args) {
          BeanContextServicesSupport context = new BeanContextServicesSupport(); // a bean context
          DocumentBean doc1 = new DocumentBean("Test.txt");
          context.add(doc1);
          context.addBeanContextServicesListener(doc1); // listen for new services
          WordCountServiceProvider provider = new WordCountServiceProvider();
          context.addService(WordCount.class, provider); // add the service to the context
     }
}

File: Test.txt

This   text will  be analyzed

 by the WordCount

service.

Output:

[Detected a service being added to the context]
Is the context offering a WordCount service? true
Attempting to use the service...
Got the service!
Word 1 is: This
Word 2 is: text
Word 3 is: will
Word 4 is: be
Word 5 is: analyzed
Word 6 is: by
Word 7 is: the
Word 8 is: WordCount
Word 9 is: service.
Total number of words in the document: 9
[WordCount service brought to you by WordCountServiceProvider]
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Bean Context #1: Containment Only
Next page: AWT Containers and the BeanContextProxy Interface


AWT Containers and the BeanContextProxy Interface (The Java™ Tutorials > JavaBeans(TM) > Using the BeanContext API)

Trail: JavaBeans(TM)
Lesson: Using the BeanContext API
Using the BeanContext API
Overview of the BeanContext API
Bean Context #1: Containment Only
Bean Context #2: Containment and Services
AWT Containers and the BeanContextProxy Interface
Home Page > JavaBeans(TM) > Using the BeanContext API
« Previous • Trail • Next »
AWT Containers and the BeanContextProxy Interface

Sometimes, it is desirable for an AWT Container to act as a BeanContext. However, AWT Containers cannot implement the BeanContext interface directly, because of a method name collision between Component and Collection. If some AWT Component needs to act as a BeanContext, it must internally create a BeanContext instance and delegate work to it. Third parties, such as visual builder tools, can discover this BeanContext instance if the Component implements the BeanContextProxy interface.

The BeanContextProxy Interface

public BeanContextChild getBeanContextProxy() - Gets the BeanContextChild (or subinterface) associated with this object.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Bean Context #2: Containment and Services
Next page: End of Trail


Trail: JDBC(TM) Database Access (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: JDBC(TM) Database Access

The JDBC™ API was designed to keep simple things simple. This means that the JDBC makes everyday database tasks easy. This trail walks you through examples of using JDBC to execute common SQL statements, and perform other objectives common to database applications.

This trail is divided into these lessons:

JDBC Introduction Lists JDBC features, describes JDBC Architecture and reviews SQL commands and Relational Database concepts.

JDBC Basics covers the JDBC API, which is included in the Java™ SE 6 release.

By the end of the first lesson, you will know how to use the basic JDBC API to create tables, insert values into them, query the tables, retrieve the results of the queries, and update the tables. In this process, you will learn how to use simple statements and prepared statements, and you will see an example of a stored procedure. You will also learn how to perform transactions and how to catch exceptions and warnings.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: JDBC Introduction


Lesson: JDBC Introduction (The Java™ Tutorials > JDBC(TM) Database Access)

JDBC Introduction
JDBC Architecture
A Relational Database Overview
Trail: JDBC(TM) Database Access
Home Page > JDBC(TM) Database Access
« Previous • Trail • Next »
Lesson: JDBC Introduction

JDBC Introduction

The JDBC API is a Java API that can access any kind of tabular data, especially data stored in a Relational Database.

JDBC helps you to write java applications that manage these three programming activities:

  1. Connect to a data source, like a database
  2. Send queries and update statements to the database
  3. Retrieve and process the results received from the database in answer to your query

    The following simple code fragment gives a simple example of these three steps:

    Connection con = DriverManager.getConnection
           ( "jdbc:myDriver:wombat", "myLogin","myPassword");

Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT a, b, c FROM Table1");
while (rs.next()) {
    int x = rs.getInt("a");
    String s = rs.getString("b");
    float f = rs.getFloat("c");
    }

    This short code fragment instantiates a DriverManager object to connect to a database driver and log into the database, instantiates a Statement object that carries your SQL language query to the database; instantiates a ResultSet object that retrieves the results of your query, and executes a simple while loop, which retrieves and displays those results. It's that simple.

JDBC Product Components

JDBC includes four components:

  1. The JDBC API —

    The JDBC™ API provides programmatic access to relational data from the Java™ programming language. Using the JDBC API, applications can execute SQL statements, retrieve results, and propagate changes back to an underlying data source. The JDBC API can also interact with multiple data sources in a distributed, heterogeneous environment.

    The JDBC API is part of the Java platform, which includes the Java™ Standard Edition (Java™ SE ) and the Java™ Enterprise Edition (Java™ EE). The JDBC 4.0 API is divided into two packages: java.sql and javax.sql. Both packages are included in the Java SE and Java EE platforms.

  2. JDBC Driver Manager —

    The JDBC DriverManager class defines objects which can connect Java applications to a JDBC driver. DriverManager has traditionally been the backbone of the JDBC architecture. It is quite small and simple.

    The Standard Extension packages javax.naming and javax.sql let you use a DataSource object registered with a Java Naming and Directory Interface™ (JNDI) naming service to establish a connection with a data source. You can use either connecting mechanism, but using a DataSource object is recommended whenever possible.

  3. JDBC Test Suite —

    The JDBC driver test suite helps you to determine that JDBC drivers will run your program. These tests are not comprehensive or exhaustive, but they do exercise many of the important features in the JDBC API.

  4. JDBC-ODBC Bridge —

    The Java Software bridge provides JDBC access via ODBC drivers. Note that you need to load ODBC binary code onto each client machine that uses this driver. As a result, the ODBC driver is most appropriate on a corporate network where client installations are not a major problem, or for application server code written in Java in a three-tier architecture.

This Trail uses the first two of these these four JDBC components to connect to a database and then build a java program that uses SQL commands to communicate with a test Relational Database. The last two components are used in specialized environments to test web applications, or to communicate with ODBC-aware DBMSs.

JDBC Architecture

Two-tier and Three-tier Processing Models

The JDBC API supports both two-tier and three-tier processing models for database access.

Figure 1: Two-tier Architecture for Data Access.

The DBMS-proprietary protocol provides two-way communication between the client machine and the database server

In the two-tier model, a Java applet or application talks directly to the data source. This requires a JDBC driver that can communicate with the particular data source being accessed. A user's commands are delivered to the database or other data source, and the results of those statements are sent back to the user. The data source may be located on another machine to which the user is connected via a network. This is referred to as a client/server configuration, with the user's machine as the client, and the machine housing the data source as the server. The network can be an intranet, which, for example, connects employees within a corporation, or it can be the Internet.

In the three-tier model, commands are sent to a "middle tier" of services, which then sends the commands to the data source. The data source processes the commands and sends the results back to the middle tier, which then sends them to the user. MIS directors find the three-tier model very attractive because the middle tier makes it possible to maintain control over access and the kinds of updates that can be made to corporate data. Another advantage is that it simplifies the deployment of applications. Finally, in many cases, the three-tier architecture can provide performance advantages.

Figure 2: Three-tier Architecture for Data Access.

The DBMS-proprietary protocol provides two-way communication between the database server and the server machine. HTTP, RMI, CORBA or other calls provide two way communication between the server machine and the client machine

Until recently, the middle tier has often been written in languages such as C or C++, which offer fast performance. However, with the introduction of optimizing compilers that translate Java bytecode into efficient machine-specific code and technologies such as Enterprise JavaBeans™, the Java platform is fast becoming the standard platform for middle-tier development. This is a big plus, making it possible to take advantage of Java's robustness, multithreading, and security features.

With enterprises increasingly using the Java programming language for writing server code, the JDBC API is being used more and more in the middle tier of a three-tier architecture. Some of the features that make JDBC a server technology are its support for connection pooling, distributed transactions, and disconnected rowsets. The JDBC API is also what allows access to a data source from a Java middle tier.

A Relational Database Overview

A database is a means of storing information in such a way that information can be retrieved from it. In simplest terms, a relational database is one that presents information in tables with rows and columns. A table is referred to as a relation in the sense that it is a collection of objects of the same type (rows). Data in a table can be related according to common keys or concepts, and the ability to retrieve related data from a table is the basis for the term relational database. A Database Management System (DBMS) handles the way data is stored, maintained, and retrieved. In the case of a relational database, a Relational Database Management System (RDBMS) performs these tasks. DBMS as used in this book is a general term that includes RDBMS.

Integrity Rules

Relational tables follow certain integrity rules to ensure that the data they contain stay accurate and are always accessible. First, the rows in a relational table should all be distinct. If there are duplicate rows, there can be problems resolving which of two possible selections is the correct one. For most DBMSs, the user can specify that duplicate rows are not allowed, and if that is done, the DBMS will prevent the addition of any rows that duplicate an existing row.

A second integrity rule of the traditional relational model is that column values must not be repeating groups or arrays. A third aspect of data integrity involves the concept of a null value. A database takes care of situations where data may not be available by using a null value to indicate that a value is missing. It does not equate to a blank or zero. A blank is considered equal to another blank, a zero is equal to another zero, but two null values are not considered equal.

When each row in a table is different, it is possible to use one or more columns to identify a particular row. This unique column or group of columns is called a primary key. Any column that is part of a primary key cannot be null; if it were, the primary key containing it would no longer be a complete identifier. This rule is referred to as entity integrity.

Table 1.2 illustrates some of these relational database concepts. It has five columns and six rows, with each row representing a different employee.

Table 1.2: Employees

Employee_Number | First_name | Last_Name | Date_of_Birth | Car_Number
10001 | Axel | Washington | 28-Aug-43 | 5
10083 | Arvid | Sharma | 24-Nov-54 | null
10120 | Jonas | Ginsberg | 01-Jan-69 | null
10005 | Florence | Wojokowski | 04-Jul-71 | 12
10099 | Sean | Washington | 21-Sep-66 | null
10035 | Elizabeth | Yamaguchi | 24-Dec-59 | null

The primary key for this table would generally be the employee number because each one is guaranteed to be different. (A number is also more efficient than a string for making comparisons.) It would also be possible to use First_Name and Last_Name because the combination of the two also identifies just one row in our sample database. Using the last name alone would not work because there are two employees with the last name of "Washington." In this particular case the first names are all different, so one could conceivably use that column as a primary key, but it is best to avoid using a column where duplicates could occur. If Elizabeth Taylor gets a job at this company and the primary key is First_Name, the RDBMS will not allow her name to be added (if it has been specified that no duplicates are permitted). Because there is already an Elizabeth in the table, adding a second one would make the primary key useless as a way of identifying just one row. Note that although using First_Name and Last_Name is a unique composite key for this example, it might not be unique in a larger database. Note also that Table 1.2 assumes that there can be only one car per employee.

SELECT Statements

SQL is a language designed to be used with relational databases. There is a set of basic SQL commands that is considered standard and is used by all RDBMSs. For example, all RDBMSs use the SELECT statement.

A SELECT statement, also called a query, is used to get information from a table. It specifies one or more column headings, one or more tables from which to select, and some criteria for selection. The RDBMS returns rows of the column entries that satisfy the stated requirements. A SELECT statement such as the following will fetch the first and last names of employees who have company cars:

SELECT First_Name, Last_Name
FROM Employees
WHERE Car_Number IS NOT NULL

The result set (the set of rows that satisfy the requirement of not having null in the Car_Number column) follows. The first name and last name are printed for each row that satisfies the requirement because the SELECT statement (the first line) specifies the columns First_Name and Last_Name. The FROM clause (the second line) gives the table from which the columns will be selected.

FIRST_NAME                LAST_NAME
----------                -----------
Axel                      Washington
Florence                  Wojokowski

The following code produces a result set that includes the whole table because it asks for all of the columns in the table Employees with no restrictions (no WHERE clause). Note that SELECT * means "SELECT all columns."

SELECT *
FROM Employees

WHERE Clauses

The WHERE clause in a SELECT statement provides the criteria for selecting values. For example, in the following code fragment, values will be selected only if they occur in a row in which the column Last_Name begins with the string 'Washington'.

SELECT First_Name, Last_Name
FROM Employees
WHERE Last_Name LIKE 'Washington%'

The keyword LIKE is used to compare strings, and it offers the feature that patterns containing wildcards can be used. For example, in the code fragment above, there is a percent sign (%) at the end of 'Washington', which signifies that any value containing the string 'Washington' plus zero or more additional characters will satisfy this selection criterion. So 'Washington' or 'Washingtonian' would be matches, but 'Washing' would not be. The other wildcard used in LIKE clauses is an underbar (_), which stands for any one character. For example,

WHERE Last_Name LIKE 'Ba_man'

would match 'Batman', 'Barman', 'Badman', 'Balman', 'Bagman', 'Bamman', and so on.

The code fragment below has a WHERE clause that uses the equal sign (=) to compare numbers. It selects the first and last name of the employee who is assigned car 12.

SELECT First_Name, Last_Name
FROM Employees
WHERE Car_Number = 12

The next code fragment selects the first and last names of employees whose employee number is greater than 10005:

SELECT First_Name, Last_Name
FROM Employees
WHERE Employee_Number > 10005

WHERE clauses can get rather elaborate, with multiple conditions and, in some DBMSs, nested conditions. This overview will not cover complicated WHERE clauses, but the following code fragment has a WHERE clause with two conditions; this query selects the first and last names of employees whose employee number is less than 10100 and who do not have a company car.

SELECT First_Name, Last_Name
FROM Employees
WHERE Employee_Number < 10100 and Car_Number IS NULL

A special type of WHERE clause involves a join, which is explained in the next section.

Joins

A distinguishing feature of relational databases is that it is possible to get data from more than one table in what is called a join. Suppose that after retrieving the names of employees who have company cars, one wanted to find out who has which car, including the make, model, and year of car. This information is stored in another table, Cars, shown in Table 1.3.

Table 1.3. Cars

Car Number | Make | Model | Year
5 | Honda | Civic DX | 1996
12 | Toyota | Corolla | 1999

There must be one column that appears in both tables in order to relate them to each other. This column, which must be the primary key in one table, is called the foreign key in the other table. In this case, the column that appears in two tables is Car_Number, which is the primary key for the table Cars and the foreign key in the table Employees. If the 1996 Honda Civic were wrecked and deleted from the Cars table, then Car_Number 5 would also have to be removed from the Employees table in order to maintain what is called referential integrity. Otherwise, the foreign key column (Car_Number) in Employees would contain an entry that did not refer to anything in Cars. A foreign key must either be null or equal to an existing primary key value of the table to which it refers. This is different from a primary key, which may not be null. There are several null values in the Car_Number column in the table Employees because it is possible for an employee not to have a company car.

The following code asks for the first and last names of employees who have company cars and for the make, model, and year of those cars. Note that the FROM clause lists both Employees and Cars because the requested data is contained in both tables. Using the table name and a dot (.) before the column name indicates which table contains the column.

SELECT Employees.First_Name, Employees.Last_Name, Cars.Make,
           Cars.Model, Cars.Year
FROM Employees, Cars
WHERE Employees.Car_Number = Cars.Car_Number

This returns a result set that will look similar to the following:

FIRST_NAME   LAST_NAME      MAKE        MODEL     YEAR
-----------  ------------   --------   ---------  -------
Axel         Washington     Honda       CivicDX   1996
Florence     Wojokowski     Toyota      Corolla   1999

Common SQL Commands

SQL commands are divided into categories, the two main ones being Data Manipulation Language (DML) commands and Data Definition Language (DDL) commands. DML commands deal with data, either retrieving it or modifying it to keep it up-to-date. DDL commands create or change tables and other database objects such as views and indexes.

A list of the more common DML commands follows:

  • SELECT —  used to query and display data from a database. The SELECT statement specifies which columns to include in the result set. The vast majority of the SQL commands used in applications are SELECT statements.

  • INSERT —  adds new rows to a table. INSERT is used to populate a newly created table or to add a new row (or rows) to an already-existing table.

  • DELETE —  removes a specified row or set of rows from a table

  • UPDATE —  changes an existing value in a column or group of columns in a table

The more common DDL commands follow:

  • CREATE TABLE —  creates a table with the column names the user provides. The user also needs to specify a type for the data in each column. Data types vary from one RDBMS to another, so a user might need to use metadata to establish the data types used by a particular database. CREATE TABLE is normally used less often than the data manipulation commands because a table is created only once, whereas adding or deleting rows or changing individual values generally occurs more frequently.

  • DROP TABLE —  deletes all rows and removes the table definition from the database. A JDBC API implementation is required to support the DROP TABLE command as specified by SQL92, Transitional Level. However, support for the CASCADE and RESTRICT options of DROP TABLE is optional. In addition, the behavior of DROP TABLE is implementation-defined when there are views or integrity constraints defined that reference the table being dropped.

  • ALTER TABLE —  adds or removes a column from a table. It also adds or drops table constraints and alters column attributes

Result Sets and Cursors

The rows that satisfy the conditions of a query are called the result set. The number of rows returned in a result set can be zero, one, or many. A user can access the data in a result set one row at a time, and a cursor provides the means to do that. A cursor can be thought of as a pointer into a file that contains the rows of the result set, and that pointer has the ability to keep track of which row is currently being accessed. A cursor allows a user to process each row of a result set from top to bottom and consequently may be used for iterative processing. Most DBMSs create a cursor automatically when a result set is generated.

Earlier JDBC API versions added new capabilities for a result set's cursor, allowing it to move both forward and backward and also allowing it to move to a specified row or to a row whose position is relative to another row.

Transactions

When one user is accessing data in a database, another user may be accessing the same data at the same time. If, for instance, the first user is updating some columns in a table at the same time the second user is selecting columns from that same table, it is possible for the second user to get partly old data and partly updated data. For this reason, DBMSs use transactions to maintain data in a consistent state (data consistency) while allowing more than one user to access a database at the same time (data concurrency).

A transaction is a set of one or more SQL statements that make up a logical unit of work. A transaction ends with either a commit or a rollback, depending on whether there are any problems with data consistency or data concurrency. The commit statement makes permanent the changes resulting from the SQL statements in the transaction, and the rollback statement undoes all changes resulting from the SQL statements in the transaction.

A lock is a mechanism that prohibits two transactions from manipulating the same data at the same time. For example, a table lock prevents a table from being dropped if there is an uncommitted transaction on that table. In some DBMSs, a table lock also locks all of the rows in a table. A row lock prevents two transactions from modifying the same row, or it prevents one transaction from selecting a row while another transaction is still modifying it.

Stored Procedures

A stored procedure is a group of SQL statements that can be called by name. In other words, it is executable code, a mini-program, that performs a particular task that can be invoked the same way one can call a function or method. Traditionally, stored procedures have been written in a DBMS-specific programming language. The latest generation of database products allows stored procedures to be written using the Java programming language and the JDBC API. Stored procedures written in the Java programming language are bytecode portable between DBMSs. Once a stored procedure is written, it can be used and reused because a DBMS that supports stored procedures will, as its name implies, store it in the database.

The following code is an example of how to create a very simple stored procedure using the Java programming language. Note that the stored procedure is just a static Java method that contains normal JDBC code. It accepts two input parameters and uses them to change an employee's car number.

Do not worry if you do not understand the example at this point. The code example below is presented only to illustrate what a stored procedure looks like. You will learn how to write the code in this example in the tutorials that follow.

import java.sql.*;

public class UpdateCar {

    public static void UpdateCarNum(int carNo, int empNo)
                                              throws SQLException {
        Connection con = null;
        PreparedStatement pstmt = null;

        try {
          con = DriverManager.getConnection("jdbc:default:connection");

            pstmt = con.prepareStatement(
                        "UPDATE EMPLOYEES SET CAR_NUMBER = ? " +
                        "WHERE EMPLOYEE_NUMBER = ?");
            pstmt.setInt(1, carNo);
            pstmt.setInt(2, empNo);
            pstmt.executeUpdate();
        }
        finally {
            if (pstmt != null) pstmt.close();
        }
    }
}

Metadata

Databases store user data, and they also store information about the database itself. Most DBMSs have a set of system tables, which list tables in the database, column names in each table, primary keys, foreign keys, stored procedures, and so forth. Each DBMS has its own functions for getting information about table layouts and database features. JDBC provides the interface DatabaseMetaData, which a driver writer must implement so that its methods return information about the driver and/or DBMS for which the driver is written. For example, a large number of methods return whether or not the driver supports a particular functionality. This interface gives users and tools a standardized way to get metadata. In general, developers writing tools and drivers are the ones most likely to be concerned with metadata.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: JDBC Architecture


JDBC Architecture (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Introduction)

Trail: JDBC(TM) Database Access
Lesson: JDBC Introduction
JDBC Introduction
JDBC Architecture
A Relational Database Overview
Home Page > JDBC(TM) Database Access > JDBC Introduction
« Previous • Trail • Next »
JDBC Architecture

The JDBC API supports both two-tier and three-tier processing models for database access.

Figure 1: Two-tier Architecture for Data Access.

The DBMS-proprietary protocol provides two-way communication between the client machine and the database server

In the two-tier model, a Java application talks directly to the data source. This requires a JDBC driver that can communicate with the particular data source being accessed. A user's commands are delivered to the database or other data source, and the results of those statements are sent back to the user. The data source may be located on another machine to which the user is connected via a network. This is referred to as a client/server configuration, with the user's machine as the client, and the machine housing the data source as the server. The network can be an intranet, which, for example, connects employees within a corporation, or it can be the Internet.

In the three-tier model, commands are sent to a "middle tier" of services, which then sends the commands to the data source. The data source processes the commands and sends the results back to the middle tier, which then sends them to the user. MIS directors find the three-tier model very attractive because the middle tier makes it possible to maintain control over access and the kinds of updates that can be made to corporate data. Another advantage is that it simplifies the deployment of applications. Finally, in many cases, the three-tier architecture can provide performance advantages.

Figure 2: Three-tier Architecture for Data Access.

The DBMS-proprietary protocol provides two-way communication between the database server and the server machine. HTTP, RMI, CORBA or other calls provide two way communication between the server machine and the client machine

Until recently, the middle tier has often been written in languages such as C or C++, which offer fast performance. However, with the introduction of optimizing compilers that translate Java bytecode into efficient machine-specific code and technologies such as Enterprise JavaBeans™, the Java platform is fast becoming the standard platform for middle-tier development. This is a big plus, making it possible to take advantage of Java's robustness, multithreading, and security features.

With enterprises increasingly using the Java programming language for writing server code, the JDBC API is being used more and more in the middle tier of a three-tier architecture. Some of the features that make JDBC a server technology are its support for connection pooling, distributed transactions, and disconnected rowsets. The JDBC API is also what allows access to a data source from a Java middle tier.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: JDBC Introduction
Next page: A Relational Database Overview


A Relational Database Overview (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Introduction)

Trail: JDBC(TM) Database Access
Lesson: JDBC Introduction
JDBC Introduction
JDBC Architecture
A Relational Database Overview
Home Page > JDBC(TM) Database Access > JDBC Introduction
« Previous • Trail • Next »
A Relational Database Overview

A database is a means of storing information in such a way that information can be retrieved from it. In simplest terms, a relational database is one that presents information in tables with rows and columns. A table is referred to as a relation in the sense that it is a collection of objects of the same type (rows). Data in a table can be related according to common keys or concepts, and the ability to retrieve related data from a table is the basis for the term relational database. A Database Management System (DBMS) handles the way data is stored, maintained, and retrieved. In the case of a relational database, a Relational Database Management System (RDBMS) performs these tasks. DBMS as used in this book is a general term that includes RDBMS.

Integrity Rules

Relational tables follow certain integrity rules to ensure that the data they contain stay accurate and are always accessible. First, the rows in a relational table should all be distinct. If there are duplicate rows, there can be problems resolving which of two possible selections is the correct one. For most DBMSs, the user can specify that duplicate rows are not allowed, and if that is done, the DBMS will prevent the addition of any rows that duplicate an existing row.

A second integrity rule of the traditional relational model is that column values must not be repeating groups or arrays. A third aspect of data integrity involves the concept of a null value. A database takes care of situations where data may not be available by using a null value to indicate that a value is missing. It does not equate to a blank or zero. A blank is considered equal to another blank, a zero is equal to another zero, but two null values are not considered equal.

When each row in a table is different, it is possible to use one or more columns to identify a particular row. This unique column or group of columns is called a primary key. Any column that is part of a primary key cannot be null; if it were, the primary key containing it would no longer be a complete identifier. This rule is referred to as entity integrity.

Table 1.2 illustrates some of these relational database concepts. It has five columns and six rows, with each row representing a different employee.

Table 1.2: Employees

Employee_Number | First_name | Last_Name | Date_of_Birth | Car_Number
10001 | Axel | Washington | 28-Aug-43 | 5
10083 | Arvid | Sharma | 24-Nov-54 | null
10120 | Jonas | Ginsberg | 01-Jan-69 | null
10005 | Florence | Wojokowski | 04-Jul-71 | 12
10099 | Sean | Washington | 21-Sep-66 | null
10035 | Elizabeth | Yamaguchi | 24-Dec-59 | null

The primary key for this table would generally be the employee number because each one is guaranteed to be different. (A number is also more efficient than a string for making comparisons.) It would also be possible to use First_Name and Last_Name because the combination of the two also identifies just one row in our sample database. Using the last name alone would not work because there are two employees with the last name of "Washington." In this particular case the first names are all different, so one could conceivably use that column as a primary key, but it is best to avoid using a column where duplicates could occur. If Elizabeth Taylor gets a job at this company and the primary key is First_Name, the RDBMS will not allow her name to be added (if it has been specified that no duplicates are permitted). Because there is already an Elizabeth in the table, adding a second one would make the primary key useless as a way of identifying just one row. Note that although using First_Name and Last_Name is a unique composite key for this example, it might not be unique in a larger database. Note also that Table 1.2 assumes that there can be only one car per employee.

SELECT Statements

SQL is a language designed to be used with relational databases. There is a set of basic SQL commands that is considered standard and is used by all RDBMSs. For example, all RDBMSs use the SELECT statement.

A SELECT statement, also called a query, is used to get information from a table. It specifies one or more column headings, one or more tables from which to select, and some criteria for selection. The RDBMS returns rows of the column entries that satisfy the stated requirements. A SELECT statement such as the following will fetch the first and last names of employees who have company cars:

SELECT First_Name, Last_Name
FROM Employees
WHERE Car_Number IS NOT NULL

The result set (the set of rows that satisfy the requirement of not having null in the Car_Number column) follows. The first name and last name are printed for each row that satisfies the requirement because the SELECT statement (the first line) specifies the columns First_Name and Last_Name. The FROM clause (the second line) gives the table from which the columns will be selected.

FIRST_NAME                LAST_NAME
----------                -----------
Axel                      Washington
Florence                  Wojokowski

The following code produces a result set that includes the whole table because it asks for all of the columns in the table Employees with no restrictions (no WHERE clause). Note that SELECT * means "SELECT all columns."

SELECT *
FROM Employees

WHERE Clauses

The WHERE clause in a SELECT statement provides the criteria for selecting values. For example, in the following code fragment, values will be selected only if they occur in a row in which the column Last_Name begins with the string 'Washington'.

SELECT First_Name, Last_Name
FROM Employees
WHERE Last_Name LIKE 'Washington%'

The keyword LIKE is used to compare strings, and it offers the feature that patterns containing wildcards can be used. For example, in the code fragment above, there is a percent sign (%) at the end of 'Washington', which signifies that any value containing the string 'Washington' plus zero or more additional characters will satisfy this selection criterion. So 'Washington' or 'Washingtonian' would be matches, but 'Washing' would not be. The other wildcard used in LIKE clauses is an underbar (_), which stands for any one character. For example,

WHERE Last_Name LIKE 'Ba_man'

would match 'Batman', 'Barman', 'Badman', 'Balman', 'Bagman', 'Bamman', and so on.

The code fragment below has a WHERE clause that uses the equal sign (=) to compare numbers. It selects the first and last name of the employee who is assigned car 12.

SELECT First_Name, Last_Name
FROM Employees
WHERE Car_Number = 12

The next code fragment selects the first and last names of employees whose employee number is greater than 10005:

SELECT First_Name, Last_Name
FROM Employees
WHERE Employee_Number > 10005

WHERE clauses can get rather elaborate, with multiple conditions and, in some DBMSs, nested conditions. This overview will not cover complicated WHERE clauses, but the following code fragment has a WHERE clause with two conditions; this query selects the first and last names of employees whose employee number is less than 10100 and who do not have a company car.

SELECT First_Name, Last_Name
FROM Employees
WHERE Employee_Number < 10100 and Car_Number IS NULL

A special type of WHERE clause involves a join, which is explained in the next section.

Joins

A distinguishing feature of relational databases is that it is possible to get data from more than one table in what is called a join. Suppose that after retrieving the names of employees who have company cars, one wanted to find out who has which car, including the make, model, and year of car. This information is stored in another table, Cars, shown in Table 1.3.

Table 1.3. Cars

Car Number | Make | Model | Year
5 | Honda | Civic DX | 1996
12 | Toyota | Corolla | 1999

There must be one column that appears in both tables in order to relate them to each other. This column, which must be the primary key in one table, is called the foreign key in the other table. In this case, the column that appears in two tables is Car_Number, which is the primary key for the table Cars and the foreign key in the table Employees. If the 1996 Honda Civic were wrecked and deleted from the Cars table, then Car_Number 5 would also have to be removed from the Employees table in order to maintain what is called referential integrity. Otherwise, the foreign key column (Car_Number) in Employees would contain an entry that did not refer to anything in Cars. A foreign key must either be null or equal to an existing primary key value of the table to which it refers. This is different from a primary key, which may not be null. There are several null values in the Car_Number column in the table Employees because it is possible for an employee not to have a company car.

The following code asks for the first and last names of employees who have company cars and for the make, model, and year of those cars. Note that the FROM clause lists both Employees and Cars because the requested data is contained in both tables. Using the table name and a dot (.) before the column name indicates which table contains the column.

SELECT Employees.First_Name, Employees.Last_Name, Cars.Make,
           Cars.Model, Cars.Year
FROM Employees, Cars
WHERE Employees.Car_Number = Cars.Car_Number

This returns a result set that will look similar to the following:

FIRST_NAME   LAST_NAME      MAKE        MODEL     YEAR
-----------  ------------   --------   ---------  -------
Axel         Washington     Honda       CivicDX   1996
Florence     Wojokowski     Toyota      Corolla   1999

Common SQL Commands

SQL commands are divided into categories, the two main ones being Data Manipulation Language (DML) commands and Data Definition Language (DDL) commands. DML commands deal with data, either retrieving it or modifying it to keep it up-to-date. DDL commands create or change tables and other database objects such as views and indexes.

A list of the more common DML commands follows:

  • SELECT —  used to query and display data from a database. The SELECT statement specifies which columns to include in the result set. The vast majority of the SQL commands used in applications are SELECT statements.

  • INSERT —  adds new rows to a table. INSERT is used to populate a newly created table or to add a new row (or rows) to an already-existing table.

  • DELETE —  removes a specified row or set of rows from a table

  • UPDATE —  changes an existing value in a column or group of columns in a table

The more common DDL commands follow:

  • CREATE TABLE —  creates a table with the column names the user provides. The user also needs to specify a type for the data in each column. Data types vary from one RDBMS to another, so a user might need to use metadata to establish the data types used by a particular database. CREATE TABLE is normally used less often than the data manipulation commands because a table is created only once, whereas adding or deleting rows or changing individual values generally occurs more frequently.

  • DROP TABLE —  deletes all rows and removes the table definition from the database. A JDBC API implementation is required to support the DROP TABLE command as specified by SQL92, Transitional Level. However, support for the CASCADE and RESTRICT options of DROP TABLE is optional. In addition, the behavior of DROP TABLE is implementation-defined when there are views or integrity constraints defined that reference the table being dropped.

  • ALTER TABLE —  adds or removes a column from a table. It also adds or drops table constraints and alters column attributes

Result Sets and Cursors

The rows that satisfy the conditions of a query are called the result set. The number of rows returned in a result set can be zero, one, or many. A user can access the data in a result set one row at a time, and a cursor provides the means to do that. A cursor can be thought of as a pointer into a file that contains the rows of the result set, and that pointer has the ability to keep track of which row is currently being accessed. A cursor allows a user to process each row of a result set from top to bottom and consequently may be used for iterative processing. Most DBMSs create a cursor automatically when a result set is generated.

Earlier JDBC API versions added new capabilities for a result set's cursor, allowing it to move both forward and backward and also allowing it to move to a specified row or to a row whose position is relative to another row.

Transactions

When one user is accessing data in a database, another user may be accessing the same data at the same time. If, for instance, the first user is updating some columns in a table at the same time the second user is selecting columns from that same table, it is possible for the second user to get partly old data and partly updated data. For this reason, DBMSs use transactions to maintain data in a consistent state (data consistency) while allowing more than one user to access a database at the same time (data concurrency).

A transaction is a set of one or more SQL statements that make up a logical unit of work. A transaction ends with either a commit or a rollback, depending on whether there are any problems with data consistency or data concurrency. The commit statement makes permanent the changes resulting from the SQL statements in the transaction, and the rollback statement undoes all changes resulting from the SQL statements in the transaction.

A lock is a mechanism that prohibits two transactions from manipulating the same data at the same time. For example, a table lock prevents a table from being dropped if there is an uncommitted transaction on that table. In some DBMSs, a table lock also locks all of the rows in a table. A row lock prevents two transactions from modifying the same row, or it prevents one transaction from selecting a row while another transaction is still modifying it.

Stored Procedures

A stored procedure is a group of SQL statements that can be called by name. In other words, it is executable code, a mini-program, that performs a particular task that can be invoked the same way one can call a function or method. Traditionally, stored procedures have been written in a DBMS-specific programming language. The latest generation of database products allows stored procedures to be written using the Java programming language and the JDBC API. Stored procedures written in the Java programming language are bytecode portable between DBMSs. Once a stored procedure is written, it can be used and reused because a DBMS that supports stored procedures will, as its name implies, store it in the database.

The following code is an example of how to create a very simple stored procedure using the Java programming language. Note that the stored procedure is just a static Java method that contains normal JDBC code. It accepts two input parameters and uses them to change an employee's car number.

Do not worry if you do not understand the example at this point. The code example below is presented only to illustrate what a stored procedure looks like. You will learn how to write the code in this example in the tutorials that follow.

import java.sql.*;

public class UpdateCar {

    public static void UpdateCarNum(int carNo, int empNo)
                                              throws SQLException {
        Connection con = null;
        PreparedStatement pstmt = null;

        try {
          con = DriverManager.getConnection("jdbc:default:connection");

            pstmt = con.prepareStatement(
                        "UPDATE EMPLOYEES SET CAR_NUMBER = ? " +
                        "WHERE EMPLOYEE_NUMBER = ?");
            pstmt.setInt(1, carNo);
            pstmt.setInt(2, empNo);
            pstmt.executeUpdate();
        }
        finally {
            if (pstmt != null) pstmt.close();
        }
    }
}

Metadata

Databases store user data, and they also store information about the database itself. Most DBMSs have a set of system tables, which list tables in the database, column names in each table, primary keys, foreign keys, stored procedures, and so forth. Each DBMS has its own functions for getting information about table layouts and database features. JDBC provides the interface DatabaseMetaData, which a driver writer must implement so that its methods return information about the driver and/or DBMS for which the driver is written. For example, a large number of methods return whether or not the driver supports a particular functionality. This interface gives users and tools a standardized way to get metadata. In general, developers writing tools and drivers are the ones most likely to be concerned with metadata.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: JDBC Architecture
Next page: JDBC Basics


Lesson: JDBC Basics (The Java™ Tutorials > JDBC(TM) Database Access)

JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Trail: JDBC(TM) Database Access
Home Page > JDBC(TM) Database Access
« Previous • Trail • Next »
Lesson: JDBC Basics

In this lesson you will learn the basics of the JDBC™ API.

  • We start by giving you set up instructions in Getting Started. This lesson sets up a basic development environment, including Java™ SE 6 and NetBeans™.

  • Setting Up a Database installs a testing database accessable through the NetBeans IDE, and installs its database driver.

  • Establishing a Connection connects you to your database.

  • Setting up Tables, Retrieving Values from Result Sets and Updating Tables all develop the process of configuring your database, sending queries and retrieving data from your database.

The next lesson discusses how to use joins, row sets, transactions and stored procedures.

The final lesson describes how to create and run a complete JDBC application and provides some code examples for study.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Getting Started


Getting Started (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
Getting Started

This lesson helps you to set up a JDBC™ development environment. This includes the following steps:

  1. Install the latest version of the Java™ platform on your machine. If you don't already have a database, it is recommended that you download the latest version of the NetBeans™ IDE and the Sun Application Server, which comes with Java DB.

      2. To install the Java platform, follow the instructions after downloading Java platform software and NetBeans. These downloads provide you with the JDBC package. JDBC includes the java.sql and javax.sql packages, which has the necessary interfaces and classes you'll need for developing JDBC applications.

      You can find the latest release at the following URL:

http://java.sun.com/products/JDK/CurrentRelease
  2. Install a driver on your machine.

      3. You also need to install a driver on your machine. If you installed NetBeans with the Sun Application Server, then you have the driver that you need.

      Note: A JDBC driver can come from many sources: database software, such as Java DB, a JDBC driver vendor such as DataDirect, Oracle, MySQL, or an ISV/OEM such as Sun. Your driver should include instructions for installing it. For a JDBC driver written for specific Database Management Systems (DBMS), installation consists of copying the driver onto your machine. No special configuration is needed.

  3. Install your Database Management System (DBMS) if needed.

      4. If you do not already have a Database Management System (DBMS) installed, follow the vendor's instructions for installation. You can download the Java DB database, which comes bundled with the Sun Application Server:
      Free Trial Download, and the NetBeans IDE. as well.

      Types of Drivers

      There are many possible implementations of JDBC drivers. These implementations are categorized as follows:

      • Type 1 - drivers that implement the JDBC API as a mapping to another data access API, such as ODBC. Drivers of this type are generally dependent on a native library, which limits their portability. The JDBC-ODBC Bridge driver is an example of a Type 1 driver.

      • Type 2 - drivers that are written partly in the Java programming language and partly in native code. These drivers use a native client library specific to the data source to which they connect. Again, because of the native code, their portability is limited.

      • Type 3 - drivers that use a pure Java client and communicate with a middleware server using a database-independent protocol. The middleware server then communicates the client?s requests to the data source.

      • Type 4 - drivers that are pure Java and implement the network protocol for a specific data source. The client connects directly to the data source.

      Check which driver type comes with your DBMS on the JDBC Data Access API Drivers page. Java DB ships with two Type 4 drivers, an Embedded driver and a Network Client Driver.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: JDBC Basics
Next page: Setting Up a Database


Setting Up a Database (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
Setting Up a Database

Before you write a JDBC™ application, you need to set up a database called COFFEEBREAK. You learn how to create a database through your vendor documentation. Once you have set up the COFFEEBREAK database, continue with this lesson.

We strongly suggest that you use the Java DB database bundled with Netbeans, to work through this tutorial. Directions for setting up and connecting to the Java DB™ and using the NetBeans™ IDE can be found here.

Overview

Assume that our sample database is being used by the proprietor of a small coffee house called The Coffee Break, where coffee beans are sold by the pound and brewed coffee is sold by the cup. To keep things simple, also suppose that the proprietor needs only two tables, one for types of coffee and one for coffee suppliers.

To store data in the database, you create tables. Later, when you learn about creating the tables used as examples in this tutorial, the tables will be in the default database. We purposely kept the size and number of tables small to keep things manageable.

Once you have created the database and tables to store the data, you'll a open a connection with your DBMS. You also need to know some SQL code. After that, you'll discover how easy it is to use JDBC to pass SQL statements to your DBMS and then process the results that are returned.

Note: The code in this lesson has been tested on most of the major DBMS products. However, you may encounter some compatibility problems using it with older ODBC drivers with the JDBC-ODBC Bridge.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Getting Started
Next page: Establishing a Connection


Establishing a Connection (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
Establishing a Connection

First, you need to establish a connection with the DBMS you want to use. Typically, a JDBC™ application connects to a target data source using one of two mechanisms:

  • DriverManager: This fully implemented class requires an application to load a specific driver, using a hardcoded URL. As part of its initialization, the DriverManager class attempts to load the driver classes referenced in the jdbc.drivers system property. This allows you to customize the JDBC Drivers used by your applications.

  • DataSource: This interface is preferred over DriverManager because it allows details about the underlying data source to be transparent to your application. A DataSource object's properties are set so that it represents a particular data source.

Establishing a connection involves two steps: Loading the driver, and making the connection.

Loading the Driver

Loading the driver you want to use is very simple. It involves just one line of code in your program. To use the Java DB driver, add the following line of code:

Class.forName("org.apache.derby.jdbc.EmbeddedDriver");

Your driver documentation provides the class name to use. In the example above, EmbeddedDriver is one of the drivers for Java DB.

Calling the Class.forName automatically creates an instance of a driver and registers it with the DriverManager, so you don't need to create an instance of the class. If you were to create your own instance, you would be creating an unnecessary duplicate, but it would do no harm.

After you have loaded a driver, it can make a connection with a DBMS.

Making the Connection

The second step in establishing a connection is to have the appropriate driver connect to the DBMS.

Using the DriverManager Class

The DriverManager class works with the Driver interface to manage the set of drivers available to a JDBC client. When the client requests a connection and provides a URL, the DriverManager is responsible for finding a driver that recognizes the URL and for using it to connect to the corresponding data source. Connection URLs have the following form:

jdbc:derby:<dbName>[propertyList]

The dbName portion of the URL identifies a specific database. A database can be in one of many locations: in the current working directory, on the classpath, in a JAR file, in a specific Java DB database home directory, or in an absolute location on your file system.

If you are using a vendor-specific driver, such as Oracle, the documentation will tell you what subprotocol to use, that is, what to put after jdbc: in the JDBC URL. For example, if the driver developer has registered the name OracleDriver as the subprotocol, the first and second parts of the JDBC URL will be jdbc.driver.OracleDriver . The driver documentation will also give you guidelines for the rest of the JDBC URL. This last part of the JDBC URL supplies information for identifying the data source.

The getConnection method establishes a connection:

Connection conn = DriverManager.getConnection("jdbc:derby:COFFEES");

In place of " myLogin " you insert the name you use to log in to the DBMS; in place of " myPassword " you insert your password for the DBMS. So, if you log in to your DBMS with a login name of " Fernanda " and a password of " J8, " just these two lines of code will establish a connection:

String url = "jdbc:derby:Fred";
Connection con = DriverManager.getConnection(url, "Fernanda", "J8");

If one of the drivers you loaded recognizes the JDBC URL supplied to the method DriverManager.getConnection, that driver establishes a connection to the DBMS specified in the JDBC URL. The DriverManager class, true to its name, manages all of the details of establishing the connection for you behind the scenes. Unless you are writing a driver, you probably won't use any of the methods in the interface Driver, and the only DriverManager method you really need to know is DriverManager.getConnection

The connection returned by the method DriverManager.getConnection is an open connection you can use to create JDBC statements that pass your SQL statements to the DBMS. In the previous example, con is an open connection, and you use it in the examples that follow.

Using a DataSource Object for a connection

Using a DataSource object increases application portability by making it possible for an application to use a logical name for a data source instead of having to supply information specific to a particular driver. The following example shows how to use a DataSource to establish a connection:

You can configure a DataSource using a tool or manually. For example, Here is an example of a DataSource lookup:

 InitialContext ic = new InitialContext()

 DataSource ds = ic.lookup("java:comp/env/jdbc/myDB");
 Connection con = ds.getConnection();
 DataSource ds = (DataSource) org.apache.derby.jdbc.ClientDataSource()
 ds.setPort(1527);
 ds.setHost("localhost");
 ds.setUser("APP")
 ds.setPassword("APP");

Connection con = ds.getConnection();

DataSource implementations must provide getter and setter methods for each property they support. These properties typically are initialized when the DataSource object is deployed.

VendorDataSource vds = new VendorDataSource();
vds.setServerName("my_database_server");
String name = vds.getServerName();

JDBC-ODBC Bridge Driver

For normal use, you should obtain a commercial JDBC driver from a vendor such as your database vendor or your database middleware vendor. The JDBC-ODBC Bridge driver provided with JDBC is recommended only for development and testing, or when no other alternative is available.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Setting Up a Database
Next page: Setting Up Tables


Setting Up Tables (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
Setting Up Tables
For the following examples, you need to create a few tables in your database. The first table, COFFEES, contains the essential information about the coffees sold at The Coffee Break, including the coffee names, their prices, the number of pounds sold the current week, and the number of pounds sold to date. The table COFFEES, which is describe in more detail later, is shown here:

COF_NAME

SUP_ID

PRICE

SALES

TOTAL

Colombian

101

7.99

0

0

French_Roast

49

8.99

0

0

Espresso

150

9.99

0

0

Colombian_Decaf

101

8.99

0

0

French_Roast_Decaf

49

9.99

0

0

The Tables Used in the Example Database

The column storing the coffee name is COF_NAME, and it holds values with an SQL type of VARCHAR and a maximum length of 32 characters. Since the names are different for each type of coffee sold, the name uniquely identifies a particular coffee and serves as the primary key. The second column, named SUP_ID, holds a number identifying the coffee supplier; this number is of SQL type INTEGER. The third column, called PRICE, stores values with an SQL type of FLOAT because it needs to hold values with decimal points. (Note that money values would normally be stored in an SQL type DECIMAL or NUMERIC, but because of differences among DBMSs and to avoid incompatibility with older versions of JDBC, you are using the more standard type FLOAT for this tutorial.) The column named SALES stores values of SQL type INTEGER and indicates the number of pounds of coffee sold during the current week. The final column, TOTAL, contains an SQL INTEGER, which gives the total number of pounds of coffee sold to date.

SUPPLIERS, the second table in our database, gives information about each of the suppliers:

SUP_ID

SUP_NAME

STREET

CITY

STATE

ZIP

101

Acme, Inc.

99 Market Street

Groundsville

CA

95199

49

Superior Coffee

1 Party Place

Mendocino

CA

95460

150

The High Ground

100 Coffee Lane

Meadows

CA

93966

The tables COFFEES and SUPPLIERS both contain the column SUP_ID. These two tables can be used in SELECT statements to get data based on the information in both tables. The column SUP_ID is the primary key in the table SUPPLIERS, and as such, it uniquely identifies each of the coffee suppliers. In the table COFFEES, SUP_ID is called a foreign key. (You can think of a foreign key as being foreign in the sense that it is imported from another table.) Note that each SUP_ID number appears only once in the SUPPLIERS table; this is required for it to be a primary key. In the COFFEES table, where it is a foreign key, it is all right for there to be duplicate SUP_ID numbers because one supplier may sell many types of coffee. Later in this chapter, you see an example of how to use primary and foreign keys in a SELECT statement.

Creating Tables

You can create your tables in at least three ways:

  • Using the database or IDE graphical interface

  • Using ANT

  • Using JDBC SQL written into an application

Creating a Tables Using the NetBeans IDE

Most database vendors provide a graphical user interface (GUI) that makes creating tables in your database easy. In addition, many IDEs, such as the NetBeans IDE, also provides an easy-to-use GUI for table creation.

For example, in the NetBeans™ 5.0 IDE, creating tables in the Java DB™ database is easy. After starting the database, either through the pull-down menu, or by right-clicking Databases, you add tables simply by right-clicking the Tables icon and selecting BBBCreate Table. You get a dialog box that looks like the one below:

Table creator in NetBeans

Fill in the dialog box fields and the NetBeans IDE creates the table. Adding or deleting rows is just as easy. Right-click the table to want to edit.

Creating Tables Using ANT

First, you can use a properties file to feed ANT, which has a simple sql target. Create a simple properties file, such as the one below:

 # Database properties are in derby.properties
 db.delimiter=;
 db.root=${javaee.home}/derby
 db.driver=org.apache.derby.jdbc.ClientDriver
 db.datasource=org.apache.derby.jdbc.ClientDataSource
 db.host=localhost
 db.port=1527
 db.sid=sun-appserv-samples
 db.url=jdbc:derby://${db.host}:${db.port}/${db.sid};create=true;
 db.user=APP
 db.pwd=APP

Next, create a build.xml file that includes targets for compiling the Java code as well as a target similar to the following:

 <target name="create-db_common" depends="init,start-db,delete-db"
               description="Create database tables and populate database.">
 -
    <sql driver="${db.driver}" url="${db.url}" userid="${db.user}"
         password="${db.password}" classpathref="db.classpath"
                 delimiter="${db.delimiter}" autocommit="false" onerror="abort">
 <transaction src="
          {javaee.tutorial.home}/examples/common/sql/${db.vendor}/tutorial.sql"/>
 </sql>
 </target>

The tutorial.sql file can contain the commands to create the tables and, possibly, populate the tables if need be, such as the example below:

 create table COFFEES(cof_name varchar32, price int, sup_id int,
 price float, sales int, total int);

The ';' matches the db.delimiter property.

NetBeans contains everything you need, including the Java DB and ANT. Download NetBeans.

Using SQL in an Application

Finally, you can create tables from within the application code itself. The following SQL statement creates the table named COFFEES. The entries within the outer pair of parentheses consist of the name of a column followed by a space and the SQL type to be stored in that column. A comma separates the entry for one column (consisting of column name and SQL type) from the next one. To be sure you are using the correct syntax, see your DBMS documentation. For the Java DB, read the current documentation.

This code does not end with a DBMS statement terminator, which can vary from DBMS to DBMS. For example, Oracle uses a semicolon (;) to indicate the end of a statement, and Sybase uses the word go. The driver you are using will automatically supply the appropriate statement terminator, and you will not need to include it in your JDBC code.

Note: In the CREATE TABLE statement, key words are printed in all capital letters, and each item is on a separate line. SQL does not require either; these conventions simply make statements easier to read. The standard in SQL is that keywords are not case sensitive, so, for example, the following SELECT statement can be written various ways. As an example, these two versions below are equivalent as far as SQL is concerned:

SELECT SUP_NAME, CITY
FROM Suppliers
WHERE SUP_NAME LIKE "Acme, Inc"
select SUP_Name, CITY from Suppliers where
SUP_NAME like "Acme, Inc;

Quoted material, however, is case sensitive: in the name " Washington," W must be capitalized, and the rest of the letters must be lowercase.

Requirements can vary from one DBMS to another when it comes to identifier names.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Establishing a Connection
Next page: Retrieving Values from Result Sets


Retrieving Values from Result Sets (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
Retrieving Values from Result Sets

In the previous lesson, ResultSet was briefly mentioned. Now, you will learn the details of the ResultSet interface. The ResultSet interface provides methods for retrieving and manipulating the results of executed queries, and ResultSet objects can have different functionality and characteristics. These characteristics are result set type, result set concurrency, and cursor holdability. A table of data representing a database result set is usually generated by executing a statement that queries the database.

The type of a ResultSet object determines the level of its functionality in two areas: the ways in which the cursor can be manipulated, and how concurrent changes made to the underlying data source are reflected by the ResultSet object.

The sensitivity of the ResultSet object is determined by one of three different ResultSet types:

  1. TYPE_FORWARD_ONLY — The result set is not scrollable; its cursor moves forward only, from before the first row to after the last row. The rows contained in the result set depend on how the underlying database materializes the results. That is, it contains the rows that satisfy the query at either the time the query is executed or as the rows are retrieved.
  2. TYPE_SCROLL_INSENSITIVE — The result set is scrollable; its cursor can move both forward and backward relative to the current position, and it can move to an absolute position.
  3. TYPE_SCROLL_SENSITIVE — The result set is scrollable; its cursor can move both forward and backward relative to the current position, and it can move to an absolute position.

Now, you'll see how to send the above SELECT statements from a program written in the Java™ programming language and how you get the results we showed.

JDBC™ returns results in a ResultSet object, so we need to declare an instance of the class ResultSet to hold our results. In addition, the Statement methods executeQuery and getResultSet both return a ResultSet object, as do various DatabaseMetaData methods. The following code demonstrates declaring the ResultSet object rs and assigning the results of our earlier query to it by using the executeQuery method.

Before you can take advantage of these features, however, you need to create a scrollable ResultSet object. The following line of code illustrates one way to create a scrollable ResultSet object:

Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                                     ResultSet.CONCUR_READ_ONLY);
ResultSet srs = stmt.executeQuery("SELECT COF_NAME, PRICE FROM COFFEES");

This code is similar to what you have used earlier, except that it adds two arguments to the createStatement method. The first argument is one of three constants added to the ResultSet API to indicate the type of a ResultSet object: TYPE_FORWARD_ONLY, TYPE_SCROLL_INSENSITIVE, and TYPE_SCROLL_SENSITIVE. The second argument is one of two ResultSet constants for specifying whether a result set is read-only or updatable: CONCUR_READ_ONLY and CONCUR_UPDATABLE . The point to remember here is that if you specify a type, you must also specify whether it is read-only or updatable. Also, you must specify the type first, and because both parameters are of type int, the compiler will not complain if you switch the order.

Specifying the constant TYPE_FORWARD_ONLY creates a nonscrollable result set, that is, one in which the cursor moves only forward. If you do not specify any constants for the type and updatability of a ResultSet object, you will automatically get one that is TYPE_FORWARD_ONLY and CONCUR_READ_ONLY.

Using the ResultSet Methods

The variable srs, which is an instance of ResultSet, contains the rows of coffees and prices shown in the result set example above. In order to access the names and prices. A ResultSet object maintains a cursor, which points to its current row of data.

When a ResultSet object is first created, the cursor is positioned before the first row. To move the cursor, you can use the following methods:

  • next() - moves the cursor forward one row. Returns true if the cursor is now positioned on a row and false if the cursor is positioned after the last row.
  • previous() - moves the cursor backwards one row. Returns true if the cursor is now positioned on a row and false if the cursor is positioned before the first row.
  • first() - moves the cursor to the first row in the ResultSet object. Returns true if the cursor is now positioned on the first row and false if the ResultSet object does not contain any rows.
  • last() - moves the cursor to the last row in the ResultSet object. Returns true if the cursor is now positioned on the last row and false if the ResultSet object does not contain any rows.
  • beforeFirst() - positions the cursor at the start of the ResultSet object, before the first row. If the ResultSet object does not contain any rows, this method has no effect.
  • afterLast() - positions the cursor at the end of the ResultSet object, after the last row. If the ResultSet object does not contain any rows, this method has no effect.
  • relative(int rows) - moves the cursor relative to its current position.
  • absolute(int row) - positions the cursor on the row-th row of the ResultSet object.

Once you have a scrollable ResultSet object, srs in the previous example, you can use it to move the cursor around in the result set. Since the cursor is initially positioned just above the first row of a ResultSet object, the first call to the method next moves the cursor to the first row and makes it the current row. Successive invocations of the method next move the cursor down one row at a time from top to bottom.

Using the getXXX Methods

The ResultSet interface declares getter methods (getBoolean, getLong, and so on) for retrieving column values from the current row. Your application can retrieve values using either the index number of the column or the name of the column. The column index is usually more efficient. Columns are numbered from 1. For maximum portability, result set columns within each row should be read in left-to-right order, and each column should be read only once.

Column names used as input to getter methods are case insensitive. When a getter method is called with a column name and several columns have the same name, the value of the first matching column will be returned. The column name option is designed to be used when column names are used in the SQL query that generated the result set. For columns that are NOT explicitly named in the query, it is best to use column numbers. If column names are used, the programmer should take care to guarantee that they uniquely refer to the intended columns, which can be assured with the SQL AS clause.

The getXXX method of the appropriate type retrieves the value in each column. For example, the first column in each row of srs is COF_NAME, which stores a value of SQL type VARCHAR. The method for retrieving a value of SQL type VARCHAR is getString. The second column in each row stores a value of SQL type FLOAT, and the method for retrieving values of that type is getFloat. The following code accesses the values stored in the current row of srs and prints a line with the name followed by three spaces and the price. Each time the method next is invoked, the next row becomes the current row, and the loop continues until there are no more rows in rs.

The method getString is invoked on the ResultSet object srs, so getString retrieves (gets) the value stored in the column COF_NAME in the current row of srs . The value that getString retrieves has been converted from an SQL VARCHAR to a String in the Java programming language, and it is assigned to the String object s.

Note that although the method getString is recommended for retrieving the SQL types CHAR and VARCHAR, it is possible to retrieve any of the basic SQL types with it. (You cannot, however, retrieve the new SQL3 datatypes with it. We will discuss SQL3 types later in this tutorial.) Getting all values with getString can be very useful, but it also has its limitations. For instance, if it is used to retrieve a numeric type, getString converts the numeric value to a Java String object, and the value has to be converted back to a numeric type before it can be operated on as a number. In cases where the value is treated as a string anyway, there is no drawback. Further, if you want an application to retrieve values of any standard SQL type other than SQL3 types, use the getString method.

Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                                     ResultSet.CONCUR_READ_ONLY);
ResultSet srs = stmt.executeQuery(
    "SELECT COF_NAME, PRICE FROM COFFEES");
while (srs.next()) {
        String name = srs.getString("COF_NAME");
        float price = srs.getFloat("PRICE");
        System.out.println(name + "     " + price);
}

The output will look something like this:

Colombian     7.99
French_Roast     8.99
Espresso     9.99
Colombian_Decaf     8.99
French_Roast_Decaf     9.99

You can process all of the rows is srs going backward, but to do this, the cursor must start out located after the last row. You can move the cursor explicitly to the position after the last row with the method afterLast. Then the method previous() moves the cursor from the position after the last row to the last row, and then to the previous row with each iteration through the while loop. The loop ends when the cursor reaches the position before the first row, where the method previous() returns false .

Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
                                         ResultSet.CONCUR_READ_ONLY);
ResultSet srs = stmt.executeQuery("SELECT COF_NAME, PRICE FROM COFFEES");
    srs.afterLast();
    while (srs.previous()) {
        String name = srs.getString("COF_NAME");
        float price = srs.getFloat("PRICE");
        System.out.println(name + "     " + price);
    }

The printout will look similar to this:

French_Roast_Decaf     9.99
Colombian_Decaf     8.99
Espresso     9.99
French_Roast     8.99
Colombian     7.99

As you can see, the printout for each has the same values, but the rows are in the opposite order.

The situation is similar with the method getFloat except that it retrieves the value stored in the column PRICE, which is an SQL FLOAT, and converts it to a Java float before assigning it to the variable n.

JDBC offers two ways to identify the column from which a getXXX method gets a value. One way is to give the column name, as was done in the example above. The second way is to give the column index (number of the column), with 1 signifying the first column, 2 , the second, and so on. Using the column number instead of the column name looks like this:

String s = srs.getString(1);
float n = srs.getFloat(2);

The first line of code gets the value in the first column of the current row of rs (column COF_NAME), converts it to a Java String object, and assigns it to s. The second line of code gets the value stored in the second column of the current row of rs , converts it to a Java float, and assigns it to n. Note that the column number refers to the column number in the result set, not in the original table.

You can move the cursor to a particular row in a ResultSet object. The methods first, last, beforeFirst, and afterLast move the cursor to the row indicated in their names. The method absolute will move the cursor to the row number indicated in the argument passed to it. If the number is positive, the cursor moves the given number from the beginning, so calling absolute(1) puts the cursor on the first row. If the number is negative, the cursor moves the given number from the end, so calling absolute(-1) puts the cursor on the last row. The following line of code moves the cursor to the fourth row of srs:

srs.absolute(4);

If srs has 500 rows, the following line of code moves the cursor to row 497:

srs.absolute(-4);

Three methods move the cursor to a position relative to its current position. As you have seen, the method next moves the cursor forward one row, and the method previous moves the cursor backward one row. With the method relative, you can specify how many rows to move from the current row and also the direction in which to move. A positive number moves the cursor forward the given number of rows; a negative number moves the cursor backward the given number of rows. For example, in the following code fragment, the cursor moves to the fourth row, then to the first row, and finally to the third row:

srs.absolute(4); // cursor is on the fourth row
. . .
srs.relative(-3); // cursor is on the first row
. . .
srs.relative(2); // cursor is on the third row

The method getRow lets you check the number of the row where the cursor is positioned. For example, you can use getRow to verify the current position of the cursor in the previous example as follows:

srs.absolute(4);
int rowNum = srs.getRow(); // rowNum should be 4
srs.relative(-3);
int rowNum = srs.getRow(); // rowNum should be 1
srs.relative(2);
int rowNum = srs.getRow(); // rowNum should be 3

Four additional methods let you verify whether the cursor is at a particular position. The position is stated in their names: isFirst, isLast, isBeforeFirst, isAfterLast. These methods all return a boolean and can therefore be used in a conditional statement. For example, the following code fragment tests to see whether the cursor is after the last row before invoking the method previous in a while loop. If the method isAfterLast returns false, the cursor is not after the last row, so the method afterLast is invoked. This guarantees that the cursor will be after the last row and that using the method previous in the while loop will cover every row in srs.

if (srs.isAfterLast() == false) {
        srs.afterLast();
}
while (srs.previous()) {
        String name = srs.getString("COF_NAME");
        float price = srs.getFloat("PRICE");
        System.out.println(name + "     " + price);
}

In summary, JDBC allows you to use either the column name or the column number as the argument to a getXXX method. Using the column number is slightly more efficient, and there are some cases where the column number is required. In general, though, supplying the column name is essentially equivalent to supplying the column number.

JDBC allows a lot of latitude as far as which getXXX methods you can use to retrieve the different SQL types. For example, the method getInt can be used to retrieve any of the numeric or character types. The data it retrieves will be converted to an int; that is, if the SQL type is VARCHAR , JDBC will attempt to parse an integer out of the VARCHAR. The method getInt is recommended for retrieving only SQL INTEGER types, however, and it cannot be used for the SQL types BINARY, VARBINARY, LONGVARBINARY, DATE , TIME, or TIMESTAMP.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Setting Up Tables
Next page: Updating Tables


Updating Tables (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
Updating Tables

Next, you learn to update rows in a result set, using methods in the Java programming language rather than having to send an SQL command.

Updating a row in a ResultSet object is a two-phase process. First, the new value for each column being updated is set, and then the change is applied to the row. The row in the underlying data source is not updated until the second phase is completed.

The ResultSet interface contains two update methods for each JDBC™ type, one specifying the column to be updated as an index and one specifying the column name as it appears in the select list. Column names supplied to updater methods are case insensitive. If a select list contains the same column more than once, the first instance of the column will be updated.

First, you need to create a ResultSet object that is updatable. To do this, supply the ResultSet constant CONCUR_UPDATABLE to the createStatement method, as you have seen in previous examples. The Statement object it creates produces an updatable ResultSet object each time it executes a query. The following code fragment illustrates creating the updatable ResultSet object uprs. Note that the code also makes uprs scrollable. An updatable ResultSet object does not necessarily have to be scrollable, but when you are making changes to a result set, you generally want to be able to move around in it. With a scrollable result set, you can move to rows you want to change, and if the type is TYPE_SCROLL_SENSITIVE, you can get the new value in a row after you have changed it.

Connection con = DriverManager.getConnection("jdbc:mySubprotocol:mySubName");
Statement stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
                                     ResultSet.CONCUR_UPDATABLE);
ResultSet uprs = stmt.executeQuery("SELECT COF_NAME, PRICE FROM COFFEES");

The ResultSet object uprs looks something like this:

COF_NAME                PRICE
------------------      -----
Colombian               7.99
French_Roast            8.99
Espresso                9.99
Colombian_Decaf         8.99
French_Roast_Decaf      9.99

The method updateRow applies all column changes to the current row. The changes are not made to the row until updateRow has been called. You can use the cancelUpdates method to back out changes made to the row before the updateRow method is called.

Statement stmt = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_UPDATABLE);
ResultSet srs = stmt.executeQuery("select COF_Name from COFFEES " +
"where price = 7.99");
srs.next();
srs.updateString("COF_NAME", "Foldgers");
srs.updateRow();

An update is the modification of a column value in the current row. Let's suppose that you want to raise the price of French Roast Decaf coffee to 10.99:

uprs.last();
uprs.updateFloat("PRICE", 10.99);

Update operations affect column values in the row where the cursor is positioned, so in the first line the ResultSet uprs calls the method last to move its cursor to the last row (the row where the column COF_NAME has the value FRENCH_ROAST_DECAF). Once the cursor is on the last row, all of the update methods you call will operate on that row until you move the cursor to another row. The second line changes the value in the PRICE column to 10.99 by calling the method updateFloat. This method is used because the column value we want to update is a float in the Java programming language.

The ResultSet. updateXXX methods take two parameters: the column to update and the new value to put in that column. As with the ResultSet.getXXX methods, the parameter designating the column may be either the column name or the column number. There is a different updateXXX method for updating each datatype ( updateString, updateBigDecimal, updateInt, and so on) just as there are different getXXX methods for retrieving different datatypes.

At this point, the price in uprs for French Roast Decaf will be 10.99, but the price in the table COFFEES in the database will still be 9.99. To make the update take effect in the database and not just the result set, we must call the ResultSet method updateRow. Here is what the code should look like to update both uprs and COFFEES :

uprs.last();
uprs.updateFloat("PRICE", 10.99f);
uprs.updateRow();

If you had moved the cursor to a different row before calling the method updateRow, the update would have been lost. If, on the other hand, you realized that the price should really have been 10.79 instead of 10.99, you could have cancelled the update to 10.99 by calling the method cancelRowUpdates. You have to invoke cancelRowUpdates before invoking the method updateRow; once updateRow is called, calling the method cancelRowUpdates does nothing. Note that cancelRowUpdates cancels all of the updates in a row, so if there are many invocations of the updateXXX methods on the same row, you cannot cancel just one of them. The following code fragment first cancels updating the price to 10.99 and then updates it to 10.79:

uprs.last();
uprs.updateFloat("PRICE", 10.99);
uprs.cancelRowUpdates();
uprs.updateFloat("PRICE", 10.79);
uprs.updateRow();

In this example, only one column value was updated, but you can call an appropriate updateXXX method for any or all of the column values in a single row. The concept to remember is that updates and related operations apply to the row where the cursor is positioned. Even if there are many calls to updateXXX methods, it takes only one call to the method updateRow to update the database with all of the changes made in the current row.

If you want to update the price for COLOMBIAN_DECAF as well, you have to move the cursor to the row containing that coffee. Because the row for COLOMBIAN_DECAF immediately precedes the row for FRENCH_ROAST_DECAF, you can call the method previous to position the cursor on the row for COLOMBIAN_DECAF. The following code fragment changes the price in that row to 9.79 in both the result set and the underlying table in the database:

uprs.previous();
uprs.updateFloat("PRICE", 9.79);
uprs.updateRow();

All cursor movements refer to rows in a ResultSet object, not rows in the underlying database. If a query selects five rows from a database table, there will be five rows in the result set, with the first row being row 1, the second row being row 2, and so on. Row 1 can also be identified as the first, and, in a result set with five rows, row 5 is the last.

The ordering of the rows in the result set has nothing at all to do with the order of the rows in the base table. In fact, the order of the rows in a database table is indeterminate. The DBMS keeps track of which rows were selected, and it makes updates to the proper rows, but they may be located anywhere in the table. When a row is inserted, for example, there is no way to know where in the table it has been inserted.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Retrieving Values from Result Sets
Next page: Milestone: The Basics of JDBC


Milestone: The Basics of JDBC (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
Milestone: The Basics of JDBC

You have just reached a milestone.

You have learned the basics of the JDBC™ API. You learned how to create a table, insert values into it, query the table, retrieve results, and update the table. These are the nuts and bolts of using a database, and you can now use them in a program written in the Java™ programming language using the JDBC 3.0 API. We have used only very simple queries in our examples so far, but as long as the driver and DBMS support them, you can send very complicated SQL queries using only the basic JDBC API we have covered so far.

The rest of this lessons looks at how to use features that are a little more advanced: stored procedures, and transactions. It also illustrates warnings and exceptions. The final part of this lesson is sample code that you can run yourself.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Updating Tables
Next page: Using Prepared Statements


Using Prepared Statements (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
Using Prepared Statements

Sometimes it is more convenient to use a PreparedStatement object for sending SQL statements to the database. This special type of statement is derived from the more general class, Statement, that you already know.

If you want to execute a Statement object many times, it normally reduces execution time to use a PreparedStatement object instead.

The main feature of a PreparedStatement object is that, unlike a Statement object, it is given an SQL statement when it is created. The advantage to this is that in most cases, this SQL statement is sent to the DBMS right away, where it is compiled. As a result, the PreparedStatement object contains not just an SQL statement, but an SQL statement that has been precompiled. This means that when the PreparedStatement is executed, the DBMS can just run the PreparedStatement SQL statement without having to compile it first.

Although PreparedStatement objects can be used for SQL statements with no parameters, you probably use them most often for SQL statements that take parameters. The advantage of using SQL statements that take parameters is that you can use the same statement and supply it with different values each time you execute it. Examples of this are in the following sections.

Creating a PreparedStatement Object

As with Statement objects, you create PreparedStatement objects with a Connection method. Using our open connection con from previous examples, you might write code such as the following to create a PreparedStatement object that takes two input parameters:

PreparedStatement updateSales = con.prepareStatement(
    "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?");

The variable updateSales now contains the SQL statement, "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?", which has also, in most cases, been sent to the DBMS and been precompiled.

Supplying Values for PreparedStatement Parameters

You need to supply values to be used in place of the question mark placeholders (if there are any) before you can execute a PreparedStatement object. You do this by calling one of the setXXX methods defined in the PreparedStatement class. If the value you want to substitute for a question mark is a Java int, you call the method setInt. If the value you want to substitute for a question mark is a Java String, you call the method setString, and so on. In general, there is a setXXX method for each primitive type declared in the Java programming language.

setXXX Using the PreparedStatement object updateSales from the previous example, the following line of code sets the first question mark placeholder to a Java int with a value of 75:

updateSales.setInt(1, 75);

setXXX The first argument given to a setXXX method indicates which question mark placeholder is to be set, and the second argument indicates the value to which it is to be set. The next example sets the second placeholder parameter to the string " Colombian":

updateSales.setString(2, "Colombian");

setXXX After these values have been set for its two input parameters, the SQL statement in updateSales is the equivalent to the SQL statement in the String object updateString that was used in the previous update example. Therefore, the following two code fragments accomplish the same thing:

Code Fragment 1:

String updateString = "UPDATE COFFEES SET SALES = 75 " +
                      "WHERE COF_NAME LIKE 'Colombian'";
stmt.executeUpdate(updateString);

Code Fragment 2:

PreparedStatement updateSales = con.prepareStatement(
        "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ? ");
updateSales.setInt(1, 75);
updateSales.setString(2, "Colombian");
updateSales.executeUpdate():

The method executeUpdate was used to execute both the Statement stmt and the PreparedStatement updateSales. Notice, however, that no argument is supplied to executeUpdate when it is used to execute updateSales. This is true because updateSales already contains the SQL statement to be executed.

Looking at these examples, you might wonder why you would choose to use a PreparedStatement object with parameters instead of just a simple statement, since the simple statement involves fewer steps. If you were going to update the SALES column only once or twice, then there would be no need to use an SQL statement with input parameters. If you will be updating often, on the other hand, it might be much easier to use a PreparedStatement object, especially in situations where you can use a for loop or while loop to set a parameter to a succession of values. You will see an example of this later in this section.

Once a parameter has been set with a value, it retains that value until it is reset to another value, or the method clearParameters is called. Using the PreparedStatement object updateSales, the following code fragment illustrates reusing a prepared statement after resetting the value of one of its parameters and leaving the other one the same:

updateSales.setInt(1, 100);
updateSales.setString(2, "French_Roast");
updateSales.executeUpdate();
// changes SALES column of French Roast row to 100
updateSales.setString(2, "Espresso");
updateSales.executeUpdate();
// changes SALES column of Espresso row to 100 (the first
// parameter stayed 100, and the second parameter was reset
// to "Espresso")

Using a Loop to Set Values

You can often make coding easier by using a for loop or a while loop to set values for input parameters.

The code fragment that follows demonstrates using a for loop to set values for parameters in the PreparedStatement object updateSales. The array salesForWeek holds the weekly sales amounts. These sales amounts correspond to the coffee names listed in the array coffees, so that the first amount in salesForWeek (175) applies to the first coffee name in coffees ("Colombian"), the second amount in salesForWeek (150) applies to the second coffee name in coffees ("French_Roast "), and so on. This code fragment demonstrates updating the SALES column for all the coffees in the table COFFEES:

PreparedStatement updateSales;
String updateString = "update COFFEES " +
                      "set SALES = ? where COF_NAME like ?";
updateSales = con.prepareStatement(updateString);
int [] salesForWeek = {175, 150, 60, 155, 90};
String [] coffees = {"Colombian", "French_Roast", "Espresso",
                     "Colombian_Decaf", "French_Roast_Decaf"};
int len = coffees.length;
for(int i = 0; i < len; i++) {
                updateSales.setInt(1, salesForWeek[i]);
                updateSales.setString(2, coffees[i]);
                updateSales.executeUpdate();
        }

When the proprietor wants to update the sales amounts for the next week, he can use this same code as a template. All he has to do is enter the new sales amounts in the proper order in the array salesForWeek. The coffee names in the array coffees remain constant, so they do not need to be changed. (In a real application, the values would probably be input from the user rather than from an initialized Java array.)

Return Values for the executeUpdate Method

Whereas executeQuery returns a ResultSet object containing the results of the query sent to the DBMS, the return value for executeUpdate is an int that indicates how many rows of a table were updated. For instance, the following code shows the return value of executeUpdate being assigned to the variable n:

updateSales.setInt(1, 50);
updateSales.setString(2, "Espresso");
int n = updateSales.executeUpdate();
// n = 1 because one row had a change in it

The table COFFEES was updated by having the value 50 replace the value in the column SALES in the row for Espresso. That update affected one row in the table, so n is equal to 1.

When the method executeUpdate is used to execute a DDL statement, such as in creating a table, it returns the int 0. Consequently, in the following code fragment, which executes the DDL statement used to create the table COFFEES, n is assigned a value of 0:

int n = executeUpdate(createTableCoffees); // n = 0

Note that when the return value for executeUpdate is 0, it can mean one of two things:

  • the statement executed was an update statement that affected zero rows
  • the statement executed was a DDL statement.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Milestone: The Basics of JDBC
Next page: Using Joins


Using Joins (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
Using Joins
Sometimes you need to use two or more tables to get the data you want. For example, suppose the proprietor of The Coffee Break wants a list of the coffees he buys from Acme, Inc. This involves information in the COFFEES table as well as the yet-to-be-created SUPPLIERS table. This is a case where a join is needed. A join is a database operation that relates two or more tables by means of values that they share in common. In our example database, the tables COFFEES and SUPPLIERS both have the column SUP_ID, which can be used to join them.

Before we go any further, we need to create the table SUPPLIERS and populate it with values.

The code below creates the table SUPPLIERS:

String createSUPPLIERS = "create table SUPPLIERS " +
             "(SUP_ID INTEGER, SUP_NAME VARCHAR(40), " +
             "STREET VARCHAR(40), CITY VARCHAR(20), " +
             "STATE CHAR(2), ZIP CHAR(5))";
stmt.executeUpdate(createSUPPLIERS);

The following code inserts rows for three suppliers into SUPPLIERS:

stmt.executeUpdate("insert into SUPPLIERS values (101, " +
    "'Acme, Inc.', '99 Market Street', 'Groundsville', " + "'CA', '95199'");
stmt.executeUpdate("Insert into SUPPLIERS values (49," +
    "'Superior Coffee', '1 Party Place', 'Mendocino', 'CA', " + "'95460'");
stmt.executeUpdate("Insert into SUPPLIERS values (150, " +
    "'The High Ground', '100 Coffee Lane', 'Meadows', 'CA', " + "'93966'");

The following code selects the whole table and lets us see what the table SUPPLIERS looks like:

ResultSet rs = stmt.executeQuery("select * from SUPPLIERS");

The result set will look similar to this:

SUP_ID SUP_NAME

STREET

CITY

STATE

ZIP
------

-------------

-------------

-----------

-----

-----
101

Acme, Inc.

99 Market Street

Groundsville

CA

95199
49

Superior Coffee

1 Party Place

Mendocino

CA

95460
150

The High Ground

100 Coffee Lane

Meadows

CA

93966

Now that we have the tables COFFEES and SUPPLIERS, we can proceed with the scenario where the owner wants to get a list of the coffees he buys from a particular supplier. The names of the suppliers are in the table SUPPLIERS, and the names of the coffees are in the table COFFEES. Since both tables have the column SUP_ID, this column can be used in a join. It follows that you need some way to distinguish which SUP_ID column you are referring to. This is done by preceding the column name with the table name, as in "COFFEES.SUP_ID" to indicate that you mean the column SUP_ID in the table COFFEES. The following code, in which stmt is a Statement object, selects the coffees bought from Acme, Inc.:

String query = "
SELECT COFFEES.COF_NAME " +
   "FROM COFFEES, SUPPLIERS " +
   "WHERE SUPPLIERS.SUP_NAME LIKE 'Acme, Inc.' " +
   "and SUPPLIERS.SUP_ID = COFFEES.SUP_ID";

ResultSet rs = stmt.executeQuery(query);
System.out.println("Coffees bought from Acme, Inc.: ");
while (rs.next()) {
    String coffeeName = rs.getString("COF_NAME");
    System.out.println("     " + coffeeName);
}

This will produce the following output:

Coffees bought from Acme, Inc.:
     Colombian
     Colombian_Decaf
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Prepared Statements
Next page: Using Transactions


Using Transactions (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
Using Transactions

There are times when you do not want one statement to take effect unless another one completes. For example, when the proprietor of The Coffee Break updates the amount of coffee sold each week, he will also want to update the total amount sold to date. However, he will not want to update one without updating the other; otherwise, the data will be inconsistent. The way to be sure that either both actions occur or neither action occurs is to use a transaction. A transaction is a set of one or more statements that are executed together as a unit, so either all of the statements are executed, or none of the statements is executed.

Disabling Auto-commit Mode

When a connection is created, it is in auto-commit mode. This means that each individual SQL statement is treated as a transaction and is automatically committed right after it is executed. (To be more precise, the default is for an SQL statement to be committed when it is completed, not when it is executed. A statement is completed when all of its result sets and update counts have been retrieved. In almost all cases, however, a statement is completed, and therefore committed, right after it is executed.)

The way to allow two or more statements to be grouped into a transaction is to disable auto-commit mode. This is demonstrated in the following line of code, where con is an active connection:

con.setAutoCommit(false);

Committing a Transaction

Once auto-commit mode is disabled, no SQL statements are committed until you call the method commit explicitly. All statements executed after the previous call to the method commit are included in the current transaction and committed together as a unit. The following code, in which con is an active connection, illustrates a transaction:

con.setAutoCommit(false);
PreparedStatement updateSales = con.prepareStatement(
    "UPDATE COFFEES SET SALES = ? WHERE COF_NAME LIKE ?");
updateSales.setInt(1, 50);
updateSales.setString(2, "Colombian");
updateSales.executeUpdate();
PreparedStatement updateTotal = con.prepareStatement(
    "UPDATE COFFEES SET TOTAL = TOTAL + ? WHERE COF_NAME LIKE ?");
updateTotal.setInt(1, 50);
updateTotal.setString(2, "Colombian");
updateTotal.executeUpdate();
con.commit();
con.setAutoCommit(true);

In this example, auto-commit mode is disabled for the connection con, which means that the two prepared statements updateSales and updateTotal are committed together when the method commit is called. Whenever the commit method is called (either automatically when auto-commit mode is enabled or explicitly when it is disabled), all changes resulting from statements in the transaction are made permanent. In this case, that means that the SALES and TOTAL columns for Colombian coffee have been changed to 50 (if TOTAL had been 0 previously) and will retain this value until they are changed with another update statement. TransactionPairs.java illustrates a similar kind of transaction but uses a for loop to supply values to the setXXX methods for updateSales and updateTotal.

The final line of the previous example enables auto-commit mode, which means that each statement is once again committed automatically when it is completed. Then, you are back to the default state where you do not have to call the method commit yourself. It is advisable to disable auto-commit mode only while you want to be in transaction mode. This way, you avoid holding database locks for multiple statements, which increases the likelihood of conflicts with other users.

Using Transactions to Preserve Data Integrity

In addition to grouping statements together for execution as a unit, transactions can help to preserve the integrity of the data in a table. For instance, suppose that an employee was supposed to enter new coffee prices in the table COFFEES but delayed doing it for a few days. In the meantime, prices rose, and today the owner is in the process of entering the higher prices. The employee finally gets around to entering the now outdated prices at the same time that the owner is trying to update the table. After inserting the outdated prices, the employee realizes that they are no longer valid and calls the Connection method rollback to undo their effects. (The method rollback aborts a transaction and restores values to what they were before the attempted update.) At the same time, the owner is executing a SELECT statement and printing out the new prices. In this situation, it is possible that the owner will print a price that was later rolled back to its previous value, making the printed price incorrect.

This kind of situation can be avoided by using transactions, providing some level of protection against conflicts that arise when two users access data at the same time.

To avoid conflicts during a transaction, a DBMS uses locks, mechanisms for blocking access by others to the data that is being accessed by the transaction. (Note that in auto-commit mode, where each statement is a transaction, locks are held for only one statement.) Once a lock is set, it remains in force until the transaction is committed or rolled back. For example, a DBMS could lock a row of a table until updates to it have been committed. The effect of this lock would be to prevent a user from getting a dirty read, that is, reading a value before it is made permanent. (Accessing an updated value that has not been committed is considered a dirty read because it is possible for that value to be rolled back to its previous value. If you read a value that is later rolled back, you will have read an invalid value.)

How locks are set is determined by what is called a transaction isolation level, which can range from not supporting transactions at all to supporting transactions that enforce very strict access rules.

One example of a transaction isolation level is TRANSACTION_READ_COMMITTED, which will not allow a value to be accessed until after it has been committed. In other words, if the transaction isolation level is set to TRANSACTION_READ_COMMITTED, the DBMS does not allow dirty reads to occur. The interface Connection includes five values which represent the transaction isolation levels you can use in JDBC.

Normally, you do not need to do anything about the transaction isolation level; you can just use the default one for your DBMS. JDBC allows you to find out what transaction isolation level your DBMS is set to (using the Connection method getTransactionIsolation) and also allows you to set it to another level (using the Connection method setTransactionIsolation). Keep in mind, however, that even though JDBC allows you to set a transaction isolation level, doing so has no effect unless the driver and DBMS you are using support it.

Setting and Rolling Back to a Savepoint

The JDBC 3.0 API adds the method Connection.setSavepoint, which sets a savepoint within the current transaction. The Connection.rollback method has been overloaded to take a savepoint argument.

The example below inserts a row into a table, sets the savepoint svpt1, and then inserts a second row. When the transaction is later rolled back to svpt1, the second insertion is undone, but the first insertion remains intact. In other words, when the transaction is committed, only the row containing ?FIRST? will be added to TAB1:

Statement stmt = conn.createStatement();
int rows = stmt.executeUpdate("INSERT INTO TAB1 (COL1) VALUES " +
                                                    "(?FIRST?)");
// set savepoint
Savepoint svpt1 = conn.setSavepoint("SAVEPOINT_1");
rows = stmt.executeUpdate("INSERT INTO TAB1 (COL1) " +
                                           "VALUES (?SECOND?)");
...
conn.rollback(svpt1);
...
conn.commit();

Releasing a Savepoint

The method Connection.releaseSavepoint takes a Savepoint object as a parameter and removes it from the current transaction.

Once a savepoint has been released, attempting to reference it in a rollback operation causes an SQLException to be thrown. Any savepoints that have been created in a transaction are automatically released and become invalid when the transaction is committed, or when the entire transaction is rolled back. Rolling a transaction back to a savepoint automatically releases and makes invalid any other savepoints that were created after the savepoint in question.

When to Call the Method rollback

As mentioned earlier, calling the method rollback aborts a transaction and returns any values that were modified to their previous values. If you are trying to execute one or more statements in a transaction and get an SQLException, you should call the method rollback to abort the transaction and start the transaction all over again. That is the only way to be sure of what has been committed and what has not been committed. Catching an SQLException tells you that something is wrong, but it does not tell you what was or was not committed. Since you cannot count on the fact that nothing was committed, calling the method rollback is the only way to be sure.

TransactionPairs.java demonstrates a transaction and includes a catch block that invokes the method rollback. In this particular situation, it is not really necessary to call rollback, and we do it mainly to illustrate how it is done. If the application continued and used the results of the transaction, however, it would be necessary to include a call to rollback in the catch block in order to protect against using possibly incorrect data.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Joins
Next page: Stored Procedures


Stored Procedures (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
Stored Procedures
A stored procedure is a group of SQL statements that form a logical unit and perform a particular task. Stored procedures are used to encapsulate a set of operations or queries to execute on a database server. For example, operations on an employee database (hire, fire, promote, lookup) could be coded as stored procedures executed by application code. Stored procedures can be compiled and executed with different parameters and results, and they may have any combination of input, output, and input/output parameters.

Stored procedures are supported by most DBMSs, but there is a fair amount of variation in their syntax and capabilities. For this reason, we will show you a simple example of what a stored procedure looks like and how it is invoked from JDBC, but this sample is not intended to be run.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Using Transactions
Next page: SQL Statements for Creating a Stored Procedure


SQL Statements for Creating a Stored Procedure (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
SQL Statements for Creating a Stored Procedure

A stored procedure is a group of SQL statements that form a logical unit and perform a particular task, and they are used to encapsulate a set of operations or queries to execute on a database server. For example, operations on an employee database (hire, fire, promote, lookup) could be coded as stored procedures executed by application code. Stored procedures can be compiled and executed with different parameters and results, and they may have any combination of input, output, and input/output parameters.

Note: Stored procedures are supported by most DBMSs, but there is a fair amount of variation in their syntax and capabilities. For this reason, this simple example of what a stored procedure looks like and how it is invoked from JDBC is not intended to be run.

This simple stored procedure has no parameters. Even though most stored procedures do something more complex than this example, it serves to illustrate some basic points about them. As previously stated, the syntax for defining a stored procedure is different for each DBMS. For example, some use   begin . . . end , or other keywords to indicate the beginning and ending of the procedure definition. In some DBMSs, the following SQL statement creates a stored procedure:

create procedure SHOW_SUPPLIERS
as
select SUPPLIERS.SUP_NAME, COFFEES.COF_NAME
from SUPPLIERS, COFFEES
where SUPPLIERS.SUP_ID = COFFEES.SUP_ID
order by SUP_NAME

The following code puts the SQL statement into a string and assigns it to the variable createProcedure, which we will use later:

String createProcedure = "create procedure SHOW_SUPPLIERS " +
             "as " +
             "select SUPPLIERS.SUP_NAME, COFFEES.COF_NAME " +
             "from SUPPLIERS, COFFEES " +
             "where SUPPLIERS.SUP_ID = COFFEES.SUP_ID " +
             "order by SUP_NAME";

The following code fragment uses the Connection object con to create a Statement object, which is used to send the SQL statement creating the stored procedure to the database:

Statement stmt = con.createStatement();
stmt.executeUpdate(createProcedure);

The procedure SHOW_SUPPLIERS is compiled and stored in the database as a database object that can be called, similar to the way you would call a method.

Calling a Stored Procedure from JDBC

JDBC allows you to call a database stored procedure from an application written in the Java programming language. The first step is to create a CallableStatement object. As with Statement and PreparedStatement objects, this is done with an open Connection object. A callableStatement object contains a call to a stored procedure; it does not contain the stored procedure itself. The first line of code below creates a call to the stored procedure SHOW_SUPPLIERS using the connection con. The part that is enclosed in curly braces is the escape syntax for stored procedures. When the driver encounters "{call SHOW_SUPPLIERS}", it will translate this escape syntax into the native SQL used by the database to call the stored procedure named SHOW_SUPPLIERS.

CallableStatement cs = con.prepareCall("{call SHOW_SUPPLIERS}");
ResultSet rs = cs.executeQuery();

The ResultSet rs will be similar to the following:

SUP_NAME			COF_NAME
----------------		-----------------------
Acme, Inc.			Colombian
Acme, Inc.			Colombian_Decaf
Superior Coffee			French_Roast
Superior Coffee			French_Roast_Decaf
The High Ground			Espresso

Note that the method used to execute cs is executeQuery because cs calls a stored procedure that contains one query and thus produces one result set. If the procedure had contained one update or one DDL statement, the method executeUpdate would have been the one to use. It is sometimes the case, however, that a stored procedure contains more than one SQL statement, in which case it will produce more than one result set, more than one update count, or some combination of result sets and update counts. In this case, where there are multiple results, the method execute should be used to execute the CallableStatement .

The class CallableStatement is a subclass of PreparedStatement, so a CallableStatement object can take input parameters just as a PreparedStatement object can. In addition, a CallableStatement object can take output parameters, or parameters that are for both input and output. INOUT parameters and the method execute are used rarely.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Stored Procedures
Next page: Creating Complete JDBC Applications


Creating Complete JDBC Applications (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
Creating Complete JDBC Applications

Up to this point, you have seen only code fragments. Now you will see some samples.

The first sample code creates the table COFFEES; the second one inserts values into the table and prints the results of a query. The third application creates the table SUPPLIERS, and the fourth populates it with values. After you have run this code, you can try a query that is a join between the tables COFFEES and SUPPLIERS, as in the fifth code example. The sixth code sample is an application that demonstrates a transaction and also shows how to set placeholder parameters in a PreparedStatement object using a for loop.

Because they are complete applications, they include some elements of the Java programming language we have not shown before in the code fragments. We will explain these elements briefly here.

Putting Code in a Class Definition

In the Java™ programming language, any code you want to execute must be inside a class definition. You type the class definition in a file and give the file the name of the class with .java appended to it. So if you have a class named MySQLStatement, its definition should be in a file named MySQLStatement.java.

Importing Classes to Make Them Visible

The first thing to do is to import the packages or classes you will be using in the new class. The classes in our examples all use the java.sql package (the JDBC™ API), which becomes available when the following line of code precedes the class definition:

import java.sql.*;

The star ( * ) indicates that all of the classes in the package java.sql are to be imported. Importing a class makes it visible and means that you do not have to write out the fully qualified name when you use a method or field from that class. If you do not include " import java.sql.*; " in your code, you will have to write " java.sql. " plus the class name in front of all the JDBC fields or methods you use every time you use them. Note that you can import individual classes selectively rather than a whole package. Java does not require that you import classes or packages, but doing so makes writing code a lot more convenient.

Any lines importing classes appear at the top of all the code samples, as they must if they are going to make the imported classes visible to the class being defined. The actual class definition follows any lines that import classes.

Using the main Method

If a class is to be executed, it must contain a static public main method. This method comes right after the line declaring the class and invokes the other methods in the class. The keyword static indicates that this method operates on a class level rather than on individual instances of a class. The keyword public means that members of any class can access this method. Since we are not just defining classes to be used by other classes but instead want to run them, the example applications in this chapter all include a main method.

Using try and catch Blocks

Something else all the sample applications include is try and catch blocks. These are the Java programming language's mechanism for handling exceptions. Java requires that when a method throws an exception, there be some mechanism to handle it. Generally a catch block will catch the exception and specify what happens (which you may choose to be nothing). In the sample code, we use two try blocks and two catch blocks. The first try block contains the method Class.forName, from the java.lang package. This method throws a ClassNotFoundException, so the catch block immediately following it deals with that exception. The second try block contains JDBC methods, which all throw SQLExceptions, so one catch block at the end of the application can handle all of the rest of the exceptions that might be thrown because they will all be SQLException objects.

Retrieving Exceptions

JDBC lets you see the warnings and exceptions generated by your DBMS and by the Java compiler. To see exceptions, you can have a catch block print them out. For example, the following two catch blocks from the sample code print out a message explaining the exception:

try {
    // Code that could generate an exception goes here.
    // If an exception is generated, the catch block below
    // will print out information about it.
} catch(SQLException ex) {
    System.err.println("SQLException: " + ex.getMessage());
}

try {
    Class.forName("myDriverClassName");
} catch(java.lang.ClassNotFoundException e) {
    System.err.print("ClassNotFoundException: ");
    System.err.println(e.getMessage());
}

If you were to run CreateCOFFEES.java twice, you would get an error message similar to this:

SQLException: There is already an object named 'COFFEES'
in the database.
Severity 16, State 1, Line 1

This example illustrates printing out the message component of an SQLException object, which is sufficient for most situations.

There are actually three components, however, and to be complete, you can print them all out. The following code fragment shows a catch block that is complete in two ways. First, it prints out all three parts of an SQLException object: the message (a string that describes the error), the SQL state (a string identifying the error according to the X/Open SQLState conventions), and the vendor error code (a number that is the driver vendor's error code number). The SQLException object ex is caught, and its three components are accessed with the methods getMessage , getSQLState , and getErrorCode .

The second way the following catch block is complete is that it gets all of the exceptions that might have been thrown. If there is a second exception, it will be chained to ex, so ex.getNextException is called to see if there is another exception. If there is, the while loop continues and prints out the next exception's message, SQLState, and vendor error code. This continues until there are no more exceptions.

try {
    // Code that could generate an exception goes here.
    // If an exception is generated, the catch block below
    // will print out information about it.
} catch(SQLException ex) {
    System.out.println("\n--- SQLException caught ---\n");
    while (ex != null) {
        System.out.println("Message:   "
                                   + ex.getMessage ());
        System.out.println("SQLState:  "
                                   + ex.getSQLState ());
        System.out.println("ErrorCode: "
                                   + ex.getErrorCode ());
        ex = ex.getNextException();
        System.out.println("");
    }
}

If you were to substitute the catch block above into the code and run it after the table COFFEES had already been created, you would get the following printout:

--- SQLException caught ---
Message:  There is already an object named 'COFFEES' in the database.
Severity 16, State 1, Line 1
SQLState: 42501
ErrorCode:   2714

The vendor error code is specific to each driver, so you need to check your driver documentation for a list of error codes and what they mean.

Retrieving Warnings

SQLWarning objects are a subclass of SQLException that deal with database access warnings. Warnings do not stop the execution of an application, as exceptions do; they simply alert the user that something did not happen as planned. For example, a warning might let you know that a privilege you attempted to revoke was not revoked. Or a warning might tell you that an error occurred during a requested disconnection.

A warning can be reported on a Connection object, a Statement object (including PreparedStatement and CallableStatement objects), or a ResultSet object. Each of these classes has a getWarnings method, which you must invoke in order to see the first warning reported on the calling object. If getWarnings returns a warning, you can call the SQLWarning method getNextWarning on it to get any additional warnings. Executing a statement automatically clears the warnings from a previous statement, so they do not build up. This means, however, that if you want to retrieve warnings reported on a statement, you must do so before you execute another statement.

The following code fragment illustrates how to get complete information about any warnings reported on the Statement object stmt and also on the ResultSet object rs :

Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("select COF_NAME from COFFEES");
while (rs.next()) {
    String coffeeName = rs.getString("COF_NAME");
    System.out.println("Coffees available at the Coffee Break:  ");
    System.out.println("    " + coffeeName);
    SQLWarning warning = stmt.getWarnings();
    if (warning != null) {
        System.out.println("\n---Warning---\n");
        while (warning != null) {
            System.out.println("Message: "
                                           + warning.getMessage());
            System.out.println("SQLState: "
                                           + warning.getSQLState());
            System.out.print("Vendor error code: ");
            System.out.println(warning.getErrorCode());
            System.out.println("");
            warning = warning.getNextWarning();
        }
    }
    SQLWarning warn = rs.getWarnings();
    if (warn != null) {
        System.out.println("\n---Warning---\n");
        while (warn != null) {
            System.out.println("Message: "
                                           + warn.getMessage());
            System.out.println("SQLState: "
                                           + warn.getSQLState());
            System.out.print("Vendor error code: ");
            System.out.println(warn.getErrorCode());
            System.out.println("");
            warn = warn.getNextWarning();
        }
    }
}

Warnings are actually rather uncommon. Of those that are reported, by far the most common warning is a DataTruncation warning, a subclass of SQLWarning. All DataTruncation objects have an SQLState of 01004, indicating that there was a problem with reading or writing data. DataTruncation methods let you find out in which column or parameter data was truncated, whether the truncation was on a read or write operation, how many bytes should have been transferred, and how many bytes were actually transferred.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: SQL Statements for Creating a Stored Procedure
Next page: Running the Sample Applications


Running the Sample Applications (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
Running the Sample Applications
You are now ready to actually try out some sample code. The directory book.html contains complete, runnable applications that illustrate concepts presented in this chapter and the next. You can download this sample code from the JDBC web site located at:

JDBC Technology Code Samples

Before you can run one of these applications, you will need to edit the file by substituting the appropriate information for the following variables:

url
the JDBC URL; parts one and two are supplied by your driver, and the third part specifies your data source
myLogin
your login name or user name
myPassword
your password for the DBMS
myDriver.ClassName
the class name supplied with your driver

The first example application is the class CreateCoffees , which is in a file named CreateCoffees.java . Below are instructions for running CreateCoffees.java on the three major platforms.

The first line in the instructions below compiles the code in the file CreateCoffees.java . If the compilation is successful, it will produce a file named CreateCoffees.class , which contains the bytecodes translated from the file CreateCoffees.java . These bytecodes will be interpreted by the Java Virtual Machine, which is what makes it possible for Java code to run on any machine with a Java Virtual Machine installed on it.

The second line of code is what actually makes the code run. Note that you use the name of the class, CreateCoffees , not the name of the file, CreateCoffees.class .

UNIX
javac CreateCoffees.java
java CreateCoffees
Windows 95/NT
javac CreateCoffees.java
java CreateCoffees
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating Complete JDBC Applications
Next page: Creating an Applet from an Application


Creating an Applet from an Application (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • Trail • Next »
Creating an Applet from an Application

Suppose that the owner of The Coffee Break wants to display his current coffee prices in an applet on his web page. He can be sure of always displaying the most current price by having the applet get the price directly from his database.

In order to do this, he needs to create two files of code, one with applet code, and one with HTML code. The applet code contains the JDBC code that would appear in a regular application plus additional code for running the applet and displaying the results of the database query. In our example, the applet code is in the file OutputApplet.java. To display our applet in an HTML page, the file OutputApplet.html tells the browser what to display and where to display it.

The rest of this section will tell you about various elements found in applet code that are not present in standalone application code. Some of these elements involve advanced aspects of the Java programming language. We will give you some rationale and some basic explanation, but explaining them fully is beyond the scope of this tutorial. For purposes of this sample applet, you only need to grasp the general idea, so don't worry if you don't understand everything. You can use the applet code as a template, substituting your own queries for the one in the applet.

Writing Applet Code

To begin with, applets will import classes not used by standalone applications. Our applet imports two classes that are special to applets: the class Applet , which is part of the java.applet package, and the class Graphics , which is part of the java.awt package. This applet also imports the general-purpose class java.util.Vector so that we have access to an array-like container whose size can be modified. This code uses Vector objects to store query results so that they can be displayed later.

All applets extend the Applet class; that is, they are subclasses of Applet . Therefore, every applet definition must contain the words extends Applet , as shown here:

public class MyAppletName extends Applet {
    . . .
}

In our applet example, OutputApplet, this line also includes the words implements Runnable , so it looks like this:

public class OutputApplet extends Applet implements Runnable {
    . . .
}

Runnable is an interface that makes it possible to run more than one thread at a time. A thread is a sequential flow of control, and it is possible for a program to be multithreaded, that is, to have many threads doing different things concurrently. The class OutputApplet implements the interface Runnable by defining the method run , the only method in Runnable . In our example the run method contains the JDBC code for opening a connection, executing a query, and getting the results from the result set. Since database connections can be slow, and can sometimes take several seconds, it is generally a good idea to structure an applet so that it can handle the database work in a separate thread.

Similar to a standalone application, which must have a main method, an applet must implement at least one init , start , or paint method. Our example applet defines a start method and a paint method. Every time start is invoked, it creates a new thread (named worker ) to re-evaluate the database query. Every time paint is invoked, it displays either the query results or a string describing the current status of the applet.

As stated previously, the run method defined in OutputApplet contains the JDBC code. When the thread worker invokes the method start , the run method is called automatically, and it executes the JDBC code in the thread worker . The code in run is very similar to the code you have seen in our other sample code with three exceptions. First, it uses the class Vector to store the results of the query. Second, it does not print out the results but rather adds them to the Vector results for display later. Third, it likewise does not print out exceptions and instead records error messages for later display.

Applets have various ways of drawing, or displaying, their content. This applet, a very simple one that has only text, uses the method drawString (part of the Graphics class) to display its text. The method drawString takes three arguments: (1) the string to be displayed, (2) the x coordinate, indicating the horizontal starting point for displaying the string, and (3) the y coordinate, indicating the vertical starting point for displaying the string (which is below the text).

The method paint is what actually displays something on the screen, and in OutputApplet.java , it is defined to contain calls to the method drawString . The main thing drawString displays is the contents of the Vector results (the stored query results). When there are no query results to display, drawString will display the current contents of the String message . This string will be "Initializing" to begin with. It gets set to "Connecting to database" when the method start is called, and the method setError sets it to an error message when an exception is caught. Thus, if the database connection takes much time, the person viewing this applet will see the message "Connecting to database" because that will be the contents of message at that time. (The method paint is called by AWT when it wants the applet to display its current state on the screen.)

The last two methods defined in the class OutputApplet, setError and setResults are private, which means that they can be used only by OutputApplet. These methods both invoke the method repaint , which clears the screen and calls paint . So if setResults calls repaint , the query results will be displayed, and if setError calls repaint , an error message will be displayed.

A final point to be made is that all the methods defined in OutputApplet except run are synchronized . The keyword synchronized indicates that while a method is accessing an object, other synchronized methods are blocked from accessing that object. The method run is not declared synchronized so that the applet can still paint itself on the screen while the database connection is in progress. If the database access methods were synchronized , they would prevent the applet from being repainted while they are executing, and that could result in delays with no accompanying status message.

To summarize, in an applet, it is good programming practice to do some things you would not need to do in a standalone application:

  1. Put your JDBC code in a separate thread
  2. Display status messages on the screen during any delays, such as when a database connection is taking a long time
  3. Display error messages on the screen instead of printing them to System.out or System.err .

Running an Applet

Before running our sample applet, you need to compile the file OutputApplet.java . This creates the file OutputApplet.class , which is referenced by the file OutputApplet.html.

The easiest way to run an applet is to use the appletviewer, which is included as part of the JDK. Simply follow the instructions below for your platform to compile and run OutputApplet.java :

UNIX
javac OutputApplet.java
appletviewer OutputApplet.html
Windows 95/NT
javac OutputApplet.java
appletviewer OutputApplet.html

Applets loaded over the network are subject to various security restrictions. Although this can seem bothersome at times, it is absolutely necessary for network security, and security is one of the major advantages of using the Java programming language. An applet cannot make network connections except to the host it came from unless the browser allows it. Whether one is able to treat locally installed applets as "trusted" also depends on the security restrictions imposed by the browser. An applet cannot ordinarily read or write files on the host that is executing it, and it cannot load libraries or define native methods.

Applets can usually make network connections to the host they came from, so they can work very well on intranets.

The JDBC-ODBC Bridge driver is a somewhat special case. It can be used quite successfully for intranet access, but it requires that ODBC, the bridge, the bridge native library, and JDBC be installed on every client. With this configuration, intranet access works from Java applications and from trusted applets. However, since the bridge requires special client configuration, it is not practical to run applets on the Internet with the JDBC-ODBC Bridge driver. Note that this is a limitation of the JDBC-ODBC Bridge, not of JDBC. With a pure Java JDBC driver, you do not need any special configuration to run applets on the Internet.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Running the Sample Applications
Next page: End of Trail


Trail: Java Management Extensions (JMX) (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Java Management Extensions (JMX)

The Java Management Extensions (JMX) trail provides an introduction to the JMX technology, which is included in the Java Platform, Standard Edition (Java SE platform). This trail presents examples of how to use the most important features of the JMX technology.

Overview of the JMX Technology provides a brief description of the JMX technology, including its purpose and principal features.

Introducing MBeans introduces the fundamental concept of the JMX technology, managed beans, otherwise known as MBeans. This lesson also introduces MXBeans.

Notifications introduces the JMX technology's notification mechanism.

Remote Management shows how to implement the JMX API's remote management capabilities and how to create a JMX client application.

Where to Go From Here provides pointers to more advanced documentation that describes the JMX technology.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Overview of the JMX Technology


Lesson: Overview of the JMX Technology (The Java™ Tutorials > Java Management Extensions (JMX))

Overview of the JMX Technology
Why Use the JMX Technology?
Architecture of the JMX Technology
Monitoring and Management of the Java Virtual Machine
Trail: Java Management Extensions (JMX)
Home Page > Java Management Extensions (JMX)
« Previous • Trail • Next »
Lesson: Overview of the JMX Technology

The Java Management Extensions (JMX) technology is a standard part of the Java Platform, Standard Edition (Java SE platform). The JMX technology was added to the platform in the Java 2 Platform, Standard Edition (J2SE) 5.0 release.

The JMX technology provides a simple, standard way of managing resources such as applications, devices, and services. Because the JMX technology is dynamic, you can use it to monitor and manage resources as they are created, installed and implemented. You can also use the JMX technology to monitor and manage the Java Virtual Machine (Java VM).

The JMX specification defines the architecture, design patterns, APIs, and services in the Java programming language for management and monitoring of applications and networks.

Using the JMX technology, a given resource is instrumented by one or more Java objects known as Managed Beans, or MBeans. These MBeans are registered in a core-managed object server, known as an MBean server. The MBean server acts as a management agent and can run on most devices that have been enabled for the Java programming language.

The specifications define JMX agents that you use to manage any resources that have been correctly configured for management. A JMX agent consists of an MBean server, in which MBeans are registered, and a set of services for handling the MBeans. In this way, JMX agents directly control resources and make them available to remote management applications.

The way in which resources are instrumented is completely independent from the management infrastructure. Resources can therefore be rendered manageable regardless of how their management applications are implemented.

The JMX technology defines standard connectors (known as JMX connectors) that enable you to access JMX agents from remote management applications. JMX connectors using different protocols provide the same management interface. Consequently, a management application can manage resources transparently, regardless of the communication protocol used. JMX agents can also be used by systems or applications that are not compliant with the JMX specification, as long as those systems or applications support JMX agents.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: Why Use the JMX Technology?


Why Use the JMX Technology? (The Java™ Tutorials > Java Management Extensions (JMX) > Overview of the JMX Technology)

Trail: Java Management Extensions (JMX)
Lesson: Overview of the JMX Technology
Overview of the JMX Technology
Why Use the JMX Technology?
Architecture of the JMX Technology
Monitoring and Management of the Java Virtual Machine
Home Page > Java Management Extensions (JMX) > Overview of the JMX Technology
« Previous • Trail • Next »
Why Use the JMX Technology?

The JMX technology provides developers with a flexible means to instrument Java technology-based applications (Java applications), create smart agents, implement distributed management middleware and managers, and smoothly integrate these solutions into existing management and monitoring systems.

  • The JMX technology enables Java applications to be managed without heavy investment.
    A JMX technology-based agent (JMX agent) can run on most Java technology-enabled devices. Consequently, Java applications can become manageable with little impact on their design. A Java application needs only to embed a managed object server and make some of its functionality available as one or several managed beans (MBeans) registered in the object server. That is all it takes to benefit from the management infrastructure.
  • The JMX technology provides a standard way to manage Java applications, systems, and networks.
    For example, the Java Platform, Enterprise Edition (Java EE) 5 Application Server conforms to the JMX architecture and consequently can be managed by using JMX technology.
  • The JMX technology can be used for out-of-the-box management of the Java VM.
    The Java Virtual Machine (Java VM) is highly instrumented using the JMX technology. You can start a JMX agent to access the built-in Java VM instrumentation, and thereby monitor and manage a Java VM remotely.
  • The JMX technology provides a scalable, dynamic management architecture.
    Every JMX agent service is an independent module that can be plugged into the management agent, depending on the requirements. This component-based approach means that JMX solutions can scale from small-footprint devices to large telecommunications switches and beyond. The JMX specification provides a set of core agent services. Additional services can be developed and dynamically loaded, unloaded, or updated in the management infrastructure.
  • The JMX technology leverages existing standard Java technologies.
    Whenever needed, the JMX specification references existing Java specifications, for example, the Java Naming and Directory Interface (J.N.D.I.) API.
  • The JMX technology-based applications (JMX applications) can be created from a NetBeans IDE module.
    You can obtain a module from the NetBeans Update Center (select Tools -> Update Center in the NetBeans interface) that enables you to create JMX applications by using the NetBeans IDE. This reduces the cost of development of JMX applications.
  • The JMX technology integrates with existing management solutions and emerging technologies.
    The JMX APIs are open interfaces that any management system vendor can implement. JMX solutions can use lookup and discovery services and protocols such as Jini network technology and the Service Location Protocol (SLP).
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Overview of the JMX Technology
Next page: Architecture of the JMX Technology


Architecture of the JMX Technology (The Java™ Tutorials > Java Management Extensions (JMX) > Overview of the JMX Technology)

Trail: Java Management Extensions (JMX)
Lesson: Overview of the JMX Technology
Overview of the JMX Technology
Why Use the JMX Technology?
Architecture of the JMX Technology
Monitoring and Management of the Java Virtual Machine
Home Page > Java Management Extensions (JMX) > Overview of the JMX Technology
« Previous • Trail • Next »
Architecture of the JMX Technology
The JMX technology can be divided into three levels, as follows:
  • Instrumentation
  • JMX agent
  • Remote management

Instrumentation

To manage resources using the JMX technology, you must first instrument the resources in the Java programming language. You use Java objects known as MBeans to implement the access to the resources' instrumentation. MBeans must follow the design patterns and interfaces defined in the JMX specification. Doing so ensures that all MBeans provide managed resource instrumentation in a standardized way. In addition to standard MBeans, the JMX specification also defines a special type of MBean called an MXBean. An MXBean is an MBean that references only a pre-defined set of data types. Other types of MBean exist, but this trail will concentrate on standard MBeans and MXBeans.

Once a resource has been instrumented by MBeans, it can be managed through a JMX agent. MBeans do not require knowledge of the JMX agent with which they will operate.

MBeans are designed to be flexible, simple, and easy to implement. Developers of applications, systems, and networks can make their products manageable in a standard way without having to understand or invest in complex management systems. Existing resources can be made manageable with minimum effort.

In addition, the instrumentation level of the JMX specification provides a notification mechanism. This mechanism enables MBeans to generate and propagate notification events to components of the other levels.

JMX Agent

A JMX technology-based agent (JMX agent) is a standard management agent that directly controls resources and makes them available to remote management applications. JMX agents are usually located on the same machine as the resources they control, but this arrangement is not a requirement.

The core component of a JMX agent is the MBean server, a managed object server in which MBeans are registered. A JMX agent also includes a set of services to manage MBeans, and at least one communications adaptor or connector to allow access by a management application.

When you implement a JMX agent, you do not need to know the semantics or functions of the resources that it will manage. In fact, a JMX agent does not even need to know which resources it will serve because any resource instrumented in compliance with the JMX specification can use any JMX agent that offers the services that the resource requires. Similarly, the JMX agent does not need to know the functions of the management applications that will access it.

Remote Management

JMX technology instrumentation can be accessed in many different ways, either through existing management protocols such as the Simple Network Management Protocol (SNMP) or through proprietary protocols. The MBean server relies on protocol adaptors and connectors to make a JMX agent accessible from management applications outside the agent's Java Virtual Machine (Java VM).

Each adaptor provides a view through a specific protocol of all MBeans that are registered in the MBean server. For example, an HTML adaptor could display an MBean in a browser.

Connectors provide a manager-side interface that handles the communication between manager and JMX agent. Each connector provides the same remote management interface through a different protocol. When a remote management application uses this interface, it can connect to a JMX agent transparently through the network, regardless of the protocol. The JMX technology provides a standard solution for exporting JMX technology instrumentation to remote applications based on Java Remote Method Invocation (Java RMI).

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Why Use the JMX Technology?
Next page: Monitoring and Management of the Java Virtual Machine


Monitoring and Management of the Java Virtual Machine (The Java™ Tutorials > Java Management Extensions (JMX) > Overview of the JMX Technology)

Trail: Java Management Extensions (JMX)
Lesson: Overview of the JMX Technology
Overview of the JMX Technology
Why Use the JMX Technology?
Architecture of the JMX Technology
Monitoring and Management of the Java Virtual Machine
Home Page > Java Management Extensions (JMX) > Overview of the JMX Technology
« Previous • Trail • Next »
Monitoring and Management of the Java Virtual Machine

The JMX technology can also be used to monitor and manage the Java virtual machine (Java VM).

The Java VM has built-in instrumentation that enables you to monitor and manage it by using the JMX technology. These built-in management utilities are often referred to as out-of-the-box management tools for the Java VM. To monitor and manage different aspects of the Java VM, the Java VM includes a platform MBean server and special MXBeans for use by management applications that conform to the JMX specification.

Platform MXBeans and the Platform MBean Server

The platform MXBeans are a set of MXBeans that is provided with the Java SE platform for monitoring and managing the Java VM and other components of the Java Runtime Environment (JRE). Each platform MXBean encapsulates a part of Java VM functionality, such as the class-loading system, just-in-time (JIT) compilation system, garbage collector, and so on. These MXBeans can be displayed and interacted with by using a monitoring and management tool that complies with the JMX specification, to enable you to monitor and manage these different VM functionalities. One such monitoring and management tool is the Java SE platform's JConsole graphical user interface (GUI).

The Java SE platform provides a standard platform MBean server in which these platform MXBeans are registered. The platform MBean server can also register any other MBeans you wish to create.

JConsole

The Java SE platform includes the JConsole monitoring and management tool, which complies with the JMX specification. JConsole uses the extensive instrumentation of the Java VM (the platform MXBeans) to provide information about the performance and resource consumption of applications that are running on the Java platform.

Out-of-the-Box Management in Action

Because standard monitoring and management utilities that implement the JMX technology are built into the Java SE platform, you can see the out-of-the-box JMX technology in action without having to write a single line of JMX API code. You can do so by launching a Java application and then monitoring it by using JConsole.

Monitoring an Application by Using JConsole

This procedure shows how to monitor the Notepad Java application. This procedure assumes that you are running the Java SE 6 platform.

  1. Start the Notepad Java application, by using the following command in a terminal window:

    java -jar jdk_home/demo/jfc/Notepad/Notepad.jar

    Where jdk_home is the directory in which the Java Development Kit (JDK) is installed.

  2. Once Notepad has opened, in a different terminal window, start JConsole by using the following command:

    jconsole

    A New Connection dialog box is displayed.

  3. In the New Connection dialog box, select Notepad.jar from the Local Process list, and click the Connect button.

    JConsole opens and connects itself to the Notepad.jar process. When JConsole opens, you are presented with an overview of monitoring and management information related to Notepad. For example, you can view the amount of heap memory the application is consuming, the number of threads the application is currently running, and how much central procesing unit (CPU) capacity the application is consuming.

  4. Click the different JConsole tabs.

    Each tab presents more detailed information about the different areas of functionality of the Java VM in which Notepad is running. All the information presented is obtained from the various JMX technology MXBeans mentioned in this trail. All the platform MXBeans can be displayed in the MBeans tab. The MBeans tab is examined in the next section of this trail.

  5. To close JConsole, select Connection -> Exit.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Architecture of the JMX Technology
Next page: Introducing MBeans


Lesson: Introducing MBeans (The Java™ Tutorials > Java Management Extensions (JMX))

Introducing MBeans
Standard MBeans
MXBeans
Trail: Java Management Extensions (JMX)
Home Page > Java Management Extensions (JMX)
« Previous • Trail • Next »
Lesson: Introducing MBeans

This lesson introduces the fundamental concept of the JMX API, namely managed beans, or MBeans.

An MBean is a managed Java object, similar to a JavaBeans component, that follows the design patterns set forth in the JMX specification. An MBean can represent a device, an application, or any resource that needs to be managed. MBeans expose a management interface that consists of the following:

  • A set of readable or writable attributes, or both.
  • A set of invokable operations.
  • A self-description.

The management interface does not change throughout the life of an MBean instance. MBeans can also emit notifications when certain predefined events occur.

The JMX specification defines five types of MBean:

  • Standard MBeans
  • Dynamic MBeans
  • Open MBeans
  • Model MBeans
  • MXBeans

The examples in this trail demonstrate only the simplest types of MBean, namely standard MBeans and MXBeans.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Standard MBeans


Standard MBeans (The Java™ Tutorials > Java Management Extensions (JMX) > Introducing MBeans)

Trail: Java Management Extensions (JMX)
Lesson: Introducing MBeans
Introducing MBeans
Standard MBeans
MXBeans
Home Page > Java Management Extensions (JMX) > Introducing MBeans
« Previous • Trail • Next »
Standard MBeans

This section presents an example of a straightforward, standard MBean.

A standard MBean is defined by writing a Java interface called SomethingMBean and a Java class called Something that implements that interface. Every method in the interface defines either an attribute or an operation in the MBean. By default, every method defines an operation. Attributes and operations are methods that follow certain design patterns. A standard MBean is composed of an MBean interface and a class. The MBean interface lists the methods for all exposed attributes and operations. The class implements this interface and provides the functionality of the instrumented resource.

The following sections examine an example of a standard MBean and a simple JMX technology-enabled agent (JMX agent) that manages the MBean.

MBean Interface

An example of a basic MBean interface, HelloMBean, follows:

package com.example;

public interface HelloMBean {

    public void sayHello();
    public int add(int x, int y);

    public String getName();

    public int getCacheSize();
    public void setCacheSize(int size);
}

By convention, an MBean interface takes the name of the Java class that implements it, with the suffix MBean added. In this case, the interface is called HelloMBean. The Hello class that implements this interface is described in the next section.

According to the JMX specification, an MBean interface consists of named and typed attributes that are readable and possibly writable, in addition to the named and typed operations that can be invoked by the applications that are managed by the MBean. The HelloMBean interface declares two operations: the Java methods add() and sayHello().

HelloMBean declares two attributes: Name is a read-only string, and CacheSize is an integer that can be both read and written. Getter and setter methods are declared to allow the managed application to access and possibly change the attribute values. As defined by the JMX specification, a getter is any public method that does not return void and whose name begins with get. A getter enables a manager to read the value of the attribute, whose type is that of the returned object. A setter is any public method that takes a single parameter and whose name begins with set. A setter enables a manager to write a new value in the attribute, whose type is the same as that of the parameter.

The implementation of these operations and attributes is shown in the following section.

MBean Implementation

The Hello Java class that follows implements the HelloMBean MBean interface:

package com.example;

public class Hello [...] implements HelloMBean {
    public void sayHello() {
    System.out.println("hello, world");
    }

    public int add(int x, int y) {
    return x + y;
    }

    public String getName() {
    return this.name;
    }

    public int getCacheSize() {
    return this.cacheSize;
    }

    public synchronized void setCacheSize(int size) {
    [...]
    this.cacheSize = size;

    System.out.println("Cache size now " + this.cacheSize);
    }

    [...]

    private final String name = "Reginald";
    private int cacheSize = DEFAULT_CACHE_SIZE;
    private static final int DEFAULT_CACHE_SIZE = 200;
}

The straightforward Hello class provides the definitions of the operations and attributes that are declared by HelloMBean. The sayHello() and add() operations are extremely simple, but real-life operations can be as simple or as sophisticated as needed.

The methods to get the Name attribute and to get and set the CacheSize attribute are also defined. In this example, the Name attribute value never changes. However, in a real scenario this attribute might change as the managed resource runs. For example, the attribute might represent statistics such as uptime or memory usage. Here, the attribute is merely the name Reginald.

Calling the setCacheSize method enables you to alter the CacheSize attribute from its declared default value of 200. In a real scenario, changing the CacheSize attribute could require other operations to be performed, such as discarding entries or allocating new entries. This example merely prints a message to confirm that the cache size has changed. However, more sophisticated operations could be defined instead of the simple call to println().

With the Hello MBean and its interface thus defined, they can now be used to manage the resource they represent, as shown in the following section.

Creating a JMX Agent to Manage a Resource

Once a resource has been instrumented by MBeans, the management of that resource is performed by a JMX agent.

The core component of a JMX agent is the MBean server. An MBean server is a managed object server in which MBeans are registered. A JMX agent also includes a set of services to manage MBeans. See the API documentation for the MBeanServer interface for details of the MBean server implementation.

The Main class that follows represents a basic JMX agent:

package com.example;

import java.lang.management.*;
import javax.management.*;

public class Main {

   public static void main(String[] args) throws Exception {

      MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
      ObjectName name = new ObjectName("com.example:type=Hello");
      Hello mbean = new Hello();
      mbs.registerMBean(mbean, name);

      [...]

      System.out.println("Waiting forever...");
      Thread.sleep(Long.MAX_VALUE);
   }
}

The JMX agent Main begins by obtaining an MBean server that has been created and initialized by the platform, by calling the getPlatformMBeanServer() method of the java.lang.management.ManagementFactory class. If no MBean server has been created by the platform already, then getPlatformMBeanServer() creates an MBean server automatically by calling the JMX method MBeanServerFactory.createMBeanServer(). The MBeanServer instance obtained by Main is named mbs.

Next, Main defines an object name for the MBean instance that it will create. Every JMX MBean must have an object name. The object name is an instance of the JMX class ObjectName and must conform to the syntax defined by the JMX specification. Namely, the object name must contain a domain and a list of key-properties. In the object name defined by Main, the domain is com.example (the package in which the example MBean is contained). In addition, the key-property declares that this object is of the type Hello.

An instance of a Hello object, named mbean, is created. The Hello object named mbean is then registered as an MBean in the MBean server mbs with the object name name, by passing the object and the object name into a call to the JMX method MBeanServer.registerMBean().

With the Hello MBean registered in the MBean server, Main simply waits for management operations to be performed on Hello. In this example, these management operations are invoking sayHello() and add(), and getting and setting the attribute values.

Running the Standard MBean Example

Having examined the example classes, you can now run the example. In this example, JConsole is used to interact with the MBean.

To run the example, follow these steps:

  1. Save the bundle of JMX API sample classes, jmx_examples.zip, to your working directory, work_dir.

  2. Unzip the bundle of sample classes by using the following command in a terminal window.

    unzip jmx_examples.zip

  3. Compile the example Java classes from within the work_dir directory.

    javac com/example/*.java

  4. Start the Main application.

    java com.example.Main

    A confirmation that Main is waiting for something to happen is displayed.

  5. Start JConsole in a different terminal window on the same machine.

    jconsole

    The New Connection dialog box is displayed, presenting a list of running JMX agents that you can connect to.

  6. In the New Connection dialog box, select com.example.Main from the list and click Connect.

    A summary of your platform's current activity is displayed.

  7. Click the MBeans tab.

    This panel shows all the MBeans that are currently registered in the MBean server.

  8. In the left frame, expand the com.example node in the MBean tree.

    You see the example MBean Hello that was created and registered by Main. If you click Hello, you see its associated Attributes and Operations nodes in the MBean tree.

  9. Expand the Attributes node of the Hello MBean in the MBean tree.

    The MBean attributes that were defined by the Hello class are displayed.

  10. Change the value of the CacheSize attribute to 150.

    In the terminal window in which you started Main, a confirmation of this attribute change is generated.

  11. Expand the Operations node of the Hello MBean in the MBean tree.

    The two operations declared by the Hello MBean, sayHello() and add(), are visible.

  12. Invoke the sayHello() operation by clicking the sayHello button.

    A JConsole dialog box informs you that the method was invoked successfully. The message "hello, world" is generated in the terminal window in which Main is running.

  13. Provide two integers for the add() operation to add and click the add button.

    The answer is displayed in a JConsole dialog box.

  14. To close JConsole, select Connection -> Exit.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Introducing MBeans
Next page: MXBeans


MXBeans (The Java™ Tutorials > Java Management Extensions (JMX) > Introducing MBeans)

Trail: Java Management Extensions (JMX)
Lesson: Introducing MBeans
Introducing MBeans
Standard MBeans
MXBeans
Home Page > Java Management Extensions (JMX) > Introducing MBeans
« Previous • Trail • Next »
MXBeans

This section explains a special type of MBean, called MXBeans.

An MXBean is a type of MBean that references only a predefined set of data types. In this way, you can be sure that your MBean will be usable by any client, including remote clients, without any requirement that the client have access to model-specific classes representing the types of your MBeans. MXBeans provide a convenient way to bundle related values together, without requiring clients to be specially configured to handle the bundles.

In the same way as for standard MBeans, an MXBean is defined by writing a Java interface called SomethingMXBean and a Java class that implements that interface. However, unlike standard MBeans, MXBeans do not require the Java class to be called Something. Every method in the interface defines either an attribute or an operation in the MXBean. The annotation @MXBean can be also used to annotate the Java interface, instead of requiring the interface's name to be followed by the MXBean suffix.

MXBeans existed in the Java 2 Platform, Standard Edition (J2SE) 5.0 software, in the package java.lang.management. However, users can now define their own MXBeans, in addition to the standard set that is defined in java.lang.management.

The main idea behind MXBeans is that types such as java.lang.management.MemoryUsage that are referenced in the MXBean interface, java.lang.management.MemoryMXBean in this case, are mapped into a standard set of types, the so-called Open Types that are defined in the package javax.management.openmbean. The exact mapping rules appear in the MXBean specification. However, the general principle is for simple types such as int or String to remain unchanged, while complex types such as MemoryUsage get mapped to the standard type CompositeDataSupport.

The MXBean example consists of the following files, which are found in jmx_examples.zip:

  • QueueSamplerMXBean interface
  • QueueSampler class that implements the MXBean interface
  • QueueSample Java type returned by the getQueueSample() method in the MXBean interface
  • Main, the program that sets up and runs the example

The MXBean example uses these classes to perform the following actions:

  • Defines a simple MXBean that manages a resource of type Queue<String>
  • Declares a getter, getQueueSample, in the MXBean that takes a snapshot of the queue when invoked and returns a Java class QueueSample that bundles the following values together:
    • The time the snapshot was taken
    • The queue size
    • The head of the queue at that given time
  • Registers the MXBean in an MBean server

MXBean Interface

The following code shows the example QueueSamplerMXBean MXBean interface:

package com.example;

public interface QueueSamplerMXBean {
    public QueueSample getQueueSample();
    public void clearQueue();
}

Note that you declare an MXBean interface in exactly the same way as you declare a standard MBean interface. The QueueSamplerMXBean interface declares a getter, getQueueSample and an operation, clearQueue.

Defining MXBean Operations

The MXBean operations are declared in the QueueSampler example class, as follows:

package com.example;

import java.util.Date;
import java.util.Queue;

public class QueueSampler implements QueueSamplerMXBean {

    private Queue queue;

    public QueueSampler(Queue queue) {
       this.queue = queue;
    }

    public QueueSample getQueueSample() {
        synchronized (queue) {
            return new QueueSample(new Date(), queue.size(), queue.peek());
        }
    }

    public void clearQueue() {
        synchronized (queue) {
            queue.clear();
        }
    }
}

QueueSampler defines the getQueueSample() getter and clearQueue() operation that were declared by the MXBean interface. The getQueueSample() operation returns an instance of the QueueSample Java type which was created with the values returned by the java.util.Queue methods peek() and size(), and an instance of java.util.Date.

Defining the Java Type Returned by the MXBean Interface

The QueueSample instance returned by QueueSampler is defined in the QueueSample class, as follows:

package com.example;

import java.beans.ConstructorProperties;
import java.util.Date;

public class QueueSample {

    private final Date date;
    private final int size;
    private final String head;

    @ConstructorProperties({"date", "size", "head"})
    public QueueSample(Date date, int size, String head) {
        this.date = date;
        this.size = size;
        this.head = head;
    }

    public Date getDate() {
        return date;
    }

    public int getSize() {
        return size;
    }

    public String getHead() {
        return head;
    }
}
In the QueueSample class, the MXBean framework calls all the getters in QueueSample to convert the given instance into a CompositeData instance and uses the @ConstructorProperties annotation to reconstruct a QueueSample instance from a CompositeData instance.

Creating and Registering the MXBean in the MBean Server

So far, the following have been defined: an MXBean interface and the class that implements it, as well as the Java type that is returned. Next, the MXBean must be created and registered in an MBean server. These actions are performed by the same Main example JMX agent that was used in the standard MBean example, but the relevant code was not shown in the Standard MBean lesson.

package com.example;

import java.lang.management.ManagementFactory;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import javax.management.MBeanServer;
import javax.management.ObjectName;

public class Main {

    public static void main(String[] args) throws Exception {
        MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();

    [...]

        ObjectName mxbeanName = new ObjectName("com.example:type=QueueSampler");

        Queue queue = new ArrayBlockingQueue(10);
        queue.add("Request-1");
        queue.add("Request-2");
        queue.add("Request-3");
        QueueSampler mxbean = new QueueSampler(queue);

        mbs.registerMBean(mxbean, mxbeanName);

        System.out.println("Waiting...");
        Thread.sleep(Long.MAX_VALUE);
    }
}

The Main class performs the following actions:

  • Gets the platform MBean server.
  • Creates an object name for the MXBean QueueSampler.
  • Creates a Queue instance for the QueueSampler MXBean to process.
  • Feeds the Queue instance to a newly created QueueSampler MXBean.
  • Registers the MXBean in the MBean server in exactly the same way as a standard MBean.

Running the MXBean Example

The MXBean example uses classes from the jmx_examples.zip bundle that you used in the Standard MBeans section. To run the MXBeans example follow these steps:

  1. If you have not done so already, save jmx_examples.zip into your work_dir directory.

  2. Unzip the bundle of sample classes by using the following command in a terminal window.

    unzip jmx_examples.zip

  3. Compile the example Java classes from within the work_dir directory.

    javac com/example/*.java

  4. Start the Main application.

    java com.example.Main

    A confirmation that Main is waiting for something to happen is generated.

  5. Start JConsole in a different terminal window on the same machine.

    jconsole

    The New Connection dialog box is displayed, presenting a list of running JMX agents that you can connect to.

  6. In the New Connection dialog box, select com.example.Main from the list and click Connect.

    A summary of your platform's current activity is displayed.

  7. Click the MBeans tab.

    This panel shows all the MBeans that are currently registered in the MBean server.

  8. In the left frame, expand the com.example node in the MBean tree.

    You see the example MBean QueueSampler that was created and registered by Main. If you click QueueSampler, you see its associated Attributes and Operations nodes in the MBean tree.

  9. Expand the Attributes node.

    You see the QueueSample attribute appear in the right pane, with its value of javax.management.openmbean.CompositeDataSupport.

  10. Double-click the CompositeDataSupport value.

    You see the QueueSample values date, head, and size because the MXBean framework has converted the QueueSample instance into CompositeData. If you had defined QueueSampler as a standard MBean rather than as an MXBean, JConsole would not have found the QueueSample class because it would not be in its class path. If QueueSampler had been a standard MBean, you would have received a ClassNotFoundException message when retrieving the QueueSample attribute value. The fact that JConsole finds QueueSampler demonstrates the usefulness of using MXBeans when connecting to JMX agents through generic JMX clients such as JConsole.

  11. Expand the Operations node.

    A button to invoke the clearQueue operation is displayed.

  12. Click the clearQueue button.

    A confirmation that the method was invoked successfully is displayed.

  13. Expand the Attributes node again, and double click on the CompositeDataSupport value.

    The head and size values have been reset.

  14. To close JConsole, select Connection -> Exit.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Standard MBeans
Next page: Notifications


Lesson: Notifications (The Java™ Tutorials > Java Management Extensions (JMX))

Trail: Java Management Extensions (JMX)
Home Page > Java Management Extensions (JMX)
« Previous • Trail • Next »
Lesson: Notifications

The JMX API defines a mechanism to enable MBeans to generate notifications, for example, to signal a state change, a detected event, or a problem.

To generate notifications, an MBean must implement the interface NotificationEmitter or extend NotificationBroadcasterSupport. To send a notification, you need to construct an instance of the class javax.management.Notification or a subclass (such as AttributeChangedNotification), and pass the instance to NotificationBroadcasterSupport.sendNotification.

Every notification has a source. The source is the object name of the MBean that generated the notification.

Every notification has a sequence number. This number can be used to order notifications coming from the same source when order matters and there is a risk of the notifications being handled in the wrong order. The sequence number can be zero, but preferably the number increments for each notification from a given MBean.

The Hello MBean implementation in Standard MBeans actually implements the notification mechanism. However, this code was omitted in that lesson for the sake of simplicity. The complete code for Hello follows:

package com.example;

import javax.management.*;

public class Hello
        extends NotificationBroadcasterSupport implements HelloMBean {

    public void sayHello() {
        System.out.println("hello, world");
    }

    public int add(int x, int y) {
        return x + y;
    }

    public String getName() {
        return this.name;
    }

    public int getCacheSize() {
        return this.cacheSize;
    }

    public synchronized void setCacheSize(int size) {
        int oldSize = this.cacheSize;
        this.cacheSize = size;

        System.out.println("Cache size now " + this.cacheSize);

        Notification n =
            new AttributeChangeNotification(this,
                        sequenceNumber++,
                        System.currentTimeMillis(),
                        "CacheSize changed",
                        "CacheSize",
                        "int",
                        oldSize,
                        this.cacheSize);

    sendNotification(n);
    }

    @Override
    public MBeanNotificationInfo[] getNotificationInfo() {
        String[] types = new String[] {
            AttributeChangeNotification.ATTRIBUTE_CHANGE
        };
        String name = AttributeChangeNotification.class.getName();
        String description = "An attribute of this MBean has changed";
        MBeanNotificationInfo info =
            new MBeanNotificationInfo(types, name, description);
        return new MBeanNotificationInfo[] {info};
    }

    private final String name = "Reginald";
    private int cacheSize = DEFAULT_CACHE_SIZE;
    private static final int DEFAULT_CACHE_SIZE = 200;

    private long sequenceNumber = 1;
}

This Hello MBean implementation extends the NotificationBroadcasterSupport class. NotificationBroadcasterSupport implements the NotificationEmitter interface.

The operations and attributes are set in the same way as in the standard MBean example, with the exception that the CacheSize attribute's setter method now defines a value of oldSize. This value records the CacheSize attribute's value prior to the set operation.

The notification is constructed from an instance, n, of the JMX class AttributeChangeNotification, which extends javax.management.Notification. The notification is constructed within the definition of the setCacheSize() method from the following information. This information is passed to AttributeChangeNotification as parameters.

  • The object name of the source of the notification, namely the Hello MBean, represented by this
  • A sequence number, namely sequenceNumber, that is set to 1 and that increases incrementally
  • A timestamp
  • The content of the notification message
  • The name of the attribute that has changed, in this case, CacheSize
  • The type of attribute that has changed
  • The old attribute value, in this case, oldSize
  • The new attribute value, in this case, this.cacheSize

The notification n is then passed to the NotificationBroadcasterSupport.sendNotification() method.

Finally, the MBeanNotificationInfo instance is defined to describe the characteristics of the different notification instances generated by the MBean for a given type of notification. In this case the type of notifications sent is AttributeChangeNotification notifications.

Running the MBean Notification Example

Once again, you will use JConsole to interact with the Hello MBean, this time to send and receive notifications.

  1. If you have not done so already, save jmx_examples.zip into your work_dir directory.

  2. Unzip the bundle of sample classes by using the following command in a terminal window.

    unzip jmx_examples.zip

  3. Compile the example Java classes from within the work_dir directory.

    javac com/example/*.java

  4. Start the Main application.

    java com.example.Main

    A confirmation that Main is waiting for something to happen is generated.

  5. Start JConsole in a different terminal window on the same machine.

    jconsole

    The New Connection dialog box is displayed, presenting a list of running JMX agents that you can connect to.

  6. In the New Connection dialog box, select com.example.Main from the list and click Connect.

    A summary of your platform's current activity is displayed.

  7. Click the MBeans tab.

    This panel shows all the MBeans that are currently registered in the MBean server.

  8. In the left frame, expand the com.example node in the MBean tree.

    You see the example MBean Hello that was created and registered by Hello. If you click Hello, you see its Notifications node in the MBean tree.

  9. Expand the Notifications node of the Hello MBean in the MBean tree.

    Note that the panel is blank.

  10. Click the Subscribe button.

    The current number of notifications received (0) is displayed in the Notifications node label.

  11. Expand the Attributes node of the Hello MBean in the MBean tree, and change the value of the CacheSize attribute to 150.

    In the terminal window in which you started Main, a confirmation of this attribute change is displayed. Note that the number of received notifications displayed in the Notifications node has changed to 1.

  12. Expand again the Notifications node of the Hello MBean in the MBean tree.

    The details of the notification are displayed.

  13. To close JConsole, select Connection -> Exit.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Remote Management


Lesson: Remote Management (The Java™ Tutorials > Java Management Extensions (JMX))

Remote Management
Exposing a Resource for Remote Management By JConsole
Creating a Custom JMX Client
Trail: Java Management Extensions (JMX)
Home Page > Java Management Extensions (JMX)
« Previous • Trail • Next »
Lesson: Remote Management

The JMX API enables you to perform remote management of your resources by using JMX technology-based connectors (JMX connectors). A JMX connector makes an MBean server accessible to remote Java technology-based clients. The client end of a connector exports essentially the same interface as the MBean server.

A JMX connector consists of a connector client and a connector server. A connector server is attached to an MBean server and listens for connection requests from clients. A connector client is responsible for establishing a connection with the connector server. A connector client is usually in a different Java Virtual Machine (Java VM) from the connector server and is often running on a different machine. The JMX API defines a standard connection protocol based on Remote Method Invocation (RMI). This protocol enables you to connect a JMX client to an MBean in an MBean server from a remote location and perform operations on the MBean, exactly as if the operations were being performed locally.

The Java SE platform provides an out-of-the-box means to monitor applications remotely by using the JMX API's standard RMI connector. The out-of-the-box RMI connector automatically exposes applications for remote management, without requiring you to create a dedicated remote connector server yourself. The out-of-the-box remote management agent is activated by starting your Java application with the correct properties. Monitoring and management applications that are compatible with the JMX technology can then connect to these applications and monitor them remotely.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Exposing a Resource for Remote Management By JConsole


Exposing a Resource for Remote Management By JConsole (The Java™ Tutorials > Java Management Extensions (JMX) > Remote Management)

Trail: Java Management Extensions (JMX)
Lesson: Remote Management
Remote Management
Exposing a Resource for Remote Management By JConsole
Creating a Custom JMX Client
Home Page > Java Management Extensions (JMX) > Remote Management
« Previous • Trail • Next »
Exposing a Resource for Remote Management By JConsole

Exposing your Java applications for remote management by using the JMX API can be extremely simple, if you use the out-of-the-box remote management agent and an existing monitoring and management tool such as JConsole.

To expose your application for remote management, you need to start it with the correct properties. This example shows how to expose the Main JMX agent for remote management.

Security consideration: For the sake of simplicity, the authentication and encryption security mechanisms are disabled in this example. However, you should implement these security mechanisms when implementing remote management in real-world environments. What Next? provides pointers to other JMX technology documentation that shows how to activate security.

To monitor the Main JMX agent remotely, follow these steps:

  1. If you have not done so already, save jmx_examples.zip into your work_dir directory.

  2. Unzip the bundle of sample classes by using the following command in a terminal window.

    unzip jmx_examples.zip

  3. Compile the example Java classes from within the work_dir directory.

    javac com/example/*.java

  4. Start the Main application, specifying the properties that expose Main for remote management:

    java -Dcom.sun.management.jmxremote.port=9999 \
    -Dcom.sun.management.jmxremote.authenticate=false \
    -Dcom.sun.management.jmxremote.ssl=false \
    com.example.Main

    A confirmation that Main is waiting for something to happen is generated.

  5. Start JConsole in a different terminal window on a different machine:

    jconsole

    The New Connection dialog box is displayed, presenting a list of running JMX agents that you can connect to locally.

  6. Select Remote Process, and type the following in the Remote Process field:

    hostname:9999

    In this address, hostname is the name of the remote machine on which the Main application is running and 9999 is the number of the port on which the out-of-the-box JMX connector will be connected.

  7. Click Connect.

    A summary of the current activity of the Java Virtual Machine (Java VM) in which Main is running is displayed.

  8. Click the MBeans tab.

    This panel shows all the MBeans that are currently registered in the remote MBean server.

  9. In the left-hand frame, expand the com.example node in the MBean tree.

    You see the example MBean Hello that was created and registered by Main. If you click Hello, you see its associated Attributes and Operations nodes in the MBean tree, even though it is running on a different machine.

  10. To close JConsole, select Connection -> Exit.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Remote Management
Next page: Creating a Custom JMX Client


Creating a Custom JMX Client (The Java™ Tutorials > Java Management Extensions (JMX) > Remote Management)

Trail: Java Management Extensions (JMX)
Lesson: Remote Management
Remote Management
Exposing a Resource for Remote Management By JConsole
Creating a Custom JMX Client
Home Page > Java Management Extensions (JMX) > Remote Management
« Previous • Trail • Next »
Creating a Custom JMX Client
The previous lessons in this trail have shown you how to create JMX technology MBeans and MXBeans, and register them with a JMX agent. However, all the previous examples have used an existing JMX client, JConsole. This lesson will demonstrate how to create your own custom JMX client.

An example of a custom JMX client, Client is included in jmx_examples.zip. This JMX client interacts with the same MBean, MXBean and JMX agent as were seen in the previous lessons. Due to the size of the Client class, it will be examined in chunks, in the following sections.

Importing the JMX Remote API Classes

To be able to create connections to JMX agents that are running remotely from the JMX client, you need to use the classes from the javax.management.remote.

package com.example;

[...]

import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;

public class Client {

    [...]

The Client class will be creating JMXConnector instances, for which it will need a JMXConnectorFactory and a JMXServiceURL.

Creating a Notification Listener

The JMX client needs a notification handler, to listen for and to process any notifications that might be sent by the MBeans that are registered in the JMX agent's MBean server. The JMX client's notification handler is an instance of the NotificationListener interface, as shown below.

    [...]

    public static class ClientListener implements NotificationListener {
        public void handleNotification(Notification notification,
                                       Object handback) {
            echo("\nReceived notification:");
            echo("\tClassName: " + notification.getClass().getName());
            echo("\tSource: " + notification.getSource());
            echo("\tType: " + notification.getType());
            echo("\tMessage: " + notification.getMessage());
            if (notification instanceof AttributeChangeNotification) {
                AttributeChangeNotification acn =
                    (AttributeChangeNotification) notification;
                echo("\tAttributeName: " + acn.getAttributeName());
                echo("\tAttributeType: " + acn.getAttributeType());
                echo("\tNewValue: " + acn.getNewValue());
                echo("\tOldValue: " + acn.getOldValue());
            }
        }
    }

    [...]

This notification listener determines the origin of any notifications it receives, and retrieves the information stored in the notification. It then performs different actions with the notification information according to the type of notification received. In this case, when the listener receives notifications of the type AttributeChangeNotification it will obtain the name and type of the MBean attribute that has changed, as well as its old and new values, by calling the AttributeChangeNotification methods getAttributeName, getAttributeType, getNewValue and getOldValue.

A new ClientListener instance is created by later in the code.

 ClientListener listener = new ClientListener();

Creating an RMI Connector Client

The Client class creates an RMI connector client that is configured to connect to an RMI connector server that you will launch when you start the JMX agent, Main. This will allow the JMX client to interact with the JMX agent as if they were running on the same machine.

    [...]

    public static void main(String[] args) throws Exception {

        echo("\nCreate an RMI connector client and " +
             "connect it to the RMI connector server");
        JMXServiceURL url =
            new JMXServiceURL("service:jmx:rmi:///jndi/rmi://:9999/jmxrmi");
        JMXConnector jmxc = JMXConnectorFactory.connect(url, null);

    [...]

As you can see, the Client defines a JMXServiceURL named url, that represents the location at which the connector client expects to find the connector server. This URL allows the connector client to retrieve the RMI connector server stub jmxrmi from the RMI registry running on port 9999 of the local host, and to connect to the RMI connector server.

With the RMI registry thus identified, the connector client can be created. The connector client, jmxc, is an instance of the interface JMXConnector, created by the connect() method of JMXConnectorFactory. The connect() method is passed the parameters url and a null environment map when it is called.

Connecting to the Remote MBean Server

With the RMI connection in place, the JMX client must connect to the remote MBean server, so that it can interact with the various MBeans registered in it by the remote JMX agent.

        [...]

        MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();

        [...]

An instance of MBeanServerConnection, named mbsc, is then created by calling the getMBeanServerConnection() method of the JMXConnector instance jmxc.

The connector client is now connected to the MBean server created by the JMX agent, and can register MBeans and perform operations on them with the connection remaining completely transparent to both ends.

To start with, the client defines some simple operations to discover information about the MBeans found in the agent's MBean server.

        [...]

        echo("\nDomains:");
        String domains[] = mbsc.getDomains();
        Arrays.sort(domains);
        for (String domain : domains) {
            echo("\tDomain = " + domain);
        }

        [...]

        echo("\nMBeanServer default domain = " + mbsc.getDefaultDomain());

        echo("\nMBean count = " + mbsc.getMBeanCount());
        echo("\nQuery MBeanServer MBeans:");
        Set names =
            new TreeSet(mbsc.queryNames(null, null));
        for (ObjectName name : names) {
            echo("\tObjectName = " + name);
        }

    [...]

The client calls various methods of MBeanServerConnection in order to obtain the domains in which the different MBeans are operating, the number of MBeans registered in the MBean server, and the object names for each of the MBeans it discovers.

Performing Operations on Remote MBeans via Proxies

The client accesses the Hello MBean in the MBean server through the MBean server connection by creating an MBean proxy. This MBean proxy is local to the client, and emulates the remote MBean.

        [...]

        ObjectName mbeanName = new ObjectName("com.example:type=Hello");

        HelloMBean mbeanProxy =
            JMX.newMBeanProxy(mbsc, mbeanName, HelloMBean.class, true);

        echo("\nAdd notification listener...");
    mbsc.addNotificationListener(mbeanName, listener, null, null);

        echo("\nCacheSize = " + mbeanProxy.getCacheSize());

        mbeanProxy.setCacheSize(150);

        echo("\nWaiting for notification...");
        sleep(2000);

        echo("\nCacheSize = " + mbeanProxy.getCacheSize());
        echo("\nInvoke sayHello() in Hello MBean...");
        mbeanProxy.sayHello();

        echo("\nInvoke add(2, 3) in Hello MBean...");
        echo("\nadd(2, 3) = " + mbeanProxy.add(2, 3));

        waitForEnterPressed();

    [...]

MBean proxies allow you to access an MBean through a Java interface, allowing you to make calls on the proxy rather than having to write lengthy code to access a remote MBean. An MBean proxy for Hello is created here by calling the method newMBeanProxy() in the javax.management.JMX class, passing it the MBean's MBeanServerConnection, object name, the class name of the MBean interface and true, to signify that the proxy must behave as a NotificationBroadcaster. The JMX client can now perform the operations defined by Hello as if they were the operations of a locally registered MBean. The JMX client also adds a notification listener and changes the MBean's CacheSize attribute, to make it send a notification.

Performing Operations on Remote MXBeans via Proxies

You can create proxies for MXBeans in exactly the same way as you create MBean proxies.

    [...]

        ObjectName mxbeanName =
            new ObjectName("com.example:type=QueueSampler");
        QueueSamplerMXBean mxbeanProxy =
            JMX.newMXBeanProxy(mbsc, mxbeanName, QueueSamplerMXBean.class);
        QueueSample queue1 = mxbeanProxy.getQueueSample();
        echo("\nQueueSample.Date = " + queue1.getDate());
        echo("QueueSample.Head = " + queue1.getHead());
        echo("QueueSample.Size = " + queue1.getSize());
        echo("\nInvoke clearQueue() in QueueSampler MXBean...");
        mxbeanProxy.clearQueue();

        QueueSample queue2 = mxbeanProxy.getQueueSample();
        echo("\nQueueSample.Date = " + queue2.getDate());
        echo("QueueSample.Head = " + queue2.getHead());
        echo("QueueSample.Size = " + queue2.getSize());

    [...]

As shown above, to create a proxy for an MXBean, all you have to do is call JMX.newMXBeanProxy instead of newMBeanProxy. The MXBean proxy mxbeanProxy allows the client to invoke the QueueSample MXBean's operations as if they were the operations of a locally registered MXBean.

Closing the Connection

Once the JMX client has obtained all the information it needs and performed all the required operations on the MBeans in the remote JMX agent's MBean server, the connection must be closed down.

        jmxc.close();

The connection is closed with a call to the JMXConnector.close method.

To Run the Custom JMX Client Example

To monitor the Main JMX agent remotely using a the custom JMX client Client, follow these steps:

  1. If you have not done so already, save jmx_examples.zip into your work_dir directory.

  2. Unzip the bundle of sample classes by using the following command in a terminal window.

    unzip jmx_examples.zip

  3. Compile the example Java classes from within the work_dir directory.

    javac com/example/*.java

  4. Start the Main application, specifying the properties that expose Main for remote management:

    java -Dcom.sun.management.jmxremote.port=9999 \
    -Dcom.sun.management.jmxremote.authenticate=false \
    -Dcom.sun.management.jmxremote.ssl=false \
    com.example.Main

    A confirmation that Main is waiting for something to happen is generated.

  5. Start the Client application in a different terminal window:

    java com.example.Client

    A confirmation that an MBeanServerConnection has been obtained is displayed.

  6. Press Enter.

    The domains in which all the MBeans that are registered in the MBean server started by Main are displayed.

  7. Press Enter again.

    The number of MBeans that are registered in the MBean server is displayed, as well as the object names of all these MBeans. The MBeans displayed include all the standard platform MXBeans running in the Java VM, as well as the Hello MBean and the QueueSampler MXBean that were registered in the MBean server by Main.

  8. Press Enter again.

    The Hello MBean's operations are invoked by Client, with the following results:

    • A notification listener is added to Client to listen for notifications from Main.
    • The value of the CacheSize attribute is changed from 200 to 150.
    • In the terminal window in which you started Main, confirmation of the CacheSize attribute change is displayed.
    • In the terminal window in which you started Client, a notification from Main is displayed, informing Client of the CacheSize attribute change.
    • The Hello MBean's sayHello operation is invoked.
    • In the terminal window in which you started Main, the message "Hello world" is displayed.
    • The Hello MBean's add operation is invoked, with the values 2 and 3 as parameters. The result is displayed by Client.

  9. Press Enter again.

    The QueueSampler MXBean's operations are invoked by Client, with the following results:

    • The QueueSample values date, head, and size are displayed.
    • The clearQueue operation is invoked.

  10. Press Enter again.

    The Client closes the connection to the MBean server and a confirmation is displayed.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Exposing a Resource for Remote Management By JConsole
Next page: End of Trail


Trail: RMI (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: RMI
The Java Remote Method Invocation (RMI) system allows an object running in one Java virtual machine to invoke methods on an object running in another Java virtual machine. RMI provides for remote communication between programs written in the Java programming language.

Note: If you are connecting to an existing IDL program, you should use Java IDL rather than RMI.
This trail provides a brief overview of the RMI system and then walks through a complete client/server example that uses RMI's unique capabilities to load and to execute user-defined tasks at runtime. The server in the example implements a generic compute engine, which the client uses to compute the value of [image].

An Overview of RMI Applications describes the RMI system and lists its advantages. Additionally, this section provides a description of a typical RMI application, composed of a server and a client, and introduces important terms.

Writing an RMI Server walks through the code for the compute engine server. This section will teach you how to design and to implement an RMI server.

Creating A Client Program takes a look at one possible compute engine client and uses it to illustrate the important features of an RMI client.

Compiling and Running the Example shows you how to compile and to run both the compute engine server and its client.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: An Overview of RMI Applications


An Overview of RMI Applications (The Java™ Tutorials > RMI)

Trail: RMI
An Overview of RMI Applications
Writing an RMI Server
Designing a Remote Interface
Implementing a Remote Interface
Creating a Client Program
Compiling and Running the Example
Compiling the Example Programs
Running the Example Programs
Home Page > RMI
« Previous • Trail • Next »
An Overview of RMI Applications
RMI applications often comprise two separate programs, a server and a client. A typical server program creates some remote objects, makes references to these objects accessible, and waits for clients to invoke methods on these objects. A typical client program obtains a remote reference to one or more remote objects on a server and then invokes methods on them. RMI provides the mechanism by which the server and the client communicate and pass information back and forth. Such an application is sometimes referred to as a distributed object application.

Distributed object applications need to do the following:

  • Locate remote objects. Applications can use various mechanisms to obtain references to remote objects. For example, an application can register its remote objects with RMI's simple naming facility, the RMI registry. Alternatively, an application can pass and return remote object references as part of other remote invocations.
  • Communicate with remote objects. Details of communication between remote objects are handled by RMI. To the programmer, remote communication looks similar to regular Java method invocations.
  • Load class definitions for objects that are passed around. Because RMI enables objects to be passed back and forth, it provides mechanisms for loading an object's class definitions as well as for transmitting an object's data.
The following illustration depicts an RMI distributed application that uses the RMI registry to obtain a reference to a remote object. The server calls the registry to associate (or bind) a name with a remote object. The client looks up the remote object by its name in the server's registry and then invokes a method on it. The illustration also shows that the RMI system uses an existing web server to load class definitions, from server to client and from client to server, for objects when needed.

Advantages of Dynamic Code Loading
One of the central and unique features of RMI is its ability to download the definition of an object's class if the class is not defined in the receiver's Java virtual machine. All of the types and behavior of an object, previously available only in a single Java virtual machine, can be transmitted to another, possibly remote, Java virtual machine. RMI passes objects by their actual classes, so the behavior of the objects is not changed when they are sent to another Java virtual machine. This capability enables new types and behaviors to be introduced into a remote Java virtual machine, thus dynamically extending the behavior of an application. The compute engine example in this trail uses this capability to introduce new behavior to a distributed program.

Remote Interfaces, Objects, and Methods
Like any other Java application, a distributed application built by using Java RMI is made up of interfaces and classes. The interfaces declare methods. The classes implement the methods declared in the interfaces and, perhaps, declare additional methods as well. In a distributed application, some implementations might reside in some Java virtual machines but not others. Objects with methods that can be invoked across Java virtual machines are called remote objects.

An object becomes remote by implementing a remote interface, which has the following characteristics:

  • A remote interface extends the interface java.rmi.Remote.
  • Each method of the interface declares java.rmi.RemoteException in its throws clause, in addition to any application-specific exceptions.

RMI treats a remote object differently from a non-remote object when the object is passed from one Java virtual machine to another Java virtual machine. Rather than making a copy of the implementation object in the receiving Java virtual machine, RMI passes a remote stub for a remote object. The stub acts as the local representative, or proxy, for the remote object and basically is, to the client, the remote reference. The client invokes a method on the local stub, which is responsible for carrying out the method invocation on the remote object.

A stub for a remote object implements the same set of remote interfaces that the remote object implements. This property enables a stub to be cast to any of the interfaces that the remote object implements. However, only those methods defined in a remote interface are available to be called from the receiving Java virtual machine.

Creating Distributed Applications by Using RMI

Using RMI to develop a distributed application involves these general steps:
  1. Designing and implementing the components of your distributed application.
  2. Compiling sources.
  3. Making classes network accessible.
  4. Starting the application.

Designing and Implementing the Application Components

First, determine your application architecture, including which components are local objects and which components are remotely accessible. This step includes:
  • Defining the remote interfaces. A remote interface specifies the methods that can be invoked remotely by a client. Clients program to remote interfaces, not to the implementation classes of those interfaces. The design of such interfaces includes the determination of the types of objects that will be used as the parameters and return values for these methods. If any of these interfaces or classes do not yet exist, you need to define them as well.
  • Implementing the remote objects. Remote objects must implement one or more remote interfaces. The remote object class may include implementations of other interfaces and methods that are available only locally. If any local classes are to be used for parameters or return values of any of these methods, they must be implemented as well.
  • Implementing the clients. Clients that use remote objects can be implemented at any time after the remote interfaces are defined, including after the remote objects have been deployed.

Compiling Sources

As with any Java program, you use the javac compiler to compile the source files. The source files contain the declarations of the remote interfaces, their implementations, any other server classes, and the client classes.
Note: With versions prior to Java Platform, Standard Edition 5.0, an additional step was required to build stub classes, by using the rmic compiler. However, this step is no longer necessary.

Making Classes Network Accessible

In this step, you make certain class definitions network accessible, such as the definitions for the remote interfaces and their associated types, and the definitions for classes that need to be downloaded to the clients or servers. Classes definitions are typically made network accessible through a web server.

Starting the Application

Starting the application includes running the RMI remote object registry, the server, and the client.

The rest of this section walks through the steps used to create a compute engine.

Building a Generic Compute Engine

This trail focuses on a simple, yet powerful, distributed application called a compute engine. The compute engine is a remote object on the server that takes tasks from clients, runs the tasks, and returns any results. The tasks are run on the machine where the server is running. This type of distributed application can enable a number of client machines to make use of a particularly powerful machine or a machine that has specialized hardware.

The novel aspect of the compute engine is that the tasks it runs do not need to be defined when the compute engine is written or started. New kinds of tasks can be created at any time and then given to the compute engine to be run. The only requirement of a task is that its class implement a particular interface. The code needed to accomplish the task can be downloaded by the RMI system to the compute engine. Then, the compute engine runs the task, using the resources on the machine on which the compute engine is running.

The ability to perform arbitrary tasks is enabled by the dynamic nature of the Java platform, which is extended to the network by RMI. RMI dynamically loads the task code into the compute engine's Java virtual machine and runs the task without prior knowledge of the class that implements the task. Such an application, which has the ability to download code dynamically, is often called a behavior-based application. Such applications usually require full agent-enabled infrastructures. With RMI, such applications are part of the basic mechanisms for distributed computing on the Java platform.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: Writing an RMI Server


Writing an RMI Server (The Java™ Tutorials > RMI)

Trail: RMI
An Overview of RMI Applications
Writing an RMI Server
Designing a Remote Interface
Implementing a Remote Interface
Creating a Client Program
Compiling and Running the Example
Compiling the Example Programs
Running the Example Programs
Home Page > RMI
« Previous • Trail • Next »
Writing an RMI Server
The compute engine server accepts tasks from clients, runs the tasks, and returns any results. The server code consists of an interface and a class. The interface defines the methods that can be invoked from the client. Essentially, the interface defines the client's view of the remote object. The class provides the implementation.

Designing a Remote Interface

This section explains the Compute interface, which provides the connection between the client and the server. You will also learn about the RMI API, which supports this communication.

Implementing a Remote Interface

This section explores the class that implements the Compute interface, thereby implementing a remote object. This class also provides the rest of the code that makes up the server program, including a main method that creates an instance of the remote object, registers it with the RMI registry, and sets up a security manager.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: An Overview of RMI Applications
Next page: Designing a Remote Interface


Designing a Remote Interface (The Java™ Tutorials > RMI)

Trail: RMI
Section: Writing an RMI Server
An Overview of RMI Applications
Writing an RMI Server
Designing a Remote Interface
Implementing a Remote Interface
Creating a Client Program
Compiling and Running the Example
Compiling the Example Programs
Running the Example Programs
Home Page > RMI
« Previous • Trail • Next »
Designing a Remote Interface
At the core of the compute engine is a protocol that enables tasks to be submitted to the compute engine, the compute engine to run those tasks, and the results of those tasks to be returned to the client. This protocol is expressed in the interfaces that are supported by the compute engine. The remote communication for this protocol is illustrated in the following figure.

Each interface contains a single method. The compute engine's remote interface, Compute, enables tasks to be submitted to the engine. The client interface, Task, defines how the compute engine executes a submitted task.

The compute.Compute interface defines the remotely accessible part, the compute engine itself. Here is the source code for the Compute interface:

package compute;

import java.rmi.Remote;
import java.rmi.RemoteException;

public interface Compute extends Remote {
    <T> T executeTask(Task<T> t) throws RemoteException;
}

By extending the interface java.rmi.Remote, the Compute interface identifies itself as an interface whose methods can be invoked from another Java virtual machine. Any object that implements this interface can be a remote object.

As a member of a remote interface, the executeTask method is a remote method. Therefore, this method must be defined as being capable of throwing a java.rmi.RemoteException. This exception is thrown by the RMI system from a remote method invocation to indicate that either a communication failure or a protocol error has occurred. A RemoteException is a checked exception, so any code invoking a remote method needs to handle this exception by either catching it or declaring it in its throws clause.

The second interface needed for the compute engine is the Task interface, which is the type of the parameter to the executeTask method in the Compute interface. The compute.Task interface defines the interface between the compute engine and the work that it needs to do, providing the way to start the work. Here is the source code for the Task interface:

package compute;

public interface Task<T> {
    T execute();
}

The Task interface defines a single method, execute, which has no parameters and throws no exceptions. Because the interface does not extend Remote, the method in this interface doesn't need to list java.rmi.RemoteException in its throws clause.

The Task interface has a type parameter, T, which represents the result type of the task's computation. This interface's execute method returns the result of the computation and thus its return type is T.

The Compute interface's executeTask method, in turn, returns the result of the execution of the Task instance passed to it. Thus, the executeTask method has its own type parameter, T, that associates its own return type with the result type of the passed Task instance.

RMI uses the Java object serialization mechanism to transport objects by value between Java virtual machines. For an object to be considered serializable, its class must implement the java.io.Serializable marker interface. Therefore, classes that implement the Task interface must also implement Serializable, as must the classes of objects used for task results.

Different kinds of tasks can be run by a Compute object as long as they are implementations of the Task type. The classes that implement this interface can contain any data needed for the computation of the task and any other methods needed for the computation.

Here is how RMI makes this simple compute engine possible. Because RMI can assume that the Task objects are written in the Java programming language, implementations of the Task object that were previously unknown to the compute engine are downloaded by RMI into the compute engine's Java virtual machine as needed. This capability enables clients of the compute engine to define new kinds of tasks to be run on the server machine without needing the code to be explicitly installed on that machine.

The compute engine, implemented by the ComputeEngine class, implements the Compute interface, enabling different tasks to be submitted to it by calls to its executeTask method. These tasks are run using the task's implementation of the execute method and the results, are returned to the remote client.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Writing an RMI Server
Next page: Implementing a Remote Interface


Implementing a Remote Interface (The Java™ Tutorials > RMI)

Trail: RMI
Section: Writing an RMI Server
An Overview of RMI Applications
Writing an RMI Server
Designing a Remote Interface
Implementing a Remote Interface
Creating a Client Program
Compiling and Running the Example
Compiling the Example Programs
Running the Example Programs
Home Page > RMI
« Previous • Trail • Next »
Implementing a Remote Interface
This section discusses the task of implementing a class for the compute engine. In general, a class that implements a remote interface should at least do the following:
  • Declare the remote interfaces being implemented
  • Define the constructor for each remote object
  • Provide an implementation for each remote method in the remote interfaces

An RMI server program needs to create the initial remote objects and export them to the RMI runtime, which makes them available to receive incoming remote invocations. This setup procedure can be either encapsulated in a method of the remote object implementation class itself or included in another class entirely. The setup procedure should do the following:

  • Create and install a security manager
  • Create and export one or more remote objects
  • Register at least one remote object with the RMI registry (or with another naming service, such as a service accessible through the Java Naming and Directory Interface) for bootstrapping purposes

The complete implementation of the compute engine follows. The engine.ComputeEngine class implements the remote interface Compute and also includes the main method for setting up the compute engine. Here is the source code for the ComputeEngine class:

package engine;

import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import compute.Compute;
import compute.Task;

public class ComputeEngine implements Compute {

    public ComputeEngine() {
        super();
    }

    public <T> T executeTask(Task<T> t) {
        return t.execute();
    }

    public static void main(String[] args) {
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
        try {
            String name = "Compute";
            Compute engine = new ComputeEngine();
            Compute stub =
                (Compute) UnicastRemoteObject.exportObject(engine, 0);
            Registry registry = LocateRegistry.getRegistry();
            registry.rebind(name, stub);
            System.out.println("ComputeEngine bound");
        } catch (Exception e) {
            System.err.println("ComputeEngine exception:");
            e.printStackTrace();
        }
    }
}

The following sections discuss each component of the compute engine implementation.

Declaring the Remote Interfaces Being Implemented

The implementation class for the compute engine is declared as follows:
public class ComputeEngine implements Compute

This declaration states that the class implements the Compute remote interface and therefore can be used for a remote object.

The ComputeEngine class defines a remote object implementation class that implements a single remote interface and no other interfaces. The ComputeEngine class also contains two executable program elements that can only be invoked locally. The first of these elements is a constructor for ComputeEngine instances. The second of these elements is a main method that is used to create a ComputeEngine instance and make it available to clients.

Defining the Constructor for the Remote Object

The ComputeEngine class has a single constructor that takes no arguments. The code for the constructor is as follows:
public ComputeEngine() {
    super();
}
This constructor just invokes the superclass constructor, which is the no-argument constructor of the Object class. Although the superclass constructor gets invoked even if omitted from the ComputeEngine constructor, it is included for clarity.

Providing Implementations for Each Remote Method

The class for a remote object provides implementations for each remote method specified in the remote interfaces. The Compute interface contains a single remote method, executeTask, which is implemented as follows:
public <T> T executeTask(Task<T> t) {
    return t.execute();
}

This method implements the protocol between the ComputeEngine remote object and its clients. Each client provides the ComputeEngine with a Task object that has a particular implementation of the Task interface's execute method. The ComputeEngine executes each client's task and returns the result of the task's execute method directly to the client.

Passing Objects in RMI

Arguments to or return values from remote methods can be of almost any type, including local objects, remote objects, and primitive data types. More precisely, any entity of any type can be passed to or from a remote method as long as the entity is an instance of a type that is a primitive data type, a remote object, or a serializable object, which means that it implements the interface java.io.Serializable.

Some object types do not meet any of these criteria and thus cannot be passed to or returned from a remote method. Most of these objects, such as threads or file descriptors, encapsulate information that makes sense only within a single address space. Many of the core classes, including the classes in the packages java.lang and java.util, implement the Serializable interface.

The rules governing how arguments and return values are passed are as follows:

  • Remote objects are essentially passed by reference. A remote object reference is a stub, which is a client-side proxy that implements the complete set of remote interfaces that the remote object implements.
  • Local objects are passed by copy, using object serialization. By default, all fields are copied except fields that are marked static or transient. Default serialization behavior can be overridden on a class-by-class basis.

Passing a remote object by reference means that any changes made to the state of the object by remote method invocations are reflected in the original remote object. When a remote object is passed, only those interfaces that are remote interfaces are available to the receiver. Any methods defined in the implementation class or defined in non-remote interfaces implemented by the class are not available to that receiver.

For example, if you were to pass a reference to an instance of the ComputeEngine class, the receiver would have access only to the compute engine's executeTask method. That receiver would not see the ComputeEngine constructor, its main method, or its implementation of any methods of java.lang.Object.

In the parameters and return values of remote method invocations, objects that are not remote objects are passed by value. Thus, a copy of the object is created in the receiving Java virtual machine. Any changes to the object's state by the receiver are reflected only in the receiver's copy, not in the sender's original instance. Any changes to the object's state by the sender are reflected only in the sender's original instance, not in the receiver's copy.

Implementing the Server's main Method

The most complex method of the ComputeEngine implementation is the main method. The main method is used to start the ComputeEngine and therefore needs to do the necessary initialization and housekeeping to prepare the server to accept calls from clients. This method is not a remote method, which means that it cannot be invoked from a different Java virtual machine. Because the main method is declared static, the method is not associated with an object at all but rather with the class ComputeEngine.

Creating and Installing a Security Manager

The main method's first task is to create and install a security manager, which protects access to system resources from untrusted downloaded code running within the Java virtual machine. A security manager determines whether downloaded code has access to the local file system or can perform any other privileged operations.

If an RMI program does not install a security manager, RMI will not download classes (other than from the local class path) for objects received as arguments or return values of remote method invocations. This restriction ensures that the operations performed by downloaded code are subject to a security policy.

Here's the code that creates and installs a security manager:

if (System.getSecurityManager() == null) {
    System.setSecurityManager(new SecurityManager());
}

Making the Remote Object Available to Clients

Next, the main method creates an instance of ComputeEngine and exports it to the RMI runtime with the following statements:
Compute engine = new ComputeEngine();
Compute stub =
    (Compute) UnicastRemoteObject.exportObject(engine, 0);

The static UnicastRemoteObject.exportObject method exports the supplied remote object so that it can receive invocations of its remote methods from remote clients. The second argument, an int, specifies which TCP port to use to listen for incoming remote invocation requests for the object. It is common to use the value zero, which specifies the use of an anonymous port. The actual port will then be chosen at runtime by RMI or the underlying operating system. However, a non-zero value can also be used to specify a specific port to use for listening. Once the exportObject invocation has returned successfully, the ComputeEngine remote object is ready to process incoming remote invocations.

The exportObject method returns a stub for the exported remote object. Note that the type of the variable stub must be Compute, not ComputeEngine, because the stub for a remote object only implements the remote interfaces that the exported remote object implements.

The exportObject method declares that it can throw a RemoteException, which is a checked exception type. The main method handles this exception with its try/catch block. If the exception were not handled in this way, RemoteException would have to be declared in the throws clause of the main method. An attempt to export a remote object can throw a RemoteException if the necessary communication resources are not available, such as if the requested port is bound for some other purpose.

Before a client can invoke a method on a remote object, it must first obtain a reference to the remote object. Obtaining a reference can be done in the same way that any other object reference is obtained in a program, such as by getting the reference as part of the return value of a method or as part of a data structure that contains such a reference.

The system provides a particular type of remote object, the RMI registry, for finding references to other remote objects. The RMI registry is a simple remote object naming service that enables clients to obtain a reference to a remote object by name. The registry is typically only used to locate the first remote object that an RMI client needs to use. That first remote object might then provide support for finding other objects.

The java.rmi.registry.Registry remote interface is the API for binding (or registering) and looking up remote objects in the registry. The java.rmi.registry.LocateRegistry class provides static methods for synthesizing a remote reference to a registry at a particular network address (host and port). These methods create the remote reference object containing the specified network address without performing any remote communication. LocateRegistry also provides static methods for creating a new registry in the current Java virtual machine, although this example does not use those methods. Once a remote object is registered with an RMI registry on the local host, clients on any host can look up the remote object by name, obtain its reference, and then invoke remote methods on the object. The registry can be shared by all servers running on a host, or an individual server process can create and use its own registry.

The ComputeEngine class creates a name for the object with the following statement:

String name = "Compute";

The code then adds the name to the RMI registry running on the server. This step is done later with the following statements:

Registry registry = LocateRegistry.getRegistry();
registry.rebind(name, stub);

This rebind invocation makes a remote call to the RMI registry on the local host. Like any remote call, this call can result in a RemoteException being thrown, which is handled by the catch block at the end of the main method.

Note the following about the Registry.rebind invocation:

  • The no-argument overload of LocateRegistry.getRegistry synthesizes a reference to a registry on the local host and on the default registry port, 1099. You must use an overload that has an int parameter if the registry is created on a port other than 1099.
  • When a remote invocation on the registry is made, a stub for the remote object is passed instead of a copy of the remote object itself. Remote implementation objects, such as instances of ComputeEngine, never leave the Java virtual machine in which they were created. Thus, when a client performs a lookup in a server's remote object registry, a copy of the stub is returned. Remote objects in such cases are thus effectively passed by (remote) reference rather than by value.
  • For security reasons, an application can only bind, unbind, or rebind remote object references with a registry running on the same host. This restriction prevents a remote client from removing or overwriting any of the entries in a server's registry. A lookup, however, can be requested from any host, local or remote.

Once the server has registered with the local RMI registry, it prints a message indicating that it is ready to start handling calls. Then, the main method completes. It is not necessary to have a thread wait to keep the server alive. As long as there is a reference to the ComputeEngine object in another Java virtual machine, local or remote, the ComputeEngine object will not be shut down or garbage collected. Because the program binds a reference to the ComputeEngine in the registry, it is reachable from a remote client, the registry itself. The RMI system keeps the ComputeEngine's process running. The ComputeEngine is available to accept calls and won't be reclaimed until its binding is removed from the registry and no remote clients hold a remote reference to the ComputeEngine object.

The final piece of code in the ComputeEngine.main method handles any exception that might arise. The only checked exception type that could be thrown in the code is RemoteException, either by the UnicastRemoteObject.exportObject invocation or by the registry rebind invocation. In either case, the program cannot do much more than exit after printing an error message. In some distributed applications, recovering from the failure to make a remote invocation is possible. For example, the application could attempt to retry the operation or choose another server to continue the operation.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Designing a Remote Interface
Next page: Creating a Client Program


Creating a Client Program (The Java™ Tutorials > RMI)

Trail: RMI
An Overview of RMI Applications
Writing an RMI Server
Designing a Remote Interface
Implementing a Remote Interface
Creating a Client Program
Compiling and Running the Example
Compiling the Example Programs
Running the Example Programs
Home Page > RMI
« Previous • Trail • Next »
Creating a Client Program
The compute engine is a relatively simple program: it runs tasks that are handed to it. The clients for the compute engine are more complex. A client needs to call the compute engine, but it also has to define the task to be performed by the compute engine.

Two separate classes make up the client in our example. The first class, ComputePi, looks up and invokes a Compute object. The second class, Pi, implements the Task interface and defines the work to be done by the compute engine. The job of the Pi class is to compute the value of [image] to some number of decimal places.

The non-remote Task interface is defined as follows:

package compute;

public interface Task<T> {
    T execute();
}

The code that invokes a Compute object's methods must obtain a reference to that object, create a Task object, and then request that the task be executed. The definition of the task class Pi is shown later. A Pi object is constructed with a single argument, the desired precision of the result. The result of the task execution is a java.math.BigDecimal representing [image] calculated to the specified precision.

Here is the source code for client.ComputePi, the main client class:

package client;

import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.math.BigDecimal;
import compute.Compute;

public class ComputePi {
    public static void main(String args[]) {
        if (System.getSecurityManager() == null) {
            System.setSecurityManager(new SecurityManager());
        }
        try {
            String name = "Compute";
            Registry registry = LocateRegistry.getRegistry(args[0]);
            Compute comp = (Compute) registry.lookup(name);
            Pi task = new Pi(Integer.parseInt(args[1]));
            BigDecimal pi = comp.executeTask(task);
            System.out.println(pi);
        } catch (Exception e) {
            System.err.println("ComputePi exception:");
            e.printStackTrace();
        }
    }
}

Like the ComputeEngine server, the client begins by installing a security manager. This step is necessary because the process of receiving the server remote object's stub could require downloading class definitions from the server. For RMI to download classes, a security manager must be in force.

After installing a security manager, the client constructs a name to use to look up a Compute remote object, using the same name used by ComputeEngine to bind its remote object. Also, the client uses the LocateRegistry.getRegistry API to synthesize a remote reference to the registry on the server's host. The value of the first command-line argument, args[0], is the name of the remote host on which the Compute object runs. The client then invokes the lookup method on the registry to look up the remote object by name in the server host's registry. The particular overload of LocateRegistry.getRegistry used, which has a single String parameter, returns a reference to a registry at the named host and the default registry port, 1099. You must use an overload that has an int parameter if the registry is created on a port other than 1099.

Next, the client creates a new Pi object, passing to the Pi constructor the value of the second command-line argument, args[1], parsed as an integer. This argument indicates the number of decimal places to use in the calculation. Finally, the client invokes the executeTask method of the Compute remote object. The object passed into the executeTask invocation returns an object of type BigDecimal, which the program stores in the variable result. Finally, the program prints the result. The following figure depicts the flow of messages among the ComputePi client, the rmiregistry, and the ComputeEngine.

The Pi class implements the Task interface and computes the value of [image] to a specified number of decimal places. For this example, the actual algorithm is unimportant. What is important is that the algorithm is computationally expensive, meaning that you would want to have it executed on a capable server.

Here is the source code for client.Pi, the class that implements the Task interface:

package client;

import compute.Task;
import java.io.Serializable;
import java.math.BigDecimal;

public class Pi implements Task<BigDecimal>, Serializable {

    private static final long serialVersionUID = 227L;

    /** constants used in pi computation */
    private static final BigDecimal FOUR =
        BigDecimal.valueOf(4);

    /** rounding mode to use during pi computation */
    private static final int roundingMode =
        BigDecimal.ROUND_HALF_EVEN;

    /** digits of precision after the decimal point */
    private final int digits;

    /**
     * Construct a task to calculate pi to the specified
     * precision.
     */
    public Pi(int digits) {
        this.digits = digits;
    }

    /**
     * Calculate pi.
     */
    public BigDecimal execute() {
        return computePi(digits);
    }

    /**
     * Compute the value of pi to the specified number of
     * digits after the decimal point.  The value is
     * computed using Machin's formula:
     *
     *          pi/4 = 4*arctan(1/5) - arctan(1/239)
     *
     * and a power series expansion of arctan(x) to
     * sufficient precision.
     */
    public static BigDecimal computePi(int digits) {
        int scale = digits + 5;
        BigDecimal arctan1_5 = arctan(5, scale);
        BigDecimal arctan1_239 = arctan(239, scale);
        BigDecimal pi = arctan1_5.multiply(FOUR).subtract(
                                  arctan1_239).multiply(FOUR);
        return pi.setScale(digits,
                           BigDecimal.ROUND_HALF_UP);
    }
    /**
     * Compute the value, in radians, of the arctangent of
     * the inverse of the supplied integer to the specified
     * number of digits after the decimal point.  The value
     * is computed using the power series expansion for the
     * arc tangent:
     *
     * arctan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 +
     *     (x^9)/9 ...
     */
    public static BigDecimal arctan(int inverseX,
                                    int scale)
    {
        BigDecimal result, numer, term;
        BigDecimal invX = BigDecimal.valueOf(inverseX);
        BigDecimal invX2 =
            BigDecimal.valueOf(inverseX * inverseX);

        numer = BigDecimal.ONE.divide(invX,
                                      scale, roundingMode);

        result = numer;
        int i = 1;
        do {
            numer =
                numer.divide(invX2, scale, roundingMode);
            int denom = 2 * i + 1;
            term =
                numer.divide(BigDecimal.valueOf(denom),
                             scale, roundingMode);
            if ((i % 2) != 0) {
                result = result.subtract(term);
            } else {
                result = result.add(term);
            }
            i++;
        } while (term.compareTo(BigDecimal.ZERO) != 0);
        return result;
    }
}

Note that all serializable classes, whether they implement the Serializable interface directly or indirectly, must declare a private static final field named serialVersionUID to guarantee serialization compatibility between versions. If no previous version of the class has been released, then the value of this field can be any long value, similar to the 227L used by Pi, as long as the value is used consistently in future versions. If a previous version of the class has been released without an explicit serialVersionUID declaration, but serialization compatibility with that version is important, then the default implicitly computed value for the previous version must be used for the value of the new version's explicit declaration. The serialver tool can be run against the previous version to determine the default computed value for it.

The most interesting feature of this example is that the Compute implementation object never needs the Pi class's definition until a Pi object is passed in as an argument to the executeTask method. At that point, the code for the class is loaded by RMI into the Compute object's Java virtual machine, the execute method is invoked, and the task's code is executed. The result, which in the case of the Pi task is a BigDecimal object, is handed back to the calling client, where it is used to print the result of the computation.

The fact that the supplied Task object computes the value of Pi is irrelevant to the ComputeEngine object. You could also implement a task that, for example, generates a random prime number by using a probabilistic algorithm. That task would also be computationally intensive and therefore a good candidate for passing to the ComputeEngine, but it would require very different code. This code could also be downloaded when the Task object is passed to a Compute object. In just the way that the algorithm for computing [image] is brought in when needed, the code that generates the random prime number would be brought in when needed. The Compute object knows only that each object it receives implements the execute method. The Compute object does not know, and does not need to know, what the implementation does.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Implementing a Remote Interface
Next page: Compiling and Running the Example


Compiling and Running the Example (The Java™ Tutorials > RMI)

Trail: RMI
An Overview of RMI Applications
Writing an RMI Server
Designing a Remote Interface
Implementing a Remote Interface
Creating a Client Program
Compiling and Running the Example
Compiling the Example Programs
Running the Example Programs
Home Page > RMI
« Previous • Trail • Next »
Compiling and Running the Example
Now that the code for the compute engine example has been written, it needs to be compiled and run.

Compiling the Example Programs

In this section, you learn how to compile the server and the client programs that make up the compute engine example.

Running the Example Programs

Finally, you run the server and client programs and consequently compute the value of [image].
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating a Client Program
Next page: Compiling the Example Programs


Compiling the Example Programs (The Java™ Tutorials > RMI)

Trail: RMI
Section: Compiling and Running the Example
An Overview of RMI Applications
Writing an RMI Server
Designing a Remote Interface
Implementing a Remote Interface
Creating a Client Program
Compiling and Running the Example
Compiling the Example Programs
Running the Example Programs
Home Page > RMI
« Previous • Trail • Next »
Compiling the Example Programs
In a real-world scenario in which a service such as the compute engine is deployed, a developer would likely create a Java Archive (JAR) file that contains the Compute and Task interfaces for server classes to implement and client programs to use. Next, a developer, perhaps the same developer of the interface JAR file, would write an implementation of the Compute interface and deploy that service on a machine available to clients. Developers of client programs can use the Compute and the Task interfaces, contained in the JAR file, and independently develop a task and client program that uses a Compute service.

In this section, you learn how to set up the JAR file, server classes, and client classes. You will see that the client's Pi class will be downloaded to the server at runtime. Also, the Compute and Task interfaces will be downloaded from the server to the registry at runtime.

This example separates the interfaces, remote object implementation, and client code into three packages:

  • compute – Compute and Task interfaces
  • engine – ComputeEngine implementation class
  • client – ComputePi client code and Pi task implementation

First, you need to build the interface JAR file to provide to server and client developers.

Building a JAR File of Interface Classes

First, you need to compile the interface source files in the compute package and then build a JAR file that contains their class files. Assume that user waldo has written these interfaces and placed the source files in the directory c:\home\waldo\src\compute on Windows or the directory /home/waldo/src/compute on Solaris OS or Linux. Given these paths, you can use the following commands to compile the interfaces and create the JAR file:

Microsoft Windows:
cd c:\home\waldo\src
javac compute\Compute.java compute\Task.java
jar cvf compute.jar compute\*.class

Solaris OS or Linux:
cd /home/waldo/src
javac compute/Compute.java compute/Task.java
jar cvf compute.jar compute/*.class

The jar command displays the following output due to the -v option:

added manifest
adding: compute/Compute.class(in = 307) (out= 201)(deflated 34%)
adding: compute/Task.class(in = 217) (out= 149)(deflated 31%)

Now, you can distribute the compute.jar file to developers of server and client applications so that they can make use of the interfaces.

After you build either server-side or client-side classes with the javac compiler, if any of those classes will need to be dynamically downloaded by other Java virtual machines, you must ensure that their class files are placed in a network-accessible location. In this example, for Solaris OS or Linux this location is /home/user/public_html/classes because many web servers allow the accessing of a user's public_html directory through an HTTP URL constructed as http://host/~user/. If your web server does not support this convention, you could use a different location in the web server's hierarchy, or you could use a file URL instead. The file URLs take the form file:/home/user/public_html/classes/ on Solaris OS or Linux and the form file:/c:/home/user/public_html/classes/ on Windows. You may also select another type of URL, as appropriate.

The network accessibility of the class files enables the RMI runtime to download code when needed. Rather than defining its own protocol for code downloading, RMI uses URL protocols supported by the Java platform (for example, HTTP) to download code. Note that using a full, heavyweight web server to serve these class files is unnecessary. For example, a simple HTTP server that provides the functionality needed to make classes available for downloading in RMI through HTTP can be found at http://java.sun.com/javase/technologies/core/basic/rmi/class-server.zip.

Building the Server Classes

The engine package contains only one server-side implementation class, ComputeEngine, the implementation of the remote interface Compute.

Assume that user ann, the developer of the ComputeEngine class, has placed ComputeEngine.java in the directory c:\home\ann\src\engine on Windows or the directory /home/ann/src/engine on Solaris OS or Linux. She is deploying the class files for clients to download in a subdirectory of her public_html directory, c:\home\ann\public_html\classes on Windows or /home/ann/public_html/classes on Solaris OS or Linux. This location is accessible through some web servers as http://host:port/~ann/classes/.

The ComputeEngine class depends on the Compute and Task interfaces, which are contained in the compute.jar JAR file. Therefore, you need the compute.jar file in your class path when you build the server classes. Assume that the compute.jar file is located in the directory c:\home\ann\public_html\classes on Windows or the directory /home/ann/public_html/classes on Solaris OS or Linux. Given these paths, you can use the following commands to build the server classes:

Microsoft Windows:
cd c:\home\ann\src
javac -cp c:\home\ann\public_html\classes\compute.jar
    engine\ComputeEngine.java

Solaris OS or Linux:
cd /home/ann/src
javac -cp /home/ann/public_html/classes/compute.jar
    engine/ComputeEngine.java

The stub class for ComputeEngine implements the Compute interface, which refers to the Task interface. So, the class definitions for those two interfaces need to be network-accessible for the stub to be received by other Java virtual machines such as the registry's Java virtual machine. The client Java virtual machine will already have these interfaces in its class path, so it does not actually need to download their definitions. The compute.jar file under the public_html directory can serve this purpose.

Now, the compute engine is ready to deploy. You could do that now, or you could wait until after you have built the client.

Building the Client Classes

The client package contains two classes, ComputePi, the main client program, and Pi, the client's implementation of the Task interface.

Assume that user jones, the developer of the client classes, has placed ComputePi.java and Pi.java in the directory c:\home\jones\src\client on Windows or the directory /home/jones/src/client on Solaris OS or Linux. He is deploying the class files for the compute engine to download in a subdirectory of his public_html directory, c:\home\jones\public_html\classes on Windows or /home/jones/public_html/classes on Solaris OS or Linux. This location is accessible through some web servers as http://host:port/~jones/classes/.

The client classes depend on the Compute and Task interfaces, which are contained in the compute.jar JAR file. Therefore, you need the compute.jar file in your class path when you build the client classes. Assume that the compute.jar file is located in the directory c:\home\jones\public_html\classes on Windows or the directory /home/jones/public_html/classes on Solaris OS or Linux. Given these paths, you can use the following commands to build the client classes:

Microsoft Windows:
cd c:\home\jones\src
javac -cp c:\home\jones\public_html\classes\compute.jar
    client\ComputePi.java client\Pi.java
mkdir c:\home\jones\public_html\classes\client
cp client\Pi.class
    c:\home\jones\public_html\classes\client

Solaris OS or Linux:
cd /home/jones/src
javac -cp /home/jones/public_html/classes/compute.jar
    client/ComputePi.java client/Pi.java
mkdir /home/jones/public_html/classes/client
cp client/Pi.class
    /home/jones/public_html/classes/client

Only the Pi class needs to be placed in the directory public_html\classes\client because only the Pi class needs to be available for downloading to the compute engine's Java virtual machine. Now, you can run the server and then the client.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Compiling and Running the Example
Next page: Running the Example Programs


Running the Example Programs (The Java™ Tutorials > RMI)

Trail: RMI
Section: Compiling and Running the Example
An Overview of RMI Applications
Writing an RMI Server
Designing a Remote Interface
Implementing a Remote Interface
Creating a Client Program
Compiling and Running the Example
Compiling the Example Programs
Running the Example Programs
Home Page > RMI
« Previous • Trail • Next »
Running the Example Programs

A Note About Security

The server and client programs run with a security manager installed. When you run either program, you need to specify a security policy file so that the code is granted the security permissions it needs to run. Here is an example policy file to use with the server program:
grant codeBase "file:/home/ann/src/" {
    permission java.security.AllPermission;
};

Here is an example policy file to use with the client program:

grant codeBase "file:/home/jones/src/" {
    permission java.security.AllPermission;
};

For both example policy files, all permissions are granted to the classes in the program's local class path, because the local application code is trusted, but no permissions are granted to code downloaded from other locations. Therefore, the compute engine server restricts the tasks that it executes (whose code is not known to be trusted and might be hostile) from performing any operations that require security permissions. The example client's Pi task does not require any permissions to execute.

In this example, the policy file for the server program is named server.policy, and the policy file for the client program is named client.policy.

Starting the Server

Before starting the compute engine, you need to start the RMI registry. The RMI registry is a simple server-side bootstrap naming facility that enables remote clients to obtain a reference to an initial remote object. It can be started with the rmiregistry command. Before you execute rmiregistry, you must make sure that the shell or window in which you will run rmiregistry either has no CLASSPATH environment variable set or has a CLASSPATH environment variable that does not include the path to any classes that you want downloaded to clients of your remote objects.

To start the registry on the server, execute the rmiregistry command. This command produces no output and is typically run in the background. For this example, the registry is started on the host zaphod.

Microsoft Windows (use javaw if start is not available):
start rmiregistry

Solaris OS or Linux:
rmiregistry &

By default, the registry runs on port 1099. To start the registry on a different port, specify the port number on the command line. Do not forget to unset your CLASSPATH environment variable.

Microsoft Windows:
start rmiregistry 2001

Solaris OS or Linux:
rmiregistry 2001 &

Once the registry is started, you can start the server. You need to make sure that both the compute.jar file and the remote object implementation class are in your class path. When you start the compute engine, you need to specify, using the java.rmi.server.codebase property, where the server's classes are network accessible. In this example, the server-side classes to be made available for downloading are the Compute and Task interfaces, which are available in the compute.jar file in the public_html\classes directory of user ann. The compute engine server is started on the host zaphod, the same host on which the registry was started.

Microsoft Windows:
java -cp c:\home\ann\src;c:\home\ann\public_html\classes\compute.jar
     -Djava.rmi.server.codebase=file:/c:/home/ann/public_html/classes/compute.jar
     -Djava.rmi.server.hostname=zaphod.east.sun.com
     -Djava.security.policy=server.policy
        engine.ComputeEngine

Solaris OS or Linux:
java -cp /home/ann/src:/home/ann/public_html/classes/compute.jar
     -Djava.rmi.server.codebase=http://zaphod/~ann/classes/compute.jar
     -Djava.rmi.server.hostname=zaphod.east.sun.com
     -Djava.security.policy=server.policy
        engine.ComputeEngine

The above java command defines the following system properties:

  • The java.rmi.server.codebase property specifies the location, a codebase URL, from which the definitions for classes originating from this server can be downloaded. If the codebase specifies a directory hierarchy (as opposed to a JAR file), you must include a trailing slash at the end of the codebase URL.
  • The java.rmi.server.hostname property specifies the host name or address to put in the stubs for remote objects exported in this Java virtual machine. This value is the host name or address used by clients when they attempt to communicate remote method invocations. By default, the RMI implementation uses the server's IP address as indicated by the java.net.InetAddress.getLocalHost API. However, sometimes, this address is not appropriate for all clients and a fully qualified host name would be more effective. To ensure that RMI uses a host name (or IP address) for the server that is routable from all potential clients, set the java.rmi.server.hostname property.
  • The java.security.policy property is used to specify the policy file that contains the permissions you intend to grant.

Starting the Client

Once the registry and the compute engine are running, you can start the client, specifying the following:
  • The location where the client serves its classes (the Pi class) by using the java.rmi.server.codebase property
  • The java.security.policy property, which is used to specify the security policy file that contains the permissions you intend to grant to various pieces of code
  • As command-line arguments, the host name of the server (so that the client knows where to locate the Compute remote object) and the number of decimal places to use in the [image] calculation

Start the client on another host (a host named ford, for example) as follows:

Microsoft Windows:
java -cp c:\home\jones\src;c:\home\jones\public_html\classes\compute.jar
     -Djava.rmi.server.codebase=file:/c:/home/jones/public_html/classes/
     -Djava.security.policy=client.policy
    client.ComputePi zaphod.east.sun.com 45

Solaris OS or Linux:
java -cp /home/jones/src:/home/jones/public_html/classes/compute.jar
     -Djava.rmi.server.codebase=http://ford/~jones/classes/
     -Djava.security.policy=client.policy
        client.ComputePi zaphod.east.sun.com 45

Note that the class path is set on the command line so that the interpreter can find the client classes and the JAR file containing the interfaces. Also note that the value of the java.rmi.server.codebase property, which specifies a directory hierarchy, ends with a trailing slash.

After you start the client, the following output is displayed:

3.141592653589793238462643383279502884197169399

The following figure illustrates where the rmiregistry, the ComputeEngine server, and the ComputePi client obtain classes during program execution.

When the ComputeEngine server binds its remote object reference in the registry, the registry downloads the Compute and Task interfaces on which the stub class depends. These classes are downloaded from either the ComputeEngine server's web server or file system, depending on the type of codebase URL used when starting the server.

Because the ComputePi client has both the Compute and the Task interfaces available in its class path, it loads their definitions from its class path, not from the server's codebase.

Finally, the Pi class is loaded into the ComputeEngine server's Java virtual machine when the Pi object is passed in the executeTask remote call to the ComputeEngine object. The Pi class is loaded by the server from either the client's web server or file system, depending on the type of codebase URL used when starting the client.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Compiling the Example Programs
Next page: End of Trail


Trail: Security Features in Java SE (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Security Features in Java SE
In this trail you'll learn how the built-in Java™ security features protect you from malevolent programs. You'll see how to use tools to control access to resources, to generate and to check digital signatures, and to create and to manage keys needed for signature generation and checking. You'll also see how to incorporate cryptography services, such as digital signature generation and checking, into your programs.

The security features provided by the Java Development Kit (JDK™) are intended for a variety of audiences:

  • Users running programs:

    Built-in security functionality protects you from malevolent programs (including viruses), maintains the privacy of your files and information about you, and authenticates the identity of each code provider. You can subject applications and applets to security controls when you need to.

  • Developers:

    You can use API methods to incorporate security functionality into your programs, including cryptography services and security checks. The API framework enables you to define and integrate your own permissions (controlling access to specific resources), cryptography service implementations, security manager implementations, and policy implementations. In addition, classes are provided for management of your public/private key pairs and public key certificates from people you trust.

  • Systems administrators, developers, and users:
    JDK tools manage your keystore (database of keys and certificates); generate digital signatures for JAR files, and verify the authenticity of such signatures and the integrity of the signed contents; and create and modify the policy files that define your installation's security policy.

Trail Lessons

Quick Tour of Controlling Applets shows how resource accesses, such as reading or writing a file, are not permitted for unsigned applets unless explicitly allowed by a permission in a policy file.

Quick Tour of Controlling Applications builds on the previous lesson, showing that when applications are run under a security manager, resource accesses may be controlled in exactly the same way as for unsigned applets.

API and Tools Use for Secure Code and File Exchanges defines digital signatures, certificates, and keystores and discusses why they are needed. It also reviews information applicable to the next three lessons regarding the steps commonly needed for using the tools or the API to generate signatures, export/import certificates, and so on.

Signing Code and Granting It Permissions illustrates the use of all the security-related tools. It shows the steps that a developer would take to sign and to distribute code for others to run. The lesson also shows how someone who will run the code (or a system administrator) could add an entry in a policy file to grant the code permission for the resource accesses it needs.

Exchanging Files shows use of the tools by one person to sign an important document, such as a contract, and to export the public key certificate for the public key corresponding to the private key used to sign the contract. Then the lesson shows how another person, who receives the contract, the signature, and the public key certificate, can import the certificate and verify the signature.

Generating and Verifying Signatures walks you step by step through an example of writing a Java program using the JDK Security API to generate keys, to generate a digital signature for data using the private key, and to export the public key and the signature to files. Then the example shows writing a second program, which may be expected to run on a different person's computer, that imports the public key and verifies the authenticity of the signature. Finally, the example discusses potential weaknesses of the approach used by the basic programs and demonstrates possible alternative approaches and methods of supplying and importing keys, including in certificates.

Implementing Your Own Permission demonstrates how to write a class that defines its own special permission.

For More Information

JDK security release documentation can be found at http://java.sun.com/javase/6/docs/technotes/guides/security/index.html . This index page lists Specifications which present detailed information about latest security features, including architecture specifications, usage guides, API documentation, and tool documentation. .

Information on use of the Java Plug-in to download the latest Java Runtime Environment compatible with JDK 6 can be found here: http://java.sun.com/products/plugin/index.html .

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Security Features Overview


Lesson: Security Features Overview (The Java™ Tutorials > Security Features in Java SE)

Trail: Security Features in Java SE
Home Page > Security Features in Java SE
« Previous • Trail • Next »
Lesson: Security Features Overview

Security functions help you to protect your programs and data from harm, to keep data shielded and private, and to deploy new applications in security-aware runtime environments.

Java also provides several tools to help you to manage access to system resources; to create, store and maintain encrypted public and private passwords (key pairs) and certificates; and to create and sign jarfiles during the deployment process.

Note: For a brief overview of security features supported in Java SE 6, see the Security Overview Whitepaper in the Security Guides directory.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: Quick Tour of Controlling Applets


Lesson: Quick Tour of Controlling Applets (The Java™ Tutorials > Security Features in Java SE)

Quick Tour of Controlling Applets
Observe Applet Restrictions
Set up a Policy File to Grant the Required Permission
Start Policy Tool
Grant the Required Permission
Save the Policy File
See the Policy File Effects
Trail: Security Features in Java SE
Home Page > Security Features in Java SE
« Previous • Trail • Next »
Lesson: Quick Tour of Controlling Applets

This lesson shows how resource accesses, such as reading or writing a file, are not permitted for unsigned applets unless explicitly allowed by a permission entry in a policy file.

The steps for this lesson are

  1. Observe Applet Restrictions

  2. Set Up a Policy File to Grant the Required Permission

  3. See the Policy File Effects
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Observe Applet Restrictions


Observe Applet Restrictions (The Java™ Tutorials > Security Features in Java SE > Quick Tour of Controlling Applets)

Trail: Security Features in Java SE
Lesson: Quick Tour of Controlling Applets
Quick Tour of Controlling Applets
Observe Applet Restrictions
Set up a Policy File to Grant the Required Permission
Start Policy Tool
Grant the Required Permission
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Quick Tour of Controlling Applets
« Previous • Trail • Next »
Observe Applet Restrictions

The Java Plug-in uses a Security Manager to keep viruses from accessing your computer through an applet. No unsigned applet is allowed to access a resource unless the Security Manager finds that permission has been explicitly granted to access that system resource. That permission is granted by an entry in a policy file.

Here's the source code for an applet named WriteFile that tries to create and to write to a file named writetest in the current directory. This applet will not be able to create the file unless it has explicit permission in a policy file.

Type this command in your command window:

appletviewer http://java.sun.com/docs/books/tutorial/security/tour1/examples/WriteFile.html
Type this command on a single line, without spaces in the URL.

You should see a message about a security exception, as shown in the following figure. This is the expected behavior; the system caught the applet trying to access a resource it does not have permission to access.

WriteFile doesn't have permission to write to writetest

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Quick Tour of Controlling Applets
Next page: Set up a Policy File to Grant the Required Permission


Set up a Policy File to Grant the Required Permission (The Java™ Tutorials > Security Features in Java SE > Quick Tour of Controlling Applets)

Trail: Security Features in Java SE
Lesson: Quick Tour of Controlling Applets
Quick Tour of Controlling Applets
Observe Applet Restrictions
Set up a Policy File to Grant the Required Permission
Start Policy Tool
Grant the Required Permission
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Quick Tour of Controlling Applets
« Previous • Trail • Next »
Set up a Policy File to Grant the Required Permission

A policy file is an ASCII text file and can be composed via a text editor or the graphical Policy Tool utility demonstrated in this section. The Policy Tool saves you typing and eliminates the need for you to know the required syntax of policy files, thus reducing errors.

This lesson uses the Policy Tool to create a policy file named mypolicy, in which you will add a policy entry that grants code from the directory where WriteFile.class is stored permission to write the writetest file.

Follow these steps to create and modify your new policy file:

  1. Start Policy Tool

  2. Grant the Required Permission

  3. Save the Policy File

Note for UNIX Users: The steps illustrate creating the policy file for a Windows system. The steps are exactly the same if you are working on a UNIX system. Where the text says to store the policy file in the C:\Test directory, you can store it in another directory. The examples in the step See the Policy File Effects and in the lesson Quick Tour of Controlling Applications assume that you stored it in the ~/test directory.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Observe Applet Restrictions
Next page: Start Policy Tool


Start Policy Tool (The Java™ Tutorials > Security Features in Java SE > Quick Tour of Controlling Applets)

Trail: Security Features in Java SE
Lesson: Quick Tour of Controlling Applets
Section: Set up a Policy File to Grant the Required Permission
Quick Tour of Controlling Applets
Observe Applet Restrictions
Set up a Policy File to Grant the Required Permission
Start Policy Tool
Grant the Required Permission
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Quick Tour of Controlling Applets
« Previous • Trail • Next »
Start Policy Tool
To start Policy Tool, simply type the following at the command line:
policytool

This brings up the Policy Tool window.

Whenever Policy Tool is started, it attempts to fill in this window with policy information from the user policy file. The user policy file is named .java.policy by default in your home directory. If Policy Tool cannot find the user policy file, it issues a warning and displays a blank Policy Tool window (a window with headings and buttons but no data in it), as shown in the following figure.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

You can then proceed to either open an existing policy file or to create a new policy file.

The first time you run the Policy Tool, you will see the blank Policy Tool window, since a user policy file does not yet exist. You can immediately proceed to create a new policy file, as described in the next step.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Set up a Policy File to Grant the Required Permission
Next page: Grant the Required Permission


Grant the Required Permission (The Java™ Tutorials > Security Features in Java SE > Quick Tour of Controlling Applets)

Trail: Security Features in Java SE
Lesson: Quick Tour of Controlling Applets
Section: Set up a Policy File to Grant the Required Permission
Quick Tour of Controlling Applets
Observe Applet Restrictions
Set up a Policy File to Grant the Required Permission
Start Policy Tool
Grant the Required Permission
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Quick Tour of Controlling Applets
« Previous • Trail • Next »
Grant the Required Permission
To grant the WriteFile applet permission to create and to write to the writetest file, you must create a policy entry granting this permission. To create a new entry, click on the Add Policy Entry button in the main Policy Tool window. This displays the Policy Entry dialog box as shown in the following figure.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

A policy entry specifies one or more permissions for code from a particular code source - code from a particular location (URL), code signed by a particular entity, or both.

The CodeBase and the SignedBy text boxes specify which code you want to grant the permission(s) you will be adding in the file.

  • A CodeBase value indicates the code source location; you grant the permission(s) to code from that location. An empty CodeBase entry signifies "any code" -- it does not matter where the code originates.

  • A SignedBy value indicates the alias for a certificate stored in a keystore. The public key within that certificate is used to verify the digital signature on the code. You grant permission to code signed by the private key corresponding to the public key in the keystore entry specified by the alias. The SignedBy entry is optional; omitting it signifies "any signer" -- it does not matter whether the code is signed, or by whom.

If you have both a CodeBase and a SignedBy entry, the permission(s) are granted only to code that is both from the specified location and signed by the named alias.

To grant WriteFile the permission it needs, you can grant permission to all code from the location (URL) where WriteFile.class is stored.

Type the following URL into the CodeBase text box of the Policy Entry dialog box:

http://java.sun.com/docs/books/tutorial/security/tour1/examples/
Note: This is a URL. Therefore, it must always use slashes as separators, not backslashes.

Leave the SignedBy text box blank, since you aren't requiring the code to be signed.

Note: To grant the permission to any code (.class file) not just from the directory specified previously but from the security directory and its subdirectories, type the following URL into the CodeBase box:
http://java.sun.com/docs/books/tutorial/security/-

You have specified where the code comes from (the CodeBase), and that the code does not have to be signed (since there is no SignedBy value). Now you are ready to grant permissions to that code.

Click on the Add Permission button to display the Permissions dialog box.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Follow these steps to grant code from the specified CodeBase permission to write (and thus also to create) the file named writetest.
  1. Choose File Permission from the Permission drop-down list. The complete permission type name (java.io.FilePermission) now displays in the text box to the right of the drop-down list.

  2. Type the following in the text box to the right of the list labeled Target Name to specify the file named writetest:
    writetest
  3. Specify write access by choosing the write option from the Actions drop-down list.
The Permissions dialog box now looks like the following.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Click on the OK button. The new permission displays in a line in the Policy Entry dialog. So now the policy entry window looks like this.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

You have now specified this policy entry, so click on the Done button in the Policy Entry dialog. The Policy Tool window now contains a line representing the policy entry, showing the CodeBase value.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Start Policy Tool
Next page: Save the Policy File


Save the Policy File (The Java™ Tutorials > Security Features in Java SE > Quick Tour of Controlling Applets)

Trail: Security Features in Java SE
Lesson: Quick Tour of Controlling Applets
Section: Set up a Policy File to Grant the Required Permission
Quick Tour of Controlling Applets
Observe Applet Restrictions
Set up a Policy File to Grant the Required Permission
Start Policy Tool
Grant the Required Permission
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Quick Tour of Controlling Applets
« Previous • Trail • Next »
Save the Policy File

To save the new policy file you've been creating, choose the Save As command from the File menu. This displays the Save As dialog box.

The examples in this lesson and in the Quick Tour of Controlling Applications lesson assume that you stored the policy file in the Test directory on the C: drive.

Navigate to the Test directory. Type the file name mypolicy and click on Save.

The policy file is now saved, and its name and path are shown in the text box labeled Policy File.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Exit Policy Tool by choosing Exit from the File menu.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Grant the Required Permission
Next page: See the Policy File Effects


See the Policy File Effects (The Java™ Tutorials > Security Features in Java SE > Quick Tour of Controlling Applets)

Trail: Security Features in Java SE
Lesson: Quick Tour of Controlling Applets
Quick Tour of Controlling Applets
Observe Applet Restrictions
Set up a Policy File to Grant the Required Permission
Start Policy Tool
Grant the Required Permission
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Quick Tour of Controlling Applets
« Previous • Trail • Next »
See the Policy File Effects
Now that you have created the mypolicy policy file, you can execute the WriteFile applet to create and to write the file writetest, as shown in the following figure.

WriteFile can now access writetest

Whenever you run an applet, or an application with a security manager, the policy files that are loaded and used by default are the ones specified in the "security properties file", which is located in one of the following directories:

  Windows:
    java.home\lib\security\java.security
  UNIX:
    java.home/lib/security/java.security
Note: The java.home environment variable names the directory into which the JRE was installed.

The policy file locations are specified as the values of properties whose names take the form

policy.url.n
Where n indicates a number. Specify each property value in a line that takes the following form:
policy.url.n=URL
Where URL is a URL specification. For example, the default policy files, sometimes referred to as the system and user policy files, respectively, are defined in the security properties file as
policy.url.1=file:${java.home}/lib/security/java.policy
policy.url.2=file:${user.home}/.java.policy
Note: Use of the notation ${propName} in the security properties file is a way of specifying the value of a property. Thus ${java.home} will be replaced at runtime by the actual value of the "java.home" property, which indicates the directory into which the JRE was installed, and ${user.home} will be replaced by the value of the "user.home" property, for example, C:\Windows.
In the previous step you did not modify one of these existing policy files. You created a new policy file named mypolicy. There are two possible ways you can have the mypolicy file be considered as part of the overall policy, in addition to the policy files specified in the security properties file. You can either specify the additional policy file in a property passed to the runtime system, as described in Approach 1, or add a line in the security properties file specifying the additional policy file, as described in Approach 2.
Note: On a UNIX system, you must have DNS configured in order for the WriteFile program to be downloaded from the public web site, shown in the command below. You need to have dns in the list of lookup services for hosts in your /etc/nsswitch.conf file, as in
    hosts:    dns files nis
You also need a /etc/resolv.conf file with a list of nameservers. Consult your system administrator for more information.

Approach 1

You can use the appletviewer command-line argument, -J-Djava.security.policy, to specify a policy file that should be used, in addition to the ones specified in the security properties file. To run the WriteFile applet with your new mypolicy policy file included, type the following in the directory in which mypolicy is stored:
appletviewer -J-Djava.security.policy=mypolicy
 http://java.sun.com/docs/books/tutorial/security/tour1/examples/WriteFile.html
Notes:
  • Type this command as a single line, with a space between mypolicy and the URL, and no spaces in the URL. Multiple lines are used in this example for legibility purposes.

  • If this command line is longer than the maximum number of characters you are allowed to type on a single line, do the following. Create and save a text file containing the full command, and name the file with a .bat extension, for example, wf.bat. Then in your command window, type the name of the .bat file instead of the command.

If the applet still reports an error, you must troubleshoot the policy file. Use the Policy Tool to open the mypolicy file (using File > Open) and check the policy entries you just created in the previous step, Set Up a Policy File to Grant the Required Permissions.

To view or edit an existing policy entry, click on the line displaying that entry in the main Policy Tool window, then choose the Edit Policy Entry button. You can also double-click the line for that entry.

This launches the same type of Policy Entry dialog box that displays when you are adding a new policy entry after choosing the Add Policy Entry button, except in this case the dialog box is filled in with the existing policy entry information. To change the information, retype it (for the CodeBase and SignedBy values) or add, remove, or modify permissions.

Approach 2

You can specify a number of URLs (including ones of the form "http://") in policy.url.n properties in the security properties file, and all the designated policy files will get loaded.

So one way to have our mypolicy file's policy entry considered by the appletviewer is to add an entry specifying that policy file in the security properties file.

Important: If you are running your own copy of the JDK, you can easily edit your security properties file. If you are running a version shared with other users, you may only be able to modify the system-wide security properties file if you have write access to it or if you ask your system administrator to modify the file when appropriate. However, it's probably not appropriate for you to make modifications to a system-wide policy file for this tutorial test. We suggest that you just read the following to see how it is done or that you install your own private version of the JDK to use for the tutorial lessons.

To modify the security properties file, open it in an editor suitable for editing an ASCII text file. Then add the following line after the line starting with policy.url.2:

  Windows:
    policy.url.3=file:/C:/Test/mypolicy
  UNIX:
    policy.url.3=file:${user.home}/test/mypolicy

On a UNIX system you can also explicitly specify your home directory:

policy.url.3=file:/home/susanj/test/mypolicy

Now you can run the following:

appletviewer http://java.sun.com/docs/books/tutorial/
security1.2/tour1/examples/WriteFile.html
Type this command on one line, without spaces in the URL.

If you still get a security exception, you must troubleshoot your new policy file. Use the Policy Tool to check the policy entry you just created in the previous step, Set Up a Policy File to Grant the Required Permissions. Change any typos or other errors.

Important: The mypolicy policy file is also used in the Quick Tour of Controlling Applications lesson. You do not need to include the mypolicy file unless you are running this Tutorial lesson. To exclude this file, open the security properties file and delete the line you just added.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Save the Policy File
Next page: Quick Tour of Controlling Applications


Lesson: Quick Tour of Controlling Applications (The Java™ Tutorials > Security Features in Java SE)

Quick Tour of Controlling Applications
Observe Application Freedom
See How to Restrict Applications
Set up the Policy File to Grant the Required Permissions
Open the Policy File
Grant the Required Permissions
Save the Policy File
See the Policy File Effects
Trail: Security Features in Java SE
Home Page > Security Features in Java SE
« Previous • Trail • Next »
Lesson: Quick Tour of Controlling Applications
Pre-requisite lesson: Quick Tour of Controlling Applets

This lesson shows how to use a security manager to grant or deny access to system resources, this time for applications. The lesson shows how resource accesses for applications may be controlled exactly the same as for unsigned applets.

The steps for this lesson are:

  1. Observe Application Freedom

  2. See How to Restrict Applications

  3. Set Up the Policy File to Grant the Required Permissions

  4. See the Policy File Effects
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Observe Application Freedom


Observe Application Freedom (The Java™ Tutorials > Security Features in Java SE > Quick Tour of Controlling Applications)

Trail: Security Features in Java SE
Lesson: Quick Tour of Controlling Applications
Quick Tour of Controlling Applications
Observe Application Freedom
See How to Restrict Applications
Set up the Policy File to Grant the Required Permissions
Open the Policy File
Grant the Required Permissions
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Quick Tour of Controlling Applications
« Previous • Trail • Next »
Observe Application Freedom

A security manager is not automatically installed when an application is running. In the next step, you'll see how to apply the same security policy to an application found on the local file system as to downloaded unsigned applets. But first, let's demonstrate that a security manager is by default not installed for an application, and thus the application has full access to resources.

Create a file named GetProps.java on your computer by either copying or downloading the GetProps.java source code.

The examples in this lesson assume that you put GetProps.java in the C:\Test directory if you're using a Windows system or in the ~/test directory on UNIX.

As you can see if you examine the source file, this program tries to get (read) the property values, whose names are "os.name" , "java.version", "user.home", and "java.home".

Now compile and run GetProps.java. You should see output like the following:

C:\TEST>java GetProps
    About to get os.name property value
      The name of your operating system is: Windows XP
    About to get java.version property value
      The version of the JVM you are running is: 1.6.0
    About to get user.home property value
      Your user home directory is: C:\WINDOWS
    About to get java.home property value
      Your JRE installation directory is: C:\JDK6.0.0\JRE
This shows that the application was allowed to access all the property values, as shown in the following figure.

Applicaton can read property values

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Quick Tour of Controlling Applications
Next page: See How to Restrict Applications


See How to Restrict Applications (The Java™ Tutorials > Security Features in Java SE > Quick Tour of Controlling Applications)

Trail: Security Features in Java SE
Lesson: Quick Tour of Controlling Applications
Quick Tour of Controlling Applications
Observe Application Freedom
See How to Restrict Applications
Set up the Policy File to Grant the Required Permissions
Open the Policy File
Grant the Required Permissions
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Quick Tour of Controlling Applications
« Previous • Trail • Next »
See How to Restrict Applications
As you saw in the previous step, the Java runtime does not automatically install a Security Manager when it runs an application. To apply the same security policy to an application found on the local file system as to downloaded unsigned applets, you can invoke the interpreter with the new -Djava.security.manager command line argument.

To execute the GetProps application with the default security manager, type the following:

java -Djava.security.manager GetProps
Here's the output from the program:
C:\TEST>java -Djava.security.manager GetProps
    About to get os.name property value
      The name of your operating system is: WindowsXP
    About to get java.version property value
      The version of the JVM you are running is: JDK 1.6.0
    About to get user.home property value
    Caught exception java.security.AccessControlException:
    access denied (java.util.PropertyPermission user.home read)

The process is shown in the following figure.

Security-Sensitive Properties

The Java runtime loads a default policy file by default and grants all code permission to access some commonly useful properties such as "os.name" and "java.version". These properties are not security-sensitive, so granting these permissions does not normally pose a security risk.

The other properties GetProps tries to access, "user.home" and "java.home", are not among the properties for which the system policy file grants read permission. Thus as soon as GetProps attempts to access the first of these properties ("user.home"), the security manager prevents the access and reports an AccessControlException. This exception indicates that the policy currently in effect, which consists of entries in one or more policy files, doesn't allow permission to read the "user.home" property.

The Default Policy File

By default, the system policy file located at:

  Windows:
    java.home\lib\security\java.policy
  UNIX:
    java.home/lib/security/java.policy
Note that java.home represents the value of the "java.home" property, which is a system property specifying the directory into which the JRE was installed. Thus if the JRE was installed in the directory named C:\jdk\jre on Windows and /jdk/jre on UNIX, the system policy file is located at
  Windows:
    C:\jdk\jre\lib\security\java.policy
  UNIX:
    /jdk/jre/lib/security/java.policy

Here is a copy of the default policy file.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Observe Application Freedom
Next page: Set up the Policy File to Grant the Required Permissions


Set up the Policy File to Grant the Required Permissions (The Java™ Tutorials > Security Features in Java SE > Quick Tour of Controlling Applications)

Trail: Security Features in Java SE
Lesson: Quick Tour of Controlling Applications
Quick Tour of Controlling Applications
Observe Application Freedom
See How to Restrict Applications
Set up the Policy File to Grant the Required Permissions
Open the Policy File
Grant the Required Permissions
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Quick Tour of Controlling Applications
« Previous • Trail • Next »
Set up the Policy File to Grant the Required Permissions
This step uses the Policy Tool utility to open the policy file named mypolicy created in the Quick Tour of Controlling Applets lesson. You will add a new policy entry granting permission for code from the directory where GetProps.class is stored to read the "user.home" and the "java.home" property values, as shown in the following figure.

The mypolicy policy file grants WriteFile and GetProps the permissions they need

The steps are as follows.

  1. Open the Policy File

  2. Grant the Required Permissions

  3. Save the Policy File

Note for UNIX Users: The instructions illustrate creating the policy file for a Windows system. The steps are exactly the same if you are working on a UNIX system, with the following differences.
  • You retrieve the mypolicy file from the test directory in your home directory.

  • For the CodeBase URL in the step for granting the required permissions, you can substitute file:${user.home}/test/ for file:/C:/Test/. Alternatively you could directly specify your home directory rather than referring to the "user.home" property, as in file:/home/susanj/test/.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: See How to Restrict Applications
Next page: Open the Policy File


Open the Policy File (The Java™ Tutorials > Security Features in Java SE > Quick Tour of Controlling Applications)

Trail: Security Features in Java SE
Lesson: Quick Tour of Controlling Applications
Section: Set up the Policy File to Grant the Required Permissions
Quick Tour of Controlling Applications
Observe Application Freedom
See How to Restrict Applications
Set up the Policy File to Grant the Required Permissions
Open the Policy File
Grant the Required Permissions
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Quick Tour of Controlling Applications
« Previous • Trail • Next »
Open the Policy File
Start Policy Tool by typing the following at the command line:
policytool

This brings up the Policy Tool window. To open the mypolicy policy file, use the Open command in the File menu. This will present you with an Open dialog, which you can use to navigate the directory structure until you get to the directory containing the policy file (that is, the C:\Test\ directory).

Choose the mypolicy file in that directory and then select the Open button.

This will fill in the Policy Tool window with information from the mypolicy policy file, including the policy file name and the CodeBase part of the policy entry created by the Quick Tour of Controlling Applets lesson.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Set up the Policy File to Grant the Required Permissions
Next page: Grant the Required Permissions


Grant the Required Permissions (The Java™ Tutorials > Security Features in Java SE > Quick Tour of Controlling Applications)

Trail: Security Features in Java SE
Lesson: Quick Tour of Controlling Applications
Section: Set up the Policy File to Grant the Required Permissions
Quick Tour of Controlling Applications
Observe Application Freedom
See How to Restrict Applications
Set up the Policy File to Grant the Required Permissions
Open the Policy File
Grant the Required Permissions
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Quick Tour of Controlling Applications
« Previous • Trail • Next »
Grant the Required Permissions
To grant the GetProps application permission to read the "user.home" and "java.home" property values, you must create a policy entry granting those permissions. Choose the Add Policy Entry button in the main Policy Tool window. This brings up the Policy Entry dialog box, as shown in the following figure.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Type the following file URL into the CodeBase text box to indicate that you are going to be granting a permission to code from the specified directory, which is the directory in which GetProps.class is stored.

file:/C:/Test/
(Note, this is a URL and thus must always have slashes, not backslashes.)

Leave the SignedBy text box blank, since you aren't requiring the code to be signed.

To add permission to read the "user.home" property value, choose the Add Permission button. This brings up the Permissions dialog box.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Do the following.
  1. Choose Property Permission from the Permission drop-down list. The complete permission type name (java.util.PropertyPermission) now appears in the text box to the right of the drop-down list.

  2. Type the following in the text box to the right of the list labeled Target Name to specify the "user.home" property:
    user.home
  3. Specify permission to read this property by selecting the read option from the Actions drop-down list.
Now the Permissions dialog box looks like the following.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Choose the OK button. The new permission appears in a line in the policy entry window.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

To add permission to read the "java.home" property value, choose the Add Permission button again. In the Permissions dialog box, do the following:

  1. Choose Property Permission from the Permission drop-down list.

  2. Type the following in the text box to the right of the list labeled Target Name to specify the "java.home" property:
    java.home
  3. Specify permission to read this property by choosing the read option from the Actions drop-down list.
Now the Permissions dialog box looks like the following.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Choose the OK button. The new permission and the previously added permission appear in lines in the policy entry window, as shown in the following figure.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

You are now done specifying this policy entry, so choose the Done button in the Policy Entry dialog. The Policy Tool window now includes a line representing the new policy entry, showing the CodeBase value.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Open the Policy File
Next page: Save the Policy File


Save the Policy File (The Java™ Tutorials > Security Features in Java SE > Quick Tour of Controlling Applications)

Trail: Security Features in Java SE
Lesson: Quick Tour of Controlling Applications
Section: Set up the Policy File to Grant the Required Permissions
Quick Tour of Controlling Applications
Observe Application Freedom
See How to Restrict Applications
Set up the Policy File to Grant the Required Permissions
Open the Policy File
Grant the Required Permissions
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Quick Tour of Controlling Applications
« Previous • Trail • Next »
Save the Policy File
To save the policy file, simply choose the Save command in the File menu.

Then exit Policy Tool by choosing the Exit command from the File menu.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Grant the Required Permissions
Next page: See the Policy File Effects


See the Policy File Effects (The Java™ Tutorials > Security Features in Java SE > Quick Tour of Controlling Applications)

Trail: Security Features in Java SE
Lesson: Quick Tour of Controlling Applications
Quick Tour of Controlling Applications
Observe Application Freedom
See How to Restrict Applications
Set up the Policy File to Grant the Required Permissions
Open the Policy File
Grant the Required Permissions
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Quick Tour of Controlling Applications
« Previous • Trail • Next »
See the Policy File Effects
Now that you have added the required policy entry to the mypolicy policy file, you should be able to read the specified properties when you execute the GetProps application with a security manager, as shown in the following figure.

As noted at the end of the Quick Tour of Controlling Applets lesson, whenever you run an unsigned applet, or an application with a security manager, the policy files that are loaded and used by default are the ones specified in the "security properties file", which is located at

  Windows:
    java.home\lib\security\java.security
  UNIX:
    java.home/lib/security/java.security
Note: java.home indicates the directory into which the JRE was installed.

There are two possible ways you can have the mypolicy file be considered as part of the overall policy, in addition to the policy files specified in the security properties file. You can either specify the additional policy file in a property passed to the runtime system, as described in Approach 1, or add a line in the security properties file specifying the additional policy file, as discussed in Approach 2.

Approach 1

You can use a -Djava.security.policy interpreter command line argument to specify a policy file that should be used in addition to the ones specified in the security properties file.

Make sure that you are in the directory containing GetProps.class and mypolicy. Then you can run the GetProps application and pass the mypolicy policy file to the interpreter by typing the following command on one line:

java -Djava.security.manager
     -Djava.security.policy=mypolicy GetProps
Note: Remember that -Djava.security.manager is required in order to run an application with a security manager, as shown in the See How to Restrict Applications step.

The program reports the values of the "user.home" and "java.home" properties.

If the application still reports an error, something is wrong in the policy file. Use the Policy Tool to check the policy entry you just created in the Set up the Policy File to Grant the Required Permissions step.

Approach 2

You can specify a number of URLs in policy.url.n properties in the security properties file, and all the designated policy files will get loaded. So one way to have your mypolicy file's policy entries considered by the java interpreter is to add an entry specifying that policy file in the security properties file.

You created such an entry in the last part of the Quick Tour of Controlling Applets lesson. If your security properties file still has that entry, you're ready to run the application. Otherwise you need to add the entry. To do so, open the security properties file in an editor suitable for editing an ASCII text file. Then add the following line after the line containing policy.url.2:

If you're on a Windows system, add
policy.url.3=file:/C:/Test/mypolicy

If you're on a UNIX system, add

policy.url.3=file:${user.home}/test/mypolicy
On a UNIX system you can alternatively explicitly specify your home directory, as in
policy.url.3=file:/home/susanj/test/mypolicy

Run the Application

Now you should be able to successfully run the following.
java -Djava.security.manager GetProps

As with approach 1, if you still get a security exception, something is wrong in the policy file. Use the Policy Tool to check the policy entry you just created in the Set up the Policy File to Grant the Required Permissions step. Then fix any typos or other errors.

Important: You do not need to include the mypolicy file unless you are running this Tutorial lesson. To exclude this file, open the security properties file and delete the line you just added.

Before continuing, you may want to delete the line you just added in the security properties file (or comment it out), since you probably do not want the mypolicy file included when you are not running the tutorial lessons.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Save the Policy File
Next page: API and Tools Use for Secure Code and File Exchanges


Lesson: API and Tools Use for Secure Code and File Exchanges (The Java™ Tutorials > Security Features in Java SE)

Trail: Security Features in Java SE
Home Page > Security Features in Java SE
« Previous • Trail • Next »
Lesson: API and Tools Use for Secure Code and File Exchanges
This lesson explains why digital signatures, certificates, and keystores are needed. The lesson also compares use of the tools versus the JDK Security API with respect to generating signatures. Such tool usage is demonstrated in the next two lessons, Signing Code and Granting It Permissions and Exchanging Files . API usage is demonstrated in the Generating and Verifying Signatures lesson.

This lesson contains the following sections

  • Code and Document Security
  • Tool and API Notes
  • Use of the JDK Security API to Sign Documents
  • Use of the Tools to Sign Code or Documents

Code and Document Security

If you electronically send someone an important document (or documents), or an applet or application to run, the recipient needs a way to verify that the document or code came from you and was not modified in transit (for example, by a malicious user intercepting it). Digital signatures, certificates, and keystores all help ensure the security of the files you send.

Digital Signatures

The basic idea in the use of digital signatures is as follows.
  1. You "sign" the document or code using one of your private keys, which you can generate by using keytool or security API methods. That is, you generate a digital signature for the document or code, using the jarsigner tool or Security API methods.

  2. You send your signed document to your recipient.

  3. You also supply your recipient with your public key. This public key corresponds to the private key you originally used to generate the signature.

  4. Your recipient uses your public key to verify that your document came from you and was not modified before it reached him/her.

A recipient needs to ensure that your public key itself is authentic before he/she can use it to verify that your signature is authentic. Therefore, you will usually supply a certificate that contains your public key together with the key of a Certificate Authority who can vouch for your key's authenticity. See the next section for details.

For more information about the terminology and concepts of signing and verification, and further explanation of the benefits, see the Signing JAR Files section of the "The Java Archive (JAR) File Format" trail.

Certificates

A certificate contains
  • A public key.

  • The "distinguished-name" information of the entity (person, company, or so on) whose certificate it is. This entity is referred to as the certificate subject, or owner. The distinguished-name information includes the following attributes (or a subset): the entity's name, organizational unit, organization, city or locality, state or province, and country code.

  • A digital signature. A certificate is signed by one entity, the issuer, to vouch for the fact that the enclosed public key is the actual public key of another entity, the owner.

  • The distinguished-name information for the signer (issuer).
One way for a recipient to check whether a certificate is valid is by verifying its digital signature, using its issuer's (signer's) public key. That key can itself be stored within another certificate whose signature can also be verified by using the public key of that next certificate's issuer, and that key may also be stored in yet another certificate, and so on. You can stop checking when you reach a public key that you already trust and use it to verify the signature on the corresponding certificate.

If the recipient cannot establish a trust chain, then he/she can calculate the the certificate fingerprint(s), using the keytool -import or -printcert command. A fingerprint is a relatively short number that uniquely and reliably identifies the certificate. (Technically, the fingerprint is a hash value of the certificate information, using a message digest function.) The recipient can then phone the certificate owner and compare the fingerprint values of the received certificate with the certificate that was sent. If the fingerprints are the same, the certificates are the same.

Thus you can ensure that a certificate was not modified in transit. One other potential uncertainty when working with certificates is the identity of the sender. Sometimes a certificate is self-signed, that is, signed using the private key corresponding to the public key in the certificate; the issuer is the same as the subject. It is reasonable to self-sign a certificate if the recipient already trusts the sender.

Otherwise the sender needs to obtain a certificate from a trusted third party, referred to as a certification authority (CA). To do so, you send a self-signed certificate signing request (CSR) to the CA. The CA verifies the signature on the CSR and your identity, perhaps by checking your driver's license or other information. The CA then vouches for your being the owner of the public key by issuing a certificate and signing it with its own (the CA's) private key. Anybody who trusts the issuing CA's public key can now verify the signature on the certificate. In many cases the issuing CA itself may have a certificate from a CA higher up in the CA hierarchy, leading to certificate chains.

Certificates of entities you trust are typically imported into your keystore as "trusted certificates." The public key in each such certificate may then be used to verify signatures generated using the corresponding private key. Such verifications can be accomplished by:

  • the jarsigner tool (if the document/code and signature appear in a JAR file),

  • API methods, or

  • the runtime system, when a resource access is attempted and a policy file specifies that the resource access is allowed for the code attempting the access if its signature is authentic. The code's class file(s) and signature must be in a JAR file.

If you are sending signed code or documents to others, you need to supply them with the certificate containing the public key corresponding to the private key used to sign the code/document. The keytool -export command or API methods can export your certificate from your keystore to a file, which can then be sent to anyone needing it. A person who receives the certificate can import it into the keystore as a trusted certificate, using, for example, API methods or the keytool -import command.

If you use the jarsigner tool to generate a signature for a JAR file, the tool retrieves your certificate and its supporting certificate chain from your keystore. The tool then stores them, along with the signature, in the JAR file.

Keystores

Private keys and their associated public key certificates are stored in password-protected databases called keystores. A keystore can contain two types of entries: the trusted certificate entries discussed above, and key/certificate entries, each containing a private key and the corresponding public key certificate. Each entry in a keystore is identified by an alias.

A keystore owner can have multiple keys in the keystore, accessed via different aliases. An alias is typically named after a particular role in which the keystore owner uses the associated key. An alias may also identify the purpose of the key. For example, the alias signPersonalEmail might be used to identify a keystore entry whose private key is used for signing personal e-mail, and the alias signJarFiles might be used to identify an entry whose private key is used for signing JAR files.

The keytool tool can be used to

  • Create private keys and their associated public key certificates
  • Issue certificate requests, which you send to the appropriate certification authority
  • Import certificate replies, obtained from the certification authority you contacted
  • Import public key certificates belonging to other parties as trusted certificates
  • Manage your keystore

API methods can also be used to access and to modify a keystore.

Tool and API Notes

Note the following regarding use of the tools and the API related to digital signatures.
  • You can use the JDK Security API, tools, or a combination to generate keys and signatures and to import certificates. You can use these API or tool features to securely exchange documents with others.

  • To use the tools for document exchange, the document(s) must be placed in a JAR (Java ARchive) file, which may be created by the jar tool. A JAR file is a good way of encapsulating multiple files in one spot. When a file is "signed", the resulting digital signature bytes need to be stored somewhere. When a JAR file is signed, the signature can go in the JAR file itself. This is what happens when you use the jarsigner tool to sign a JAR file.

  • If you are creating applet code that you will sign, it needs to be placed in a JAR file. The same is true if you are creating application code that may be similarly restricted by running it with a security manager. The reason you need the JAR file is that when a policy file specifies that code signed by a particular entity is permitted one or more operations, such as specific file reads or writes, the code is expected to come from a signed JAR file. (The term "signed code" is an abbreviated way of saying "code in a class file that appears in a JAR file that was signed.")

  • In order for the runtime system to check a code signature, the person/organization that will run the code first needs to import into their keystore a certificate authenticating the public key corresponding to the private key used to sign the code.

  • In order for the jarsigner tool to verify the authenticity of a JAR file signature, the person/organization that received the JAR file first needs to import into their keystore a certificate authenticating the public key corresponding to the private key used to sign the code.

  • At this time there are no APIs for certificate creation.

Use of the JDK Security API to Sign Documents

The Generating and Verifying Signatures shows you how to use the JDK Security API to sign documents. The lesson shows what one program, executed by the person who has the original document, would do to
  • generate keys,

  • generate a digital signature for the data using the private key, and

  • export the public key and the signature to files.
Then it shows an example of another program, executed by the receiver of the data, signature, and public key. It shows how the program
  • Imports the public key

  • Verifies the authenticity of the signature.
This lesson also shows you alternative ways to import and supply keys, including certificates.

Use of the Tools to Sign Code or Documents

The Signing Code and Granting It Permissions lesson shows how to use Java Security tools to place your code into a JAR file, sign it, and export your public key. Then it shows how your recipient can use these same Java tools to import your public key certificate and then add an entry to a policy file that will grant your code the permission it needs to access system resources controlled by your recipient.

The Exchanging Files lesson you how to use Java security tools to sign a document and then export the public key certificate for the public key using keytool. corresponding to the private key used to sign that document using keytool. Then it shows how your recipient can verify your signature by installing your public key certificate and then using the jarsigner tool to verify your signature.

These two lessons have much in common. In both cases, the first two steps for the code or document sender are to:

  • Create a JAR file containing the document or class file, using the jar tool.

  • Generate keys (if they don't already exist), using the keytool -genkey command.
The next two steps are optional:
  • Use the keytool -certreq command; then send the resulting certificate signing request to a certification authority (CA) such as VeriSign.

  • Use the keytool -import command to import the CA's response.
The next two steps are required:
  • Sign the JAR file, using the jarsigner tool and the private key generated earlier.

  • Export the public key certificate, using the keytool -export command. Then supply the signed JAR file and the certificate to the receiver.
In both cases, the receiver of the signed JAR file and the certificate should import the certificate as a trusted certificate, using the keytool -import command. The keytool will attempt to construct a trust chain from the certificate to be imported to an already trusted certificate in the keystore. If that fails, the keytool will display the certificate fingerprint and prompt you to verify it.

If what was sent was code, the receiver also needs to modify a policy file to permit the required resource accesses to code signed by the private key corresponding to the public key in the imported certificate. The Policy Tool can be used to do this.

If what was sent was one or more documents, the receiver needs to verify the authenticity of the JAR file signature, using the jarsigner tool.

This lesson discusses the two optional steps. The other steps are covered in the next two lessons, Signing Code and Granting It Permissions and Exchanging Files .

Generating a Certificate Signing Request (CSR) for a Public Key Certificate

When keytool is used to generate public/private key pairs, it creates a keystore entry containing a private key and a self-signed certificate for the public key. (That is, the certificate is signed using the corresponding private key.) This may be adequate if the people receiving your signed files already know and trust your identity.

However, a certificate is more likely to be trusted by others if it is signed by a certification authority (CA). To get a certificate signed by a CA, you first generate a certificate signing request (CSR), via a command such as the following:

keytool -certreq -alias alias -file csrFile
Here alias is used to access the keystore entry containing the private key and the public key certificate, and csrFile specifies the name to be used for the CSR created by this command.

You then submit this file to a CA, such as VeriSign, Inc. The CA authenticates you, the requestor ("subject"), and then signs and returns a certificate authenticating your public key. By signing the certificate, the CA vouches that you are the owner of the public key.

In some cases, the CA will return a chain of certificates, each one authenticating the public key of the signer of the previous certificate in the chain.

Importing the Response from the CA

If you submitted a certificate signing request (CSR) to a certification authority (CA), you need to replace the original self-signed certificate in your keystore with a certificate chain by importing the certificate (or chain of certificates) returned to you by the CA.

But first you need a "trusted certificate" entry in your keystore (or in the cacerts keystore file, described below) that authenticates the CA's public key. With such an entry the CA's signature can be verified. That is, the CA's signature on the certificate, or on the final certificate in the chain the CA sends to you in response to your CSR, can be verified.

Importing a Certificate from a CA as a "Trusted Certificate"

Before you import the certificate reply from a CA, you need one or more "trusted certificates" in your keystore or in the cacerts file.

  • If the certificate reply is a certificate chain, you just need the top certificate of the chain -- the "root" CA certificate authenticating that CA's public key.

  • If the certificate reply is a single certificate, you need a certificate for the issuing CA (the one that signed it). If that certificate is not self-signed, you need a certificate for its signer, and so on, up to a self-signed "root" CA certificate.

The cacerts file represents a system-wide keystore with CA certificates. This file resides in the JRE security properties directory, java.home/lib/security, where java.home is the JRE installation directory.

IMPORTANT: Verify Your cacerts File
Since you trust the CAs in the cacerts file as entities for signing and issuing certificates to other entities, you must manage the cacerts file carefully. The cacerts file should contain only certificates of the CAs you trust. It is your responsibility to verify the trusted root CA certificates bundled in the cacerts file and make your own trust decisions. To remove an untrusted CA certificate from the cacerts file, use the delete option of the keytool command. You can find the cacerts file in the JRE installation directory. Contact your system administrator if you do not have permission to edit this file.
The cacerts file contains a number of trusted CA certificates. If you sent your CSR to one of these trusted vendors (such as VeriSign), you won't need to import the vendor's root certificate as a trusted certificate in your keystore; you can go on to the next section to see how to import the certificate reply from the CA.

A certificate from a CA is usually either self-signed or signed by another CA, in which case you also need a certificate authenticating that CA's public key. Suppose that company ABC, Inc., is a CA and that you obtain a file named ABCCA.cer, purportedly a self-signed certificate from ABC, authenticating that CA's public key.

Be very careful to ensure that the certificate is valid prior to importing it as a "trusted" certificate! View it first (using the keytool -printcert command or the keytool -import command without the -noprompt option), and make sure that the displayed certificate fingerprint(s) match the expected ones. You can call the person who sent the certificate and compare the fingerprint(s) that you see with the ones that they show or that a secure public key repository shows. Only if the fingerprints are equal is it guaranteed that the certificate has not been replaced in transit with somebody else's (for example, an attacker's) certificate. If such an attack took place and you did not check the certificate before you imported it, you would end up trusting anything the attacker has signed.

If you trust that the certificate is valid, you can add it to your keystore via a command such as the following:

keytool -import -alias alias
        -file ABCCA.cer -keystore storefile
This command creates a "trusted certificate" entry in the keystore whose name is that specified in storefile. The entry contains the data from the file ABCCA.cer, and it is assigned the specified alias.

Importing the Certificate Reply from the CA

Once you've imported the required trusted certificate(s), as described in the previous section, or they are already in your keystore or in the cacerts file, you can import the certificate reply and thereby replace your self-signed certificate with a certificate chain. This chain will be either the one returned by the CA in response to your request (if the CA reply is a chain) or one constructed (if the CA reply is a single certificate) by using the certificate reply and trusted certificates that are already available in the keystore or in the cacerts keystore file.

As an example, suppose that you sent your certificate signing request to VeriSign. You can then import the reply via the following, which assumes that the returned certificate is in the file specified by certReplyFile:

keytool -import -trustcacerts -keystore storefile
   -alias alias
   -file certReplyFile

Type this command on one line.

The certificate reply is validated by using trusted certificates from the keystore and optionally by using the certificates configured in the cacerts keystore file (if the -trustcacerts option is specified). Each certificate in the chain is verified, using the certificate at the next level higher in the chain. You need to trust only the top-level "root" CA certificate in the chain. If you do not already trust the top-level certificate, keytool will display the fingerprint of that certificate and ask you whether you want to trust it.

The new certificate chain of the specified (by alias) entry replaces the old certificate (or chain) associated with this entry. The old chain can be replaced only if a valid keypass, the password used to protect the private key of the entry, is supplied. If no password is provided and if the private key password is different from the keystore password, the user is prompted for it.

For more detailed information about generating CSRs and importing certificate replies, see the keytool documentation on the public java.sun.com web site:

  • keytool documentation with Windows examples
  • keytool documentation with UNIX examples
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Signing Code and Granting It Permissions


Lesson: Signing Code and Granting It Permissions (The Java™ Tutorials > Security Features in Java SE)

Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Trail: Security Features in Java SE
Home Page > Security Features in Java SE
« Previous • Trail • Next »
Lesson: Signing Code and Granting It Permissions

This lesson shows how to use use keytool, jarsigner, Policy Tool and jar to place files into JAR (Java ARchive) files for subsequent signing by the jarsigner tool.

This lesson has two parts. First, you will create and deploy an application. Second; you will act as the recipient of a signed application.

Here are the steps to create and deploy an application:

Note: For convenience, you pretend to be a user/developer named Susan Jones. You need to define Susan Jones when you generate the keys.

  • Put Java class files comprising your application into a JAR file
  • Sign the JAR file
  • Export the public key certificate corresponding to the private key used to sign the JAR file

Here are the steps to grant permissions to an application

Note: For convenience, you pretend to be a user named Ray.

  • You see how the signed application cannot normally read a file when it is run under a security manager.
  • Use keytool to import a certificate into Ray's keystore in an entry aliased by susan
  • Use the Policy Tool to create an entry in Ray's policy file to permit code signed by susan to read the specified file.
  • Finally, you see how the application running under a security manager can now read the file, since it has been granted permission to do so.

For more information about digital signatures, certificates, keystores, and the tools, see the API and Tools Use for Secure Code and File Exchanges lesson.

Important: You need to perform the tasks in this lesson while working in the directory in which you store the sample application, but you should store the data file needed by the application in a different directory. All examples in this trail assume that you are working in the C:\Test directory, and that the data file is in the C:\TestData directory.

If you are working on a UNIX system, substitute your own directory names.

Here are the steps:

  • Steps for the Code Signer

  • Steps for the Code Receiver
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Steps for the Code Signer


Steps for the Code Signer (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
Steps for the Code Signer

The code signer takes the following steps:

  1. Download and Try the Sample Application.

  2. Create a JAR File Containing the Class File, using the jar tool.

  3. Generate Keys (if they don't already exist), using the keytool -genkey command.

    Optional Step Generate a certificate signing request (CSR) for the public key certificate, and import the response from the certification authority (CA). For simplicity (and since you are only pretending to be Susan Jones), this step is omitted. See Generating a Certificate Signing Request (CSR) for a Public Key Certificate for more information.

  4. Sign the JAR File, using the jarsigner tool and the private key.

  5. Export the Public Key Certificate, using the keytool -export command. Then supply the signed JAR file and the certificate to the receiver Ray.

These steps are shown in the following figure.

Signing Your Code
This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Signing Code and Granting It Permissions
Next page: Download and Try the Sample Application


Download and Try the Sample Application (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Section: Steps for the Code Signer
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
Download and Try the Sample Application

This lesson uses a simple application that we provide to you.

  1. Create a file named Count.java on your local computer by either copying or downloading the Count.java source code. The examples in this lesson assume that you place count in the C:\Test directory.

  2. The count application needs to access a text file containing the data it will process. Download a sample data file here, or use any other convenient text file as data.

    Important: Put your data file into a directory other than the directory containing your downloaded count class file. We suggest C:\TestData\data.

    Later in this lesson you will see how an application running under a security manager cannot read a file unless it has explicit permission to do so. However, an application can always read a file from the same directory (or a subdirectory). It does not need explicit permission.

  3. Compile and then run the Count application to see what it does.

    When you run the count application, you need to specify (as an argument) the path name of a file to be read.

    java Count C:\TestData\data

Here is a sample run:

    C:\Test>java Count C:\TestData\data
    Counted 65 chars.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Steps for the Code Signer
Next page: Create a JAR File Containing the Class File


Create a JAR File Containing the Class File (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Section: Steps for the Code Signer
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
Create a JAR File Containing the Class File
Next, create a JAR file containing the Count.class file. Type the following in your command window:
jar cvf Count.jar Count.class
This creates a JAR file, Count.jar, and places the Count.class file inside it.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Download and Try the Sample Application
Next page: Generate Keys


Generate Keys (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Section: Steps for the Code Signer
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
Generate Keys

If a code signer does not yet have a suitable private key for signing the code, the key must first be generated, along with a corresponding public key that can be used by the code receiver's runtime system to verify the signature.

Since this lesson assumes that you don't yet have such keys, you are going to create a keystore named susanstore and create an entry with a newly generated public/private key pair (with the public key in a certificate).

Now pretend that you are Susan Jones and that you work in company ABC's purchasing department. Type the following command in your command window to create a keystore named susanstore and to generate keys for Susan Jones:

keytool -genkey -alias signFiles -keypass kpi135
 -keystore susanstore -storepass ab987c

Note: You must type this command on a single line.

Subparts of the keytool Command

Let's look at what each of the keytool subparts mean.

  • The command for generating keys is -genkey.
  • The -alias signFiles subpart indicates the alias to be used in the future to refer to the keystore entry containing the keys that will be generated.
  • The -keypass kpi135 subpart specifies a password for the private key about to be generated. You will always need this password in order to access the keystore entry containing that key. The entry doesn't have to have its own password. If you don't include a -keypass option, you will be prompted for the key password and given the option of letting it be the same as the keystore password.
  • The -keystore susanstore subpart indicates the name (and optionally path) of the keystore you are creating or already using.
  • The -storepass ab987c subpart indicates the keystore password. If you don't include a -storepass option, you will be prompted for the keystore password.

Note: For security reasons you should not normally set your key or keystore passwords on the command line, because they can be intercepted more easily that way. Instead you should leave off the -keypass and the -storepass options and type your passwords when you are prompted for them.

Distinguished-Name Information

If you use the preceding keystorecommand, you will be prompted for your distinguished-name information. Following are the prompts; the bold indicates what you should type.

What is your first and last name?
  [Unknown]:  Susan Jones
What is the name of your organizational unit?
  [Unknown]:  Purchasing
What is the name of your organization?
  [Unknown]:  ABC
What is the name of your City or Locality?
  [Unknown]:  Cupertino
What is the name of your State or Province?
  [Unknown]:  CA
What is the two-letter country code for this unit?
  [Unknown]:  US
Is <CN=Susan Jones, OU=Purchasing, O=ABC,
    L=Cupertino, ST=CA, C=US> correct?
  [no]:  y

Command Results

The keytool command creates the keystore named susanstore (if it doesn't already exist) in the same directory in which the command is executed and assigns it the password ab987c. The command generates a public/private key pair for the entity whose distinguished name has a common name of Susan Jones and the organizational unit of Purchasing.

The command creates a self-signed certificate that includes the public key and the distinguished-name information. (The distinguised name you supply will be used as the "subject" field in the certificate.) This certificate will be valid for 90 days, the default validity period if you don't specify a -validity option. The certificate is associated with the private key in a keystore entry referred to by the alias signFiles. The private key is assigned the password kpi135.

Note: The command could be shorter if option defaults are accepted or you wish to be prompted for various values. Whenever you execute a keytool command, defaults are used for unspecified options that have default values, and you are prompted for any required values. For the genkey command, options with default values include alias (whose default is mykey), validity (90 days), and keystore (the file named .keystore in your home directory). Required values include dname, storepass, and keypass.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Create a JAR File Containing the Class File
Next page: Sign the JAR File


Sign the JAR File (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Section: Steps for the Code Signer
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
Sign the JAR File
Now you are ready to sign the JAR file. Type the following in your command window to sign the JAR file Count.jar, using the private key in the keystore entry aliased by signFiles, and to name the resulting signed JAR file sCount.jar:
jarsigner -keystore susanstore -signedjar sCount.jar Count.jar signFiles
You will be prompted for the store password (ab987c) and the private key password (kpi135).
Note: The jarsigner tool extracts the certificate from the keystore entry whose alias is signFiles and attaches it to the generated signature of the signed JAR file.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Generate Keys
Next page: Export the Public Key Certificate


Export the Public Key Certificate (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Section: Steps for the Code Signer
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
Export the Public Key Certificate
You now have a signed JAR file sCount.jar. The runtime system of the code receiver (Ray) will need to authenticate the signature when the Count application in the signed JAR file tries to read a file and a policy file grants that permission to this signed code.

In order for the runtime system to authenticate the signature, Ray's keystore needs to have the public key corresponding to the private key used to generate the signature. You supply this by sending Ray a copy of the certificate authenticating the public key. Copy that certificate from the keystore susanstore to a file named SusanJones.cer via the following:

keytool -export -keystore susanstore -alias signFiles -file SusanJones.cer
You will be prompted for the store password (ab987c).
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Sign the JAR File
Next page: Steps for the Code Receiver


Steps for the Code Receiver (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
Steps for the Code Receiver

In this lesson, you will act as the receiver of the signed jar file containing the count.class file. It was signed by Susan. It requests access to your system resources on your system that it normally would not have permission to access.

This procedure requires you to perform the following steps listed below. See the figure below for a flowchart.

  1. Observe the Restricted Application. This application will not be able to access your system resources until you import Susan's certificate and create a policy file.

  2. Import Susan's certificate as a trusted certificate using the keytool -import command, and give it the alias susan.

  3. Set up a policy file to grant permission for the count application signed by susan to read the specified file on your system.

  4. Test your reconfigured count application to verify that with a trusted certificate and access to your new policy file that grants it permission to read files on your system, count can now read your data file.

Steps for Receiving Code
This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Export the Public Key Certificate
Next page: Observe the Restricted Application


Observe the Restricted Application (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Section: Steps for the Code Receiver
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
Observe the Restricted Application
The last part of the Quick Tour of Controlling Applications lesson shows how an application can be run under a security manager by invoking the interpreter with the new -Djava.security.manager command-line argument. But what if the application to be invoked resides inside a JAR file?

One of the interpreter options is the -cp (for class path) option, that lets you specify a search path for application classes and resources. Therefore, to execute the Count application inside the sCount.jar JAR file, specifying the file C:\TestData\data as its argument, you can type the following command while in the directory containing sCount.jar:

java -cp sCount.jar Count C:\TestData\data
To execute the application with a security manager, add -Djava.security.manager, as shown below:
java -Djava.security.manager -cp sCount.jar Count C:\TestData\data
Important: When you run this command, your Java interpreter will throw an exception shown below:
Exception in thread "main" java.security.AccessControlException:
access denied (java.io.FilePermission C:\TestData\data read)
    at java.security.AccessControlContext.checkPermission(Compiled Code)
    at java.security.AccessController.checkPermission(Compiled Code)
    at java.lang.SecurityManager.checkPermission(Compiled Code)
    at java.lang.SecurityManager.checkRead(Compiled Code)
    at java.io.FileInputStream.(Compiled Code)
    at Count.main(Compiled Code)

In this example, AccessControlException reported that the count application does not have permission to read the file C:\TestData\data. Your interpreter raised this exception because it will not allow any application running under a security manager to read a file or to access other resources unless it has explicit permission to do so -- usually specified in a grant statement contained in a policy file.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Steps for the Code Receiver
Next page: Import the Certificate as a Trusted Certificate


Import the Certificate as a Trusted Certificate (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Section: Steps for the Code Receiver
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
Import the Certificate as a Trusted Certificate
Before you can grant the signed code permission to read a specified file, you need to import Susan's certificate as a trusted certificate in your keystore.

Suppose that you have received from Susan

  • the signed JAR file sCount.jar, which contains the Count.class file, and

  • the file SusanJones.cer, which contains the public key certificate for the public key corresponding to the private key used to sign the JAR file.

Even though you created these files and they haven't actually been transported anywhere, you can simulate being someone other than the creater and sender, Susan. Pretend that you are now Ray. Acting as Ray, you will create a keystore named raystore and will use it to import the certificate into an entry with an alias of susan.

A keystore is created whenever you use a keytool command specifying a keystore that doesn't yet exist. Thus we can create the raystore and import the certificate via a single keytool command. Do the following in your command window.

  1. Go to the directory containing the public key certificate file SusanJones.cer. (You should actually already be there, since this lesson assumes that you stay in a single directory throughout.)

  2. Type the following command on one line:
    keytool -import -alias susan
   -file SusanJones.cer -keystore raystore
Since the keystore doesn't yet exist, it will be created, and you will be prompted for a keystore password; type whatever password you want.

The keytool command will print out the certificate information and ask you to verify it, for example, by comparing the displayed certificate fingerprints with those obtained from another (trusted) source of information. (Each fingerprint is a relatively short number that uniquely and reliably identifies the certificate.) For example, in the real world you might call up Susan and ask her what the fingerprints should be. She can get the fingerprints of the SusanJones.cer file she created by executing the command

keytool -printcert -file SusanJones.cer
If the fingerprints she sees are the same as the ones reported to you by keytool, the certificate has not been modified in transit. In that case you let keytool proceed with placing a trusted certificate entry in the keystore. The entry contains the public key certificate data from the file SusanJones.cer and is assigned the alias susan.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Observe the Restricted Application
Next page: Set Up a Policy File to Grant the Required Permission


Set Up a Policy File to Grant the Required Permission (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Section: Steps for the Code Receiver
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
Set Up a Policy File to Grant the Required Permission

Next, you will use the Policy Tool to create a policy file named raypolicy and in it grant a permission to code from a signed JAR file.

The JAR file must have been signed using the private key corresponding to the public key imported into Ray's keystore (raystore) in the previous step. The certificate containing the public key is aliased by susan in the keystore. We will grant such code permission to read any file in the C:\TestData\ directory.

The steps are:

  1. Start Policy Tool

  2. Specify the Keystore

  3. Add a Policy Entry with a SignedBy Alias

  4. Save the Policy File

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Import the Certificate as a Trusted Certificate
Next page: Start Policy Tool


Start Policy Tool (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Section: Steps for the Code Receiver
Subsection: Set Up a Policy File to Grant the Required Permission
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
Start Policy Tool
To start Policy Tool, simply type the following at the command line:
policytool

This brings up the Policy Tool window. Whenever Policy Tool is started, it tries to fill in this window with policy information from what is sometimes referred to as the "user policy file," which by default is a file named .java.policy in your home directory. If Policy Tool cannot find the user policy file, it reports the situation and displays a blank Policy Tool window (that is, a window with headings and buttons but no data in it, as shown in the following figure.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

You will create and work on a policy file other than the user policy file, since the lessons of this trail don't expect modifications to be made to your official user policy file.

Assuming that you see the blank Policy Tool window (if not, select New in the File menu), you can immediately proceed to create a new policy file.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Set Up a Policy File to Grant the Required Permission
Next page: Specify the Keystore


Specify the Keystore (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Section: Steps for the Code Receiver
Subsection: Set Up a Policy File to Grant the Required Permission
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
Specify the Keystore
For this lesson you will grant all code in JAR files signed by the alias susan read access to all files in the C:\TestData\ directory. You need to
  1. Specify the keystore containing the certificate information aliased by susan

  2. Create the policy entry granting the permission

The keystore is the one named raystore created in the Import the Certificate as a Trusted Certificate step.

To specify the keystore, choose the Change Keystore command in the Edit menu of the main Policy Tool window. This brings up a dialog box in which you can specify the keystore URL and the keystore type.

To specify the keystore named raystore in the Test directory on the C: drive, type the following file URL into the text box labeled New KeyStore URL

file:/C:/Test/raystore
You can leave the text box labeled New KeyStore Type blank if the keystore type is the default one, as specified in the security properties file. Your keystore will be the default type, so leave the text box blank. The result is shown in the following figure.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Note: The New KeyStore URL value is a URL and thus should always use slashes (never backslashes) as the directory separator.

When you are done specifying the keystore URL, choose OK. The text box labeled Keystore is now filled in with the URL:

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Next, you need to specify the new policy entry.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Start Policy Tool
Next page: Add a Policy Entry with a SignedBy Alias


Add a Policy Entry with a SignedBy Alias (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Section: Steps for the Code Receiver
Subsection: Set Up a Policy File to Grant the Required Permission
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
Add a Policy Entry with a SignedBy Alias
To grant code signed by susan permission to read any files in the C:\TestData directory, you need to create a policy entry granting this permission. Note that "Code signed by susan" is an abbreviated way of saying "Code in a class file contained in a JAR file, where the JAR file was signed using the private key corresponding to the public key that appears in a keystore certificate in an entry aliased by susan."

Choose the Add Policy Entry button in the main Policy Tool window. This brings up the Policy Entry dialog box:

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Using this dialog box, type the following alias into the SignedBy text box:
susan

Leave the CodeBase text box blank, to grant all code signed by susan the permission, no matter where it comes from.

Note: If you wanted to restrict the permission to just code signed by susan that comes from the C:\Test\ directory, you would type the following URL into the CodeBase text box:
file:/C:/Test/*

To add the permission, choose the Add Permission button. This brings up the Permissions dialog box.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Do the following.

  1. Choose File Permission from the Permission drop-down list. The complete permission type name (java.io.FilePermission) now appears in the text box to the right of the drop-down list.

  2. Type the following in the text box to the right of the list labeled Target Name to specify all files in the C:\TestData\ directory:
    C:\TestData\*
  3. Specify read access by choosing the read option from the Actions drop-down list.
Now the Permissions dialog box looks like the following.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Choose the OK button. The new permission appears in a line in the Policy Entry dialog, as follows.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Note: Each backslash in the file path you typed has been replaced with two backslashes, for your convenience. Strings in a policy file are processed by a tokenizer that allows \ to be used as an escape character (for example, \n to indicate a new line), so the policy file requires two backslashes to indicate a single backslash. If you use single backslashes as your directory separators, Policy Tool automatically converts them to double backslashes for you.

You are now done specifying this policy entry, so choose the Done button in the Policy Entry dialog. The Policy Tool window now contains a line representing the policy entry, showing the SignedBy value, as shown in the following figure.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Specify the Keystore
Next page: Save the Policy File


Save the Policy File (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Section: Steps for the Code Receiver
Subsection: Set Up a Policy File to Grant the Required Permission
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
Save the Policy File

To save the new policy file you've been creating, choose the Save As command from the File menu. This brings up the Save As dialog box.

Navigate the directory structure to get to the directory in which to save the policy file: the Test directory on the C: drive. Type the file name

raypolicy
Then choose the Save button. The policy file is now saved, and its name and path are shown in the text box labeled Policy File, as shown in the following figure.

This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

Then exit Policy Tool by selecting the Exit command from the File menu.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Add a Policy Entry with a SignedBy Alias
Next page: See the Policy File Effects


See the Policy File Effects (The Java™ Tutorials > Security Features in Java SE > Signing Code and Granting It Permissions)

Trail: Security Features in Java SE
Lesson: Signing Code and Granting It Permissions
Section: Steps for the Code Receiver
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Home Page > Security Features in Java SE > Signing Code and Granting It Permissions
« Previous • Trail • Next »
See the Policy File Effects
In the previous steps you created an entry in the raypolicy policy file granting code signed by susan permission to read files from the C:\TestData\ directory (or the testdata directory in your home directory if you're working on UNIX). Now you should be able to successfully execute the Count program to read and to count the characters in a file from the specified directory, even when you run the application with a security manager.

As described at the end of the Quick Tour of Controlling Applets lesson, there are two possible ways you can have the raypolicy file be considered as part of the overall policy, in addition to the policy files specified in the security properties file. The first approach is to specify the additional policy file in a property passed to the runtime system. The second approach is to add a line in the security properties file specifying the additional policy file.

Approach 1

You can use a -Djava.security.policy command-line argument to specify a policy file that should be used in addition to or instead of the ones specified in the security properties file.

To run the Count application and have the raypolicy policy file included, type the following while in the directory containing the sCount.jar and raypolicy files:

java -Djava.security.manager -Djava.security.policy=raypolicy
  -cp sCount.jar Count C:\TestData\data

Note: The command should be typed on a single line, with a space between raypolicy and -cp.

The program should report the number of characters in the specified file.

If it still reports an error, something is wrong in the policy file. Use the Policy Tool to check the permission you just created in the previous step, and change any typos or other errors.

Approach 2

You can specify a number of URLs -- including ones of the form "http://" -- in policy.url.n properties in the security properties file, and all the designated policy files will get loaded.

So one way to have your raypolicy file's policy entries considered by the interpreter is to add an entry indicating that file in the security properties file.

Important: If you are running your own copy of the JDK, you can easily edit your security properties file. If you are running a version shared with others, you may only be able to modify the system-wide security properties file if you have write access to it or if you ask your system administrator to modify the file when appropriate. However, it's probably not appropriate for you to make modifications to a system-wide policy file for this tutorial test; we suggest that you just read the following to see how it's done or that you install your own private version of the JDK to use for the tutorial lessons.
The security properties file is located at
  Windows:
    java.home\lib\security\java.security
  UNIX:
    java.home/lib/security/java.security
The java.home portion indicates the directory into which the JRE was installed.

To modify the security properties file, open it in an editor suitable for editing an ASCII text file. Then add the following line after the line starting with policy.url.2:

  Windows:
    policy.url.3=file:/C:/Test/raypolicy
  UNIX:
    policy.url.3=file:${user.home}/test/raypolicy

On a UNIX system you can alternatively explicitly specify your home directory, as in

policy.url.3=file:/home/susanj/test/raypolicy
Next, in your command window, go to the directory containing the sCount.jar file, that is, the C:\Test or ~/test directory. Type the following command on one line:
java -Djava.security.manager
        -cp sCount.jar Count C:\TestData\data

As with approach 1, if the program still reports an error, something is wrong with the policy file. Use the Policy Tool to check the permission you just created in the previous step, and change any typos or other errors.

Important: Before continuing, you may want to delete the line you just added in the security properties file (or comment it out), since you probably do not want the raypolicy file included when you are not running the tutorial lessons.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Save the Policy File
Next page: Exchanging Files


Lesson: Exchanging Files (The Java™ Tutorials > Security Features in Java SE)

Exchanging Files
Steps for the Contract Sender
Create a JAR File Containing the Contract
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Contract Receiver
Import the Certificate as a Trusted Certificate
Verify the JAR File Signature
Trail: Security Features in Java SE
Home Page > Security Features in Java SE
« Previous • Trail • Next »
Lesson: Exchanging Files

If you want to electronically send an important document, (like a Contract) to someone else, it is a good idea to digitally "sign" the document, so your recipient can check that the document indeed came from you and was not altered in transit.

This lesson shows you how to use Security tools for the exchange of an important document, in this case a contract.

You first pretend that you are the contract sender, Stan Smith. This lesson shows the steps Stan would use to put the contract in a JAR file, sign it, and export the public key certificate for the public key corresponding to the private key used to sign the JAR file.

Then you pretend that you are Ruth, who has received the signed JAR file and the certificate. You'll use keytool to import the certificate into Ruth's keystore in an entry aliased by stan, and use the jarsigner tool to verify the signature.

For further information about digital signatures, certificates, keystores, and the tools, see the API and Tools Use for Secure Code and File Exchanges lesson.

Note: This lesson assumes that you execute all commands from within the same directory.

Here are the steps:

  • Steps for the Contract Sender

  • Steps for the Contract Receiver
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Steps for the Contract Sender


Steps for the Contract Sender (The Java™ Tutorials > Security Features in Java SE > Exchanging Files)

Trail: Security Features in Java SE
Lesson: Exchanging Files
Exchanging Files
Steps for the Contract Sender
Create a JAR File Containing the Contract
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Contract Receiver
Import the Certificate as a Trusted Certificate
Verify the JAR File Signature
Home Page > Security Features in Java SE > Exchanging Files
« Previous • Trail • Next »
Steps for the Contract Sender
The steps outlined here for the contract sender are basically the same as those listed for a code signer in the Signing Code and Granting It Permissions lesson. Here, however, you are pretending to be Stan Smith rather than Susan Jones and are storing a data file rather than a class file in the JAR file to be signed.

The steps you take as the contract sender are as follows.

  1. Create a JAR File Containing the Contract, using the jar tool.

  2. Generate Keys (if they don't already exist), using the keytool -genkey command.

    Optional Step: Generate a certificate signing request (CSR) for the public key certificate, and import the response from the certification authority. For simplicity and since you are only pretending to be Stan Smith, this step is omitted. See Generating a Certificate Signing Request (CSR) for a Public Key Certificate for more information.

  3. Sign the JAR File, using the jarsigner tool and the private key generated in step 2.

  4. Export the Public Key Certificate, using the keytool -export command. Then supply the signed JAR file and the certificate to the receiver, Ruth.

Steps for the Contract Sender
This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Exchanging Files
Next page: Create a JAR File Containing the Contract


Create a JAR File Containing the Contract (The Java™ Tutorials > Security Features in Java SE > Exchanging Files)

Trail: Security Features in Java SE
Lesson: Exchanging Files
Section: Steps for the Contract Sender
Exchanging Files
Steps for the Contract Sender
Create a JAR File Containing the Contract
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Contract Receiver
Import the Certificate as a Trusted Certificate
Verify the JAR File Signature
Home Page > Security Features in Java SE > Exchanging Files
« Previous • Trail • Next »
Create a JAR File Containing the Contract

The first thing you need is a contract file. You can download and use this very basic sample file named contract. Or you can use any other file you like. Just be sure to name the file contract so it will work with the commands specified in this lesson.

Once you've got the contract file, place it into a JAR file. In your command window type the following:

jar cvf Contract.jar contract
This command creates a JAR file named Contract.jar and places the contract file inside it.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Steps for the Contract Sender
Next page: Generate Keys


Generate Keys (The Java™ Tutorials > Security Features in Java SE > Exchanging Files)

Trail: Security Features in Java SE
Lesson: Exchanging Files
Section: Steps for the Contract Sender
Exchanging Files
Steps for the Contract Sender
Create a JAR File Containing the Contract
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Contract Receiver
Import the Certificate as a Trusted Certificate
Verify the JAR File Signature
Home Page > Security Features in Java SE > Exchanging Files
« Previous • Trail • Next »
Generate Keys

Before signing the Contract.jar JAR file containing the contract file, you need to generate keys, if you don't already have suitable keys available. You need to sign your JAR file using your private key, and your recipient needs your corresponding public key to verify your signature.

This lesson assumes that you don't have a key pair yet. You are going to create a keystore named stanstore and create an entry with a newly generated public/private key pair (with the public key in a certificate).

Now pretend that you are Stan Smith and that you work in the legal department of XYZ corporation. Type the following in your command window to create a keystore named stanstore and to generate keys for Stan Smith:

keytool -genkey -alias signLegal -keystore stanstore

The keystore tool prompts you for a keystore password, your distinguished-name information, and the key password. Following are the prompts; the bold indicates what you should type.

Enter keystore password:  balloon53
What is your first and last name?
  [Unknown]:  Stan Smith
What is the name of your organizational unit?
  [Unknown]:  Legal
What is the name of your organization?
  [Unknown]:  XYZ
What is the name of your City or Locality?
  [Unknown]:  New York
What is the name of your State or Province?
  [Unknown]:  NY
What is the two-letter country code for this unit?
  [Unknown]:  US
Is <CN=Stan Smith, OU=Legal, O=XYZ, L=New York,
       ST=NY, C=US> correct?
  [no]:  y

Enter key password for
        (RETURN if same as keystore password):  cat876

The preceding keytool command creates the keystore named stanstore in the same directory in which the command is executed (assuming that the specified keystore doesn't already exist) and assigns it the password balloon53. The command generates a public/private key pair for the entity whose distinguished name has a common name of Stan Smith and an organizational unit of Legal.

The self-signed certificate you have just created includes the public key and the distinguished-name information. (A self-signed certificate is one signed by the private key corresponding to the public key in the certificate.) This certificate is valid for 90 days. This is the default validity period if you don't specify a -validity option. The certificate is associated with the private key in a keystore entry referred to by the alias signLegal. The private key is assigned the password cat876.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Create a JAR File Containing the Contract
Next page: Sign the JAR File


Sign the JAR File (The Java™ Tutorials > Security Features in Java SE > Exchanging Files)

Trail: Security Features in Java SE
Lesson: Exchanging Files
Section: Steps for the Contract Sender
Exchanging Files
Steps for the Contract Sender
Create a JAR File Containing the Contract
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Contract Receiver
Import the Certificate as a Trusted Certificate
Verify the JAR File Signature
Home Page > Security Features in Java SE > Exchanging Files
« Previous • Trail • Next »
Sign the JAR File
Now you are ready to sign the JAR file.

Type the following in your command window to sign the JAR file Contract.jar, using the private key in the keystore entry aliased by signLegal, and to name the resulting signed JAR file sContract.jar:

jarsigner -keystore stanstore -signedjar sContract.jar
    Contract.jar signLegal
(Type all that on one line.)

You will be prompted for the store password (balloon53) and the private key password (cat876).

The jarsigner tool extracts the certificate from the keystore entry whose alias is signLegal and attaches it to the generated signature of the signed JAR file.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Generate Keys
Next page: Export the Public Key Certificate


Export the Public Key Certificate (The Java™ Tutorials > Security Features in Java SE > Exchanging Files)

Trail: Security Features in Java SE
Lesson: Exchanging Files
Section: Steps for the Contract Sender
Exchanging Files
Steps for the Contract Sender
Create a JAR File Containing the Contract
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Contract Receiver
Import the Certificate as a Trusted Certificate
Verify the JAR File Signature
Home Page > Security Features in Java SE > Exchanging Files
« Previous • Trail • Next »
Export the Public Key Certificate
You now have a signed JAR file sContract.jar. Recipients wanting to use this file will also want to authenticate your signature. To do this, they need the public key that corresponds to the private key you used to generate your signature. You supply your public key by sending them a copy of the certificate that contains your public key. Copy that certificate from the keystore stanstore to a file named StanSmith.cer via the following:
keytool -export -keystore stanstore -alias signLegal -file StanSmith.cer
You will be prompted for the store password (balloon53).

Once they have that certificate and the signed JAR file, your recipient can use the jarsigner tool to authenticate your signature. See Steps for the Contract Receiver .

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Sign the JAR File
Next page: Steps for the Contract Receiver


Steps for the Contract Receiver (The Java™ Tutorials > Security Features in Java SE > Exchanging Files)

Trail: Security Features in Java SE
Lesson: Exchanging Files
Exchanging Files
Steps for the Contract Sender
Create a JAR File Containing the Contract
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Contract Receiver
Import the Certificate as a Trusted Certificate
Verify the JAR File Signature
Home Page > Security Features in Java SE > Exchanging Files
« Previous • Trail • Next »
Steps for the Contract Receiver

Now acting as Ruth, who receives the signed JAR file and the certificate file from Stan, perform the following steps, as shown in the figure.

  1. Import the Certificate as a Trusted Certificate, using the keytool -import command.

  2. Verify the JAR File Signature, using the jarsigner tool.

Steps for the Contract Receiver
This figure has been reduced to fit on the page.
Click the image to view it at its natural size.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Export the Public Key Certificate
Next page: Import the Certificate as a Trusted Certificate


Import the Certificate as a Trusted Certificate (The Java™ Tutorials > Security Features in Java SE > Exchanging Files)

Trail: Security Features in Java SE
Lesson: Exchanging Files
Section: Steps for the Contract Receiver
Exchanging Files
Steps for the Contract Sender
Create a JAR File Containing the Contract
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Contract Receiver
Import the Certificate as a Trusted Certificate
Verify the JAR File Signature
Home Page > Security Features in Java SE > Exchanging Files
« Previous • Trail • Next »
Import the Certificate as a Trusted Certificate
W

Suppose that you are Ruth and have received from Stan Smith

  • The signed JAR file sContract.jar containing a contract

  • The file StanSmith.cer containing the public key certificate for the public key corresponding to the private key used to sign the JAR file

Before you can use the jarsigner tool to check the authenticity of the JAR file's signature, you need to import Stan's certificate into your keystore.

Even though you (acting as Stan) created these files and they haven't actually been transported anywhere, you can simulate being someone other than the creater and sender, Stan. Acting as Ruth, type the following command to create a keystore named ruthstore and import the certificate into an entry with an alias of stan.

keytool -import -alias stan -file StanSmith.cer -keystore ruthstore
Since the keystore doesn't yet exist, keytool will create it for you. It will prompt you for a keystore password.

The keytool prints the certificate information and asks you to verify it; For example, by comparing the displayed certificate fingerprints with those obtained from another (trusted) source of information. (Each fingerprint is a relatively short number that uniquely and reliably identifies the certificate.) For example, in the real world you can phone Stan and ask him what the fingerprints should be. He can get the fingerprints of the StanSmith.cer file he created by executing the command

keytool -printcert -file StanSmith.cer
If the fingerprints he sees are the same as the ones reported to you by keytool, then you both can assume that the certificate has not been modified in transit. You can safely let keytool procede to place a "trusted certificate" entry into your keystore. This entry contains the public key certificate data from the file StanSmith.cer. keytoolassigns the alias stan to this new entry.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Steps for the Contract Receiver
Next page: Verify the JAR File Signature


Verify the JAR File Signature (The Java™ Tutorials > Security Features in Java SE > Exchanging Files)

Trail: Security Features in Java SE
Lesson: Exchanging Files
Section: Steps for the Contract Receiver
Exchanging Files
Steps for the Contract Sender
Create a JAR File Containing the Contract
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Contract Receiver
Import the Certificate as a Trusted Certificate
Verify the JAR File Signature
Home Page > Security Features in Java SE > Exchanging Files
« Previous • Trail • Next »
Verify the JAR File Signature
Acting as Ruth, you have now imported Stan's public key certificate into the ruthstore keystore as a "trusted certificate." You can now use the jarsigner tool to verify the authenticity of the JAR file signature.

When you verify a signed JAR file, you verify that the signature is valid and that the JAR file has not been tampered with. You can do this for the sContract.jar file via the following command:

jarsigner -verify -verbose -keystore ruthstore sContract.jar
You should see something like the following:
       183 Fri Jul 31 10:49:54 PDT 1998 META-INF/SIGNLEGAL.SF
       1542 Fri Jul 31 10:49:54 PDT 1998 META-INF/SIGNLEGAL.DSA
       0 Fri Jul 31 10:49:18 PDT 1998 META-INF/
smk    1147 Wed Jul 29 16:06:12 PDT 1998 contract

 s = signature was verified
 m = entry is listed in manifest
 k = at least one certificate was found in keystore
 i = at least one certificate was found in identity scope

jar verified.
Be sure to run the command with the -verbose option to get enough information to ensure the following:
  • the contract file is among the files in the JAR file that were signed and its signature was verified (that's what the s signifies)

  • the public key used to verify the signature is in the specified keystore and thus trusted by you (that's what the k signifies).
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Import the Certificate as a Trusted Certificate
Next page: Generating and Verifying Signatures


Lesson: Generating and Verifying Signatures (The Java™ Tutorials > Security Features in Java SE)

Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Trail: Security Features in Java SE
Home Page > Security Features in Java SE
« Previous • Trail • Next »
Lesson: Generating and Verifying Signatures

This lesson walks you through the steps necessary to use the JDK Security API to generate a digital signature for data and to verify that a signature is authentic. This lesson is meant for developers who wish to incorporate security functionality into their programs, including cryptography services.

This lesson demonstrates the use of the JDK Security API with respect to signing documents. The lesson shows what one program, executed by the person who has the original document, would do to generate keys, generate a digital signature for the document using the private key, and export the public key and the signature to files.

Then it shows an example of another program, executed by the receiver of the document, signature, and public key. It shows how the program could import the public key and verify the authenticity of the signature. The lesson also discusses and demonstrates possible alternative approaches and methods of supplying and importing keys, including in certificates.

For further information about the concepts and terminology (digital signatures, certificates, keystores), see the API and Tools Use for Secure Code and File Exchanges lesson.

In this lesson you create two basic applications, one for the digital signature generation and the other for the verification. This is followed by a discussion and demonstration of potential enhancements. The lesson contains three sections.

  • Generating a Digital Signature shows using the API to generate keys and a digital signature for data using the private key and to export the public key and the signature to files. The application gets the data file name from the command line.

  • Verifying a Digital Signature shows using the API to import a public key and a signature that is alleged to be the signature of a specified data file and to verify the authenticity of the signature. The data, public key, and signature file names are specified on the command line.

  • Weaknesses and Alternatives discusses potential weaknesses of the approach used by the basic programs. It then presents and demonstrates possible alternative approaches and methods of supplying and importing keys, including the use of files containing encoded key bytes and the use of certificates containing public keys.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Generating a Digital Signature


Generating a Digital Signature (The Java™ Tutorials > Security Features in Java SE > Generating and Verifying Signatures)

Trail: Security Features in Java SE
Lesson: Generating and Verifying Signatures
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Home Page > Security Features in Java SE > Generating and Verifying Signatures
« Previous • Trail • Next »
Generating a Digital Signature
The GenSig program you are about to create will use the JDK Security API to generate keys and a digital signature for data using the private key and to export the public key and the signature to files. The application gets the data file name from the command line.

The following steps create the GenSig sample program.

  1. Prepare Initial Program Structure

    Create a text file named GenSig.java. Type in the initial program structure (import statements, class name, main method, and so on).

  2. Generate Public and Private Keys

    Generate a key pair (public key and private key). The private key is needed for signing the data. The public key will be used by the VerSig program for verifying the signature.

  3. Sign the Data

    Get a Signature object and initialize it for signing. Supply it with the data to be signed, and generate the signature.

  4. Save the Signature and the Public Key in Files

    Save the signature bytes in one file and the public key bytes in another.

  5. Compile and Run the Program
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Generating and Verifying Signatures
Next page: Prepare Initial Program Structure


Prepare Initial Program Structure (The Java™ Tutorials > Security Features in Java SE > Generating and Verifying Signatures)

Trail: Security Features in Java SE
Lesson: Generating and Verifying Signatures
Section: Generating a Digital Signature
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Home Page > Security Features in Java SE > Generating and Verifying Signatures
« Previous • Trail • Next »
Prepare Initial Program Structure

Here's the basic structure of the GenSig program. Place it in a file called GenSig.java.

import java.io.*;
import java.security.*;

class GenSig {

    public static void main(String[] args) {

        /* Generate a DSA signature */

        if (args.length != 1) {
            System.out.println("Usage: GenSig nameOfFileToSign");
            }
        else try {

        // the rest of the code goes here

        } catch (Exception e) {
            System.err.println("Caught exception " + e.toString());
        }
    }

}

Notes:
  • The methods for signing data are in the java.security package, so the program imports everything from that package. The program also imports the java.io package, which contains the methods needed to input the file data to be signed.

  • A single argument is expected, specifying the data file to be signed.

  • The code written in subsequent steps will go between the try and the catch blocks.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Generating a Digital Signature
Next page: Generate Public and Private Keys


Generate Public and Private Keys (The Java™ Tutorials > Security Features in Java SE > Generating and Verifying Signatures)

Trail: Security Features in Java SE
Lesson: Generating and Verifying Signatures
Section: Generating a Digital Signature
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Home Page > Security Features in Java SE > Generating and Verifying Signatures
« Previous • Trail • Next »
Generate Public and Private Keys

In order to be able to create a digital signature, you need a private key. (Its corresponding public key will be needed in order to verify the authenticity of the signature.)

In some cases the key pair (private key and corresponding public key) are already available in files. In that case the program can import and use the private key for signing, as shown in Weaknesses and Alternatives.

In other cases the program needs to generate the key pair. A key pair is generated by using the KeyPairGenerator class.

In this example you will generate a public/private key pair for the Digital Signature Algorithm (DSA). You will generate keys with a 1024-bit length.

Generating a key pair requires several steps:

Create a Key Pair Generator

The first step is to get a key-pair generator object for generating keys for the DSA signature algorithm.

As with all engine classes, the way to get a KeyPairGenerator object for a particular type of algorithm is to call the getInstance static factory method on the KeyPairGenerator class. This method has two forms, both of which hava a String algorithm first argument; one form also has a String provider second argument.

A caller may thus optionally specify the name of a provider, which will guarantee that the implementation of the algorithm requested is from the named provider. The sample code of this lesson always specifies the default SUN provider built into the JDK.

Put the following statement after the

else try {
line in the file created in the previous step, Prepare Initial Program Structure:
KeyPairGenerator keyGen =
    KeyPairGenerator.getInstance("DSA", "SUN");

Initialize the Key-Pair Generator

The next step is to initialize the key-pair generator. All key-pair generators share the concepts of a keysize and a source of randomness. The KeyPairGenerator class has an initialize method that takes these two types of arguments.

The keysize for a DSA key generator is the key length (in bits), which you will set to 1024.

The source of randomness must be an instance of the SecureRandom class. This example requests one that uses the SHA1PRNG pseudo-random-number generation algorithm, as provided by the built-in SUN provider. The example then passes this SecureRandom instance to the key-pair generator initialization method.

SecureRandom random =
    SecureRandom.getInstance("SHA1PRNG", "SUN");
keyGen.initialize(1024, random);

Note: The SecureRandom implementation attempts to completely randomize the internal state of the generator itself unless the caller follows the call to the getInstance method with a call to the setSeed method. So if you had a specific seed value that you wanted used, you would call the following prior to the initialize call:

random.setSeed(seed);

Generate the Pair of Keys

The final step is to generate the key pair and to store the keys in PrivateKey and PublicKey objects.
KeyPair pair = keyGen.generateKeyPair();
PrivateKey priv = pair.getPrivate();
PublicKey pub = pair.getPublic();

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Prepare Initial Program Structure
Next page: Sign the Data


Sign the Data (The Java™ Tutorials > Security Features in Java SE > Generating and Verifying Signatures)

Trail: Security Features in Java SE
Lesson: Generating and Verifying Signatures
Section: Generating a Digital Signature
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Home Page > Security Features in Java SE > Generating and Verifying Signatures
« Previous • Trail • Next »
Sign the Data

Now that you have created a public key and a private key, you are ready to sign the data. In this example you will sign the data contained in a file. GenSig gets the file name from the command line. A digital signature is created (or verified) using an instance of the Signature class.

Signing data, generating a digital signature for that data, is done with the following steps.

Get a Signature Object:

The following gets a Signature object for generating or verifying signatures using the DSA algorithm, the same algorithm for which the program generated keys in the previous step, Generate Public and Private Keys.
Signature dsa = Signature.getInstance("SHA1withDSA", "SUN");

Note: When specifying the signature algorithm name, you should also include the name of the message digest algorithm used by the signature algorithm. SHA1withDSA is a way of specifying the DSA signature algorithm, using the SHA-1 message digest algorithm.

Initialize the Signature Object

Before a Signature object can be used for signing or verifying, it must be initialized. The initialization method for signing requires a private key. Use the private key placed into the PrivateKey object named priv in the previous step.

dsa.initSign(priv);

Supply the Signature Object the Data to Be Signed

This program will use the data from the file whose name is specified as the first (and only) command line argument. The program will read in the data a buffer at a time and will supply it to the Signature object by calling the update method.
FileInputStream fis = new FileInputStream(args[0]);
BufferedInputStream bufin = new BufferedInputStream(fis);
byte[] buffer = new byte[1024];
int len;
while (bufin.available() != 0) {
    len = bufin.read(buffer);
    dsa.update(buffer, 0, len);
};
bufin.close();

Generate the Signature

Once all of the data has been supplied to the Signature object, you can generate the digital signature of that data.

byte[] realSig = dsa.sign();
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Generate Public and Private Keys
Next page: Save the Signature and the Public Key in Files


Save the Signature and the Public Key in Files (The Java™ Tutorials > Security Features in Java SE > Generating and Verifying Signatures)

Trail: Security Features in Java SE
Lesson: Generating and Verifying Signatures
Section: Generating a Digital Signature
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Home Page > Security Features in Java SE > Generating and Verifying Signatures
« Previous • Trail • Next »
Save the Signature and the Public Key in Files
Now that you have generated a signature for some data, you need to save the signature bytes in one file and the public key bytes in another so you can send (via modem, floppy, mail, and so on) someone else
  • the data for which the signature was generated,

  • the signature, and

  • the public key
The receiver can verify that the data came from you and was not modified in transit by running the VerSig program you will generate in the upcoming Verifying a Digital Signature steps. That program uses the public key to verify that the signature received is the true signature for the data received.

Recall that the signature was placed in a byte array named realSig. You can save the signature bytes in a file named sig via the following.

        /* save the signature in a file */
        FileOutputStream sigfos = new FileOutputStream("sig");
        sigfos.write(realSig);
        sigfos.close();
Recall from the Generate Public and Private Keys step that the public key was placed in a PublicKey object named pub. You can get the encoded key bytes by calling the getEncoded method and then store the encoded bytes in a file. You can name the file whatever you want. If, for example, your name is Susan, you might name it something like suepk (for "Sue's public key"), as in the following:
        /* save the public key in a file */
        byte[] key = pub.getEncoded();
        FileOutputStream keyfos = new FileOutputStream("suepk");
        keyfos.write(key);
        keyfos.close();
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Sign the Data
Next page: Compile and Run the Program


Compile and Run the Program (The Java™ Tutorials > Security Features in Java SE > Generating and Verifying Signatures)

Trail: Security Features in Java SE
Lesson: Generating and Verifying Signatures
Section: Generating a Digital Signature
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Home Page > Security Features in Java SE > Generating and Verifying Signatures
« Previous • Trail • Next »
Compile and Run the Program

Here is the complete source code for the GenSig.java program, with some comments added. Compile and run it. Remember, you need to specify the name of a file to be signed, as in

java GenSig data

You can download and use this sample file named data or any other file you like. The file will not be modified. It will be read so that a signature can be generated for it.

After executing the program, you should see the saved suepk (public key) and sig (signature) files.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Save the Signature and the Public Key in Files
Next page: Verifying a Digital Signature


Verifying a Digital Signature (The Java™ Tutorials > Security Features in Java SE > Generating and Verifying Signatures)

Trail: Security Features in Java SE
Lesson: Generating and Verifying Signatures
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Home Page > Security Features in Java SE > Generating and Verifying Signatures
« Previous • Trail • Next »
Verifying a Digital Signature

If you have data for which a digital signature was generated, you can verify the authenticity of the signature. To do so, you need

  • the data

  • the signature

  • the public key corresponding to the private key used to sign the data

In this example you write a VerSig program to verify the signature generated by the GenSig program. This demonstrates the steps required to verify the authenticity of an alleged signature.

VerSig imports a public key and a signature that is alleged to be the signature of a specified data file and then verifies the authenticity of the signature. The public key, signature, and data file names are specified on the command line.

The steps to create the VerSig sample program to import the files and to verify the signature are the following.

  1. Prepare Initial Program Structure

    Create a text file named VerSig.java. Type in the initial program structure (import statements, class name, main method, and so on).

  2. Input and Convert the Encoded Public Key Bytes

    Import the encoded public key bytes from the file specified as the first command line argument and convert them to a PublicKey.

  3. Input the Signature Bytes

    Input the signature bytes from the file specified as the second command line argument.

  4. Verify the Signature

    Get a Signature object and initialize it with the public key for verifying the signature. Supply it with the data whose signature is to be verified (from the file specified as the third command line argument), and verify the signature.

  5. Compile and Run the Program
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Compile and Run the Program
Next page: Prepare Initial Program Structure


Prepare Initial Program Structure (The Java™ Tutorials > Security Features in Java SE > Generating and Verifying Signatures)

Trail: Security Features in Java SE
Lesson: Generating and Verifying Signatures
Section: Verifying a Digital Signature
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Home Page > Security Features in Java SE > Generating and Verifying Signatures
« Previous • Trail • Next »
Prepare Initial Program Structure

Here's the basic structure of the VerSig program created in the following parts of this lesson. Place this program structure in a file called VerSig.java.

import java.io.*;
import java.security.*;
import java.security.spec.*;

class VerSig {

    public static void main(String[] args) {

        /* Verify a DSA signature */

        if (args.length != 3) {
            System.out.println("Usage: VerSig publickeyfile signaturefile datafile");
            }
        else try{

        // the rest of the code goes here

        } catch (Exception e) {
            System.err.println("Caught exception " + e.toString());
        }
    }

}

Notes:
  • The methods for verifying data are in the java.security package, so the program imports everything from that package. The program also imports the java.io package for methods needed to input the file data to be signed, as well as the java.security.spec package, which contains the X509EncodedKeySpec class.

  • Three arguments are expected, specifying the public key, the signature, and the data files.

  • The code written in subsequent steps of this lesson will go between the try and the catch blocks.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Verifying a Digital Signature
Next page: Input and Convert the Encoded Public Key Bytes


Input and Convert the Encoded Public Key Bytes (The Java™ Tutorials > Security Features in Java SE > Generating and Verifying Signatures)

Trail: Security Features in Java SE
Lesson: Generating and Verifying Signatures
Section: Verifying a Digital Signature
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Home Page > Security Features in Java SE > Generating and Verifying Signatures
« Previous • Trail • Next »
Input and Convert the Encoded Public Key Bytes
Next, VerSig needs to import the encoded public key bytes from the file specified as the first command line argument and to convert them to a PublicKey. A PublicKey is needed because that is what the Signature initVerify method requires in order to initialize the Signature object for verification.

First, read in the encoded public key bytes.

        FileInputStream keyfis = new FileInputStream(args[0]);
        byte[] encKey = new byte[keyfis.available()];
        keyfis.read(encKey);

        keyfis.close();
Now the byte array encKey contains the encoded public key bytes.

You can use a KeyFactory class in order to instantiate a DSA public key from its encoding. The KeyFactory class provides conversions between opaque keys (of type Key) and key specifications, which are transparent representations of the underlying key material. With an opaque key you can obtain the algorithm name, format name, and encoded key bytes, but not the key material, which, for example, may consist of the key itself and the algorithm parameters used to calculate the key. (Note that PublicKey, because it extends Key, is itself a Key.)

So, first you need a key specification. You can obtain one via the following, assuming that the key was encoded according to the X.509 standard, which is the case, for example, if the key was generated with the built-in DSA key-pair generator supplied by the SUN provider:

        X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(encKey);

Now you need a KeyFactory object to do the conversion. That object must be one that works with DSA keys.

        KeyFactory keyFactory = KeyFactory.getInstance("DSA", "SUN");

Finally, you can use the KeyFactory object to generate a PublicKey from the key specification.

        PublicKey pubKey = keyFactory.generatePublic(pubKeySpec);
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Prepare Initial Program Structure
Next page: Input the Signature Bytes


Input the Signature Bytes (The Java™ Tutorials > Security Features in Java SE > Generating and Verifying Signatures)

Trail: Security Features in Java SE
Lesson: Generating and Verifying Signatures
Section: Verifying a Digital Signature
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Home Page > Security Features in Java SE > Generating and Verifying Signatures
« Previous • Trail • Next »
Input the Signature Bytes
Next, input the signature bytes from the file specified as the second command line argument.
        FileInputStream sigfis = new FileInputStream(args[1]);
        byte[] sigToVerify = new byte[sigfis.available()];
        sigfis.read(sigToVerify);
        sigfis.close();
Now the byte array sigToVerify contains the signature bytes.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Input and Convert the Encoded Public Key Bytes
Next page: Verify the Signature


Verify the Signature (The Java™ Tutorials > Security Features in Java SE > Generating and Verifying Signatures)

Trail: Security Features in Java SE
Lesson: Generating and Verifying Signatures
Section: Verifying a Digital Signature
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Home Page > Security Features in Java SE > Generating and Verifying Signatures
« Previous • Trail • Next »
Verify the Signature

You've added code to the VerSig program to

  • Input the encoded key bytes and converted them to a PublicKey named pubKey

  • Input the signature bytes into a byte array named sigToVerify
You can now proceed to do the verification.

Initialize the Signature Object for Verification

As with signature generation, a signature is verified by using an instance of the Signature class. You need to create a Signature object that uses the same signature algorithm as was used to generate the signature. The algorithm used by the GenSig program was the SHA1withDSA algorithm from the SUN provider.

Signature sig = Signature.getInstance("SHA1withDSA", "SUN");
Next, you need to initialize the Signature object. The initialization method for verification requires the public key.
sig.initVerify(pubKey);

Supply the Signature Object With the Data to be Verified

You now need to supply the Signature object with the data for which a signature was generated. This data is in the file whose name was specified as the third command line argument. As you did when signing, read in the data one buffer at a time, and supply it to the Signature object by calling the update method.
FileInputStream datafis = new FileInputStream(args[2]);
BufferedInputStream bufin = new BufferedInputStream(datafis);

byte[] buffer = new byte[1024];
int len;
while (bufin.available() != 0) {
    len = bufin.read(buffer);
    sig.update(buffer, 0, len);
};

bufin.close();

Verify the Signature

Once you have supplied all of the data to the Signature object, you can verify the digital signature of that data and report the result. Recall that the alleged signature was read into a byte array called sigToVerify.

boolean verifies = sig.verify(sigToVerify);

System.out.println("signature verifies: " + verifies);

The verifies value will be true if the alleged signature (sigToVerify) is the actual signature of the specified data file generated by the private key corresponding to the public key pubKey.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Input the Signature Bytes
Next page: Compile and Run the Program


Compile and Run the Program (The Java™ Tutorials > Security Features in Java SE > Generating and Verifying Signatures)

Trail: Security Features in Java SE
Lesson: Generating and Verifying Signatures
Section: Verifying a Digital Signature
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Home Page > Security Features in Java SE > Generating and Verifying Signatures
« Previous • Trail • Next »
Compile and Run the Program

Here is the complete source code for the VerSig.java program, with some comments added.

Compile and run the program. Remember, you need to specify three arguments on the command line:

  • The name of the file containing the encoded public key bytes

  • The name of the file containing the signature bytes

  • The name of the data file (the one for which the signature was generated)
Since you will be testing the output of the GenSig program, the file names you should use are
  • suepk

  • sig

  • data

Here's a sample run; the bold indicates what you type.

%java VerSig suepk sig data
signature verifies: true
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Verify the Signature
Next page: Weaknesses and Alternatives


Weaknesses and Alternatives (The Java™ Tutorials > Security Features in Java SE > Generating and Verifying Signatures)

Trail: Security Features in Java SE
Lesson: Generating and Verifying Signatures
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Home Page > Security Features in Java SE > Generating and Verifying Signatures
« Previous • Trail • Next »
Weaknesses and Alternatives
The GenSig and VerSig programs in this lesson illustrate the use of the JDK Security API to generate a digital signature for data and to verify that a signature is authentic. However, the actual scenario depicted by those programs, in which a sender uses the JDK Security API to generate a new public/private key pair, the sender stores the encoded public key bytes in a file, and the receiver reads in the key bytes, is not necessarily realistic, and has a potential major flaw.

In many cases the keys do not need to be generated; they already exist, either as encoded keys in files or as entries in a keystore.

The potential major flaw is that nothing guarantees the authenticity of the public key the receiver receives, and the VerSig program correctly verifies the authenticity of a signature only if the public key it is supplied is itself authentic!

Working with Encoded Key Bytes

Sometimes encoded key bytes already exist in files for the key pair to be used for signing and verification. If that's the case the GenSig program can import the encoded private key bytes and convert them to a PrivateKey needed for signing, via the following, assuming that the name of the file containing the private key bytes is in the privkeyfile String and that the bytes represent a DSA key that has been encoded by using the PKCS #8 standard.
    FileInputStream keyfis = new FileInputStream(privkeyfile);
    byte[] encKey = new byte[keyfis.available()];
    keyfis.read(encKey);
    keyfis.close();

    PKCS8EncodedKeySpec privKeySpec = new PKCS8EncodedKeySpec(encKey);

    KeyFactory keyFactory = KeyFactory.getInstance("DSA");
    PrivateKey privKey = keyFactory.generatePrivate(privKeySpec);
GenSig no longer needs to save the public key bytes in a file, as they're already in one.

In this case the sender sends the receiver

  • the already existing file containing the encoded public key bytes (unless the receiver already has this) and

  • the data file and the signature file exported by GenSig.

The VerSig program remains unchanged, as it already expects encoded public key bytes in a file.

But what about the potential problem of a malicious user intercepting the files and replacing them all in such a way that their switch cannot be detected? In some cases this is not an issue, because people have already exchanged public keys face to face or via a trusted third party that does the face-to-face exchange. After that, multiple subsequent file and signature exchanges may be done remotely (that is, between two people in different locations), and the public keys may be used to verify their authenticity. If a malicious user tries to change the data or signature, this is detected by VerSig.

If a face-to-face key exchange is not possible, you can try other methods of increasing the likelihood of proper receipt. For example, you could send your public key via the most secure method possible prior to subsequent exchanges of data and signature files, perhaps using less secure mediums.

In general, sending the data and the signature separately from your public key greatly reduces the likelihood of an attack. Unless all three files are changed, and in a certain manner discussed in the next paragraph, VerSig will detect any tampering.

If all three files (data document, public key, and signature) were intercepted by a malicious user, that person could replace the document with something else, sign it with a private key, and forward on to you the replaced document, the new signature, and the public key corresponding to the private key used to generate the new signature. Then VerSig would report a successful verification, and you'd think that the document came from the original sender. Thus you should take steps to ensure that at least the public key is received intact (VerSig detects any tampering of the other files), or you can use certificates to facilitate authentication of the public key, as described in the next section.

Working with Certificates

It is more common in cryptography to exchange certificates containing public keys rather than the keys themselves.

One benefit is that a certificate is signed by one entity (the issuer) to verify that the enclosed public key is the actual public key of another entity (the subject or owner). Typically a trusted third-party certification authority (CA) verifies the identity of the subject and then vouches for its being the owner of the public key by signing the certificate.

Another benefit of using certificates is that you can check to ensure the validity of a certificate you received by verifying its digital signature, using its issuer's (signer's) public key, which itself may be stored in a certificate whose signature can be verified by using the public key of that certificate issuer; that public key itself may be stored in a certificate, and so on, until you reach a public key that you already trust.

If you cannot establish a trust chain (perhaps because the required issuer certificates are not available to you), the certificate fingerprint(s) can be calculated. Each fingerprint is a relatively short number that uniquely and reliably identifies the certificate. (Technically it's a hash value of the certificate information, using a message digest, also known as a one-way hash function.) You can call up the certificate owner and compare the fingerprints of the certificate you received with the ones sent. If they're the same, the certificates are the same.

It would be more secure for GenSig to create a certificate containing the public key and for VerSig to then import the certificate and extract the public key. However, the JDK has no public certificate APIs that would allow you to create a certificate from a public key, so the GenSig program cannot create a certificate from the public key it generated. (There are public APIs for extracting a public key from a certificate, though.)

If you want, you can use the various security tools, not APIs, to sign your important document(s) and work with certificates from a keystore, as was done in the Exchanging Files lesson.

Alternatively you can use the API to modify your programs to work with an already existing private key and corresponding public key (in a certificate) from your keystore. To start, modify the GenSig program to extract a private key from a keystore rather than generate new keys. First, let's assume the following.

  • The keystore name is in the String ksName

  • The keystore type is "JKS", the proprietary type created by Sun Microsystems

  • The keystore password is in the char array spass

  • The alias to the keystore entry containing the private key, and the public key certificate is in the String alias

  • The private key password is in the char array kpass
Then you can extract the private key from the keystore via the following.
    KeyStore ks = KeyStore.getInstance("JKS");
    FileInputStream ksfis = new FileInputStream(ksName);
    BufferedInputStream ksbufin = new BufferedInputStream(ksfis);

    ks.load(ksbufin, spass);
    PrivateKey priv = (PrivateKey) ks.getKey(alias, kpass);
You can extract the public key certificate from the keystore and save its encoded bytes to a file named suecert, via the following.
    java.security.cert.Certificate cert = ks.getCertificate(alias);
    byte[] encodedCert = cert.getEncoded();

    /* save the certificate in a file named "suecert" */
    FileOutputStream certfos = new FileOutputStream("suecert");
    certfos.write(encodedCert);
    certfos.close();
Then you send the data file, the signature, and the certificate to the receiver. The receiver verifes the authenticity of the certificate by first getting the certificate's fingerprints, via the keytool -printcert command.
keytool -printcert -file suecert
  Owner: CN=Susan Jones, OU=Purchasing, O=ABC, L=Cupertino, ST=CA, C=US
  Issuer: CN=Susan Jones, OU=Purchasing, O=ABC, L=Cupertino, ST=CA, C=US
  Serial number: 35aaed17
  Valid from: Mon Jul 13 22:31:03 PDT 1998 until:
  Sun Oct 11 22:31:03 PDT 1998
  Certificate fingerprints:
       MD5:  1E:B8:04:59:86:7A:78:6B:40:AC:64:89:2C:0F:DD:13
       SHA1: 1C:79:BD:26:A1:34:C0:0A:30:63:11:6A:F2:B9:67:DF:E5:8D:7B:5E
Then the receiver verifies the fingerprints, perhaps by calling the sender up and comparing them with those of the sender's certificate or by looking them up in a public repository.

The receiver's verification program (a modified VerSig) can then import the certificate and extract the public key from it via the following, assuming that the certificate file name (for example, suecert) is in the String certName.

FileInputStream certfis = new FileInputStream(certName);
java.security.cert.CertificateFactory cf =
    java.security.cert.CertificateFactory.getInstance("X.509");
java.security.cert.Certificate cert = cf.generateCertificate(certfis);
PublicKey pub = cert.getPublicKey();

Ensuring Data Confidentiality

Suppose that you want to keep the contents of the data confidential so people accidentally or maliciously trying to view it in transit (or on your own machine or disk) cannot do so. To keep the data confidential, you should encrypt it and store and send only the encryption result (referred to as ciphertext). The receiver can decrypt the ciphertext to obtain a copy of the original data.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Compile and Run the Program
Next page: Implementing Your Own Permission


Lesson: Implementing Your Own Permission (The Java™ Tutorials > Security Features in Java SE)

Implementing Your Own Permission
TerrysGame
The HighScore Class
The HighScorePermission Class
A Sample Policy File
Putting It All Together
Steps for the HighScore Developer (Chris)
Steps for the TerrysGame Developer (Terry)
Steps for a User Running TerrysGame (Kim)
Trail: Security Features in Java SE
Home Page > Security Features in Java SE
« Previous • Trail • Next »
Lesson: Implementing Your Own Permission
This lesson demonstrates how to write a class that defines its own special permission. The basic components in this lesson include:
  1. A sample game called TerrysGame.

  2. A class called HighScore, which is used by TerrysGame to store a user's latest high score.

  3. A class called HighScorePermission, which is used to protect access to the user's stored high score value.

  4. A user's security policy file, which grants permission to TerrysGame to update his/her high score.
The basic scenario is as follows:
  1. A user plays TerrysGame.

  2. If the user reaches a new high score, TerrysGame uses the HighScore class to save this new value.

  3. The HighScore class looks into the user's security policy to check if TerrysGame has permission to update the user's high score value.

  4. If TerrysGame has permission to update the high score, then the HighScore class updates that value.

We describe the key points of each of the basic components and then show a sample run:

  • TerrysGame

  • The HighScore Class

  • The HighScorePermission Class

  • A Sample Policy File

  • Putting It All Together

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: TerrysGame


TerrysGame (The Java™ Tutorials > Security Features in Java SE > Implementing Your Own Permission)

Trail: Security Features in Java SE
Lesson: Implementing Your Own Permission
Implementing Your Own Permission
TerrysGame
The HighScore Class
The HighScorePermission Class
A Sample Policy File
Putting It All Together
Steps for the HighScore Developer (Chris)
Steps for the TerrysGame Developer (Terry)
Steps for a User Running TerrysGame (Kim)
Home Page > Security Features in Java SE > Implementing Your Own Permission
« Previous • Trail • Next »
TerrysGame

Below is the source code for TerrysGame. For simplicity, TerrysGame does not actually contain code to play a game. It simply retrieves or updates a user's high score.

To see what the user's current high score value is, you could run:

java TerrysGame get
To set a new high score value for the user, you could run:
java TerrysGame set score
To retrieve the user's current high score, TerrysGame simply instantiates a HighScore object and makes a call to its getHighScore method. To set a new high score for the user, TerrysGame instantiates a HighScore object and calls setHighScore, passing it the user's new high score.

Here is the source code for TerrysGame, TerrysGame.java:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.gamedev.games;

import java.io.*;
import java.security.*;
import java.util.Hashtable;
import com.scoredev.scores.*;

public class TerrysGame
{
    public static void main(String args[])
    throws Exception
    {
    HighScore hs = new HighScore("TerrysGame");

    if (args.length == 0)
        usage();

    if (args[0].equals("set")) {
        hs.setHighScore(Integer.parseInt(args[1]));
    } else if (args[0].equals("get")) {
        System.out.println("score = "+ hs.getHighScore());
    } else {
        usage();
    }
    }

    public static void usage()
    {
    System.out.println("TerrysGame get");
    System.out.println("TerrysGame set <score>");
    System.exit(1);
    }
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Implementing Your Own Permission
Next page: The HighScore Class


The HighScore Class (The Java™ Tutorials > Security Features in Java SE > Implementing Your Own Permission)

Trail: Security Features in Java SE
Lesson: Implementing Your Own Permission
Implementing Your Own Permission
TerrysGame
The HighScore Class
The HighScorePermission Class
A Sample Policy File
Putting It All Together
Steps for the HighScore Developer (Chris)
Steps for the TerrysGame Developer (Terry)
Steps for a User Running TerrysGame (Kim)
Home Page > Security Features in Java SE > Implementing Your Own Permission
« Previous • Trail • Next »
The HighScore Class
The HighScore class stores and protects access to the user's high score for TerrysGame (and any other games that call it). For simplicity, this class saves the high score value into a file, called .highscore, in the user's home directory. However, before allowing TerrysGame to retrieve or update the user's high score value, this class checks to make sure that the user has granted TerrysGame permission to access the high score in his/her security policy file.

Checking that TerrysGame has the HighScorePermission

To check whether or not TerrysGame has permission to access the user's high score, the HighScore class must:
  1. Call System.getSecurityManager() to get the currently installed security manager.

  2. If the result is not null (i.e., there is a security manager, as opposed to the caller being an application that is unrestricted), then

    1. Construct a HighScorePermission object, and

    2. Call the security manager's checkPermission method, and pass it the newly constructed HighScorePermission object.
Here is the code:
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
    sm.checkPermission(new HighScorePermission(gameName));
}
The checkPermission method essentially asks the security manager if TerrysGame has the specified HighScorePermission. In other words, it asks the security manager if TerrysGame has permission to update the user's high score value for the specified game (TerrysGame). The underlying security framework will consult the user's security policy to see if TerrysGame indeed has this permission.

The HighScore Code

Here is the complete source code for the HighScore class.

Note: The doPrivileged method calls are used to enable HighScore to temporarily access resources that are available to it but that are not available to the code that calls it (TerrysGame). For example, it is expected that the policy file will grant HighScore permission to access the .highscore file in the user's home directory, but it will not grant this permission to games, such as TerrysGame.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: TerrysGame
Next page: The HighScorePermission Class


The HighScorePermission Class (The Java™ Tutorials > Security Features in Java SE > Implementing Your Own Permission)

Trail: Security Features in Java SE
Lesson: Implementing Your Own Permission
Implementing Your Own Permission
TerrysGame
The HighScore Class
The HighScorePermission Class
A Sample Policy File
Putting It All Together
Steps for the HighScore Developer (Chris)
Steps for the TerrysGame Developer (Terry)
Steps for a User Running TerrysGame (Kim)
Home Page > Security Features in Java SE > Implementing Your Own Permission
« Previous • Trail • Next »
The HighScorePermission Class
The HighScorePermission class defines the permission that TerrysGame needs to update the user's high score.

All permission classes should subclass from either java.security.Permission or java.security.BasicPermission. The basic difference between the two is that java.security.Permission defines more complex permissions that require names and actions. For example, a java.io.FilePermission extends from java.security.Permission, and requires a name (a filename), and actions allowed for that file (read/write/delete).

In contrast, java.security.BasicPermission defines simpler permissions that only require a name. For example, java.lang.RuntimePermission extends from java.security.BasicPermission and simply needs a name (like "exitVM"), which allows programs to exit the Java Virtual Machine.

Our HighScorePermission is a simple permission, and hence can be extended from java.security.BasicPermission.

Often, the method implementations in the BasicPermission class itself do not need to be overridden by its subclasses. That is the case with our HighScorePermission, so all we need to implement are the constructors, which just invoke the superclass constructors, as shown in the following:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package com.scoredev.scores;

import java.security.*;

public final class HighScorePermission extends BasicPermission {

    public HighScorePermission(String name)
    {
    super(name);
    }

    // note that actions is ignored and not used,
    // but this constructor is still needed
    public HighScorePermission(String name, String actions)
    {
    super(name, actions);
    }
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The HighScore Class
Next page: A Sample Policy File


A Sample Policy File (The Java™ Tutorials > Security Features in Java SE > Implementing Your Own Permission)

Trail: Security Features in Java SE
Lesson: Implementing Your Own Permission
Implementing Your Own Permission
TerrysGame
The HighScore Class
The HighScorePermission Class
A Sample Policy File
Putting It All Together
Steps for the HighScore Developer (Chris)
Steps for the TerrysGame Developer (Terry)
Steps for a User Running TerrysGame (Kim)
Home Page > Security Features in Java SE > Implementing Your Own Permission
« Previous • Trail • Next »
A Sample Policy File
Below is a complete policy file for a user wanting to run TerrysGame.

The policy file syntax is not described here; if you're interested, see Default Policy Implementation and Policy File Syntax on the public java.sun.com web site.

You don't need to know the syntax; you can always use the Policy Tool to create policy files, as shown in Quick Tour of Controlling Applets , Quick Tour of Controlling Applications , and Signing Code and Granting It Permissions lessons.

Below is the sample policy file, followed by a description of the individual entries. Assume that

  • The policy file is on Kim's computer, and Kim's keystore is named kim.keystore.

  • TerrysGame has been signed by the game creator Terry's private key, and the corresponding public key is in the keystore entry aliased by "terry".

  • The HighScore and HighScorePermissions classes were signed by the private key of the person who implemented them (Chris), and the corresponding public key is in the keystore entry aliased by "chris".
Here's the policy file:
keystore "kim.keystore";

// Here is the permission TerrysGame needs.
// It grants code signed by "terry" the HighScorePermission, if the
// HighScorePermission was signed by "chris"
grant SignedBy "terry" {
  permission com.scoredev.scores.HighScorePermission
      "TerrysGame", signedBy "chris";
};

// Here is the set of permissions the HighScore class needs:
grant SignedBy "chris" {
  // The HighScore class needs permission to read "user.home" to find
  // the location of the highscore file

  permission java.util.PropertyPermission "user.home", "read";

  // It needs permission to read and write the high score file itself

  permission java.io.FilePermission
      "${user.home}${/}.highscore", "read,write";

  // It needs to get granted its own permission,
  // so it can call checkPermission
  // to see if its caller has permission.
  // Only grant it the permission
  // if the permission itself was signed by "chris"

  permission com.scoredev.scores.HighScorePermission
      "*", signedBy "chris";
};

The Keystore Entry

A keystore is a repository of keys and certificates, and is used to look up the public keys of the signers specified in the policy file ("terry" and "chris" in this example).

The keytool utility is used to create and administer keystores.

For this lesson, assume Kim would like to play TerrysGame. If Kim's keystore is named kim.keystore, then Kim's policy file needs the following line at the very beginning:

keystore "kim.keystore";

The TerrysGame Entry

A policy file entry specifies one or more permissions for code from a particular code source - either code from a particular location (URL), or code signed by a particular entity, or both.

Our policy file needs an entry for each game, granting code signed by a key from that game's creator a HighScorePermission whose name is the game name. That permission allows the game to call the HighScore methods to get or update the user's high score value for that particular game.

The entry required for TerrysGame is:

grant SignedBy "terry" {
  permission com.scoredev.scores.HighScorePermission
      "TerrysGame", signedBy "chris";
};

Requiring that TerrysGame be signed by "terry" enables Kim to know that the game is the actual game that Terry developed. For this to work, Kim must have already stored Terry's public key certificate into kim.keystore using the alias "terry".

Notice that the HighScorePermission needs to be signed by "chris", the person who actually implemented that permission. This ensures that TerrysGame is granted the actual permission implemented by "chris", and not someone else. As before, for this to work Kim must have already stored Chris's public key certificate into kim.keystore using the alias "chris".

The HighScore Entry

The final entry in the policy file grants permissions to the HighScore class. More specifically, it grants permissions to code signed by "chris", who created and signed the class. Requiring the class to be signed by "chris" ensures that when TerrysGame calls upon this class to update the user's high score, TerrysGame knows for sure that it is using the original class implemented by "chris".

To update the user's high score value for any games that call upon it do so, the HighScore class requires three permissions:

1. Permission to read the "user.home" property value.

The HighScore class stores the user's high score values in a .highscore file in the user's home directory. Therefore this class needs a java.util.PropertyPermission that allows it to read the "user.home" property value to find out exactly where the user's home directory resides:

permission java.util.PropertyPermission
    "user.home", "read";

2. Permission to read and write to the high score file itself.

This permission is needed so the HighScore getHighScore and setHighScore methods can access the user's .highscore file to get or set, respectively, the current high score for the current game.

Here's the required permission:

permission java.io.FilePermission
    "${user.home}${/}.highscore", "read,write";
Note: The notation ${propName} specifies the value of a property. Thus, ${user.home} will be replaced by the value of the "user.home" property. The notation ${/} is a platform-independent way of specifying a file separator.

3. All HighScorePermissions (i.e, HighScorePermissions of any name).

This permission is needed so that the HighScore checks to ensure the calling game has been granted a HighScorePermission whose name is the game name will work. That is, the HighScore class must also be granted the permission, since a permission check requires that all code currently on the stack have the specified permission.

Here's the required permission:

permission com.scoredev.scores.HighScorePermission
    "*", signedBy "chris";
As before, the HighScorePermission itself needs to be signed by "chris", the person who actually implemented the permission.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The HighScorePermission Class
Next page: Putting It All Together


Putting It All Together (The Java™ Tutorials > Security Features in Java SE > Implementing Your Own Permission)

Trail: Security Features in Java SE
Lesson: Implementing Your Own Permission
Implementing Your Own Permission
TerrysGame
The HighScore Class
The HighScorePermission Class
A Sample Policy File
Putting It All Together
Steps for the HighScore Developer (Chris)
Steps for the TerrysGame Developer (Terry)
Steps for a User Running TerrysGame (Kim)
Home Page > Security Features in Java SE > Implementing Your Own Permission
« Previous • Trail • Next »
Putting It All Together

Here, we simulate being, in turn, the HighScore developer (Chris), the TerrysGame developer (Terry), and a user (Kim) running the game.

You can execute all the specified steps, and then (as Kim's last step) run TerrysGame.

The steps are presented without explanation. For further information about the steps that need to be taken by both code signers (such as Chris and Terry) and receivers of such code (such as Kim), see the Signing Code and Granting It Permissions lesson.

Here are the steps:

  • Steps for the HighScore Developer (Chris)

  • Steps for the TerrysGame Developer (Terry)

  • Steps for a User Running TerrysGame (Kim)

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: A Sample Policy File
Next page: Steps for the HighScore Developer (Chris)


Steps for the HighScore Developer (Chris) (The Java™ Tutorials > Security Features in Java SE > Implementing Your Own Permission)

Trail: Security Features in Java SE
Lesson: Implementing Your Own Permission
Section: Putting It All Together
Implementing Your Own Permission
TerrysGame
The HighScore Class
The HighScorePermission Class
A Sample Policy File
Putting It All Together
Steps for the HighScore Developer (Chris)
Steps for the TerrysGame Developer (Terry)
Steps for a User Running TerrysGame (Kim)
Home Page > Security Features in Java SE > Implementing Your Own Permission
« Previous • Trail • Next »
Steps for the HighScore Developer (Chris)

The steps Chris would take, after creating the HighScore and HighScorePermission classes, are:

Compile the Classes

javac HighScore*.java -d .

Place the class files in a JAR File

jar cvf hs.jar com/scoredev/scores/HighScore*.class

Create a Keystore and Keys for Signing

keytool -genkey -keystore chris.keystore -alias signJars
Specify whatever you want for the passwords and distinguished name information.

Sign the JAR File

jarsigner -keystore chris.keystore hs.jar signJars

Export the Public Key Certificate

keytool -export -keystore chris.keystore
    -alias signJars -file Chris.cer

Supply Files and Information Needed by Game Developers and Users

That is, supply them
  • the signed JAR File hs.jar,

  • the public key certificate file Chris.cer, and

  • information as to the permissions the HighScore and HighScorePermission classes must be granted in a policy file in order to work. For this, Chris could supply the exact grant entry needed.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Putting It All Together
Next page: Steps for the TerrysGame Developer (Terry)


Steps for the TerrysGame Developer (Terry) (The Java™ Tutorials > Security Features in Java SE > Implementing Your Own Permission)

Trail: Security Features in Java SE
Lesson: Implementing Your Own Permission
Section: Putting It All Together
Implementing Your Own Permission
TerrysGame
The HighScore Class
The HighScorePermission Class
A Sample Policy File
Putting It All Together
Steps for the HighScore Developer (Chris)
Steps for the TerrysGame Developer (Terry)
Steps for a User Running TerrysGame (Kim)
Home Page > Security Features in Java SE > Implementing Your Own Permission
« Previous • Trail • Next »
Steps for the TerrysGame Developer (Terry)

The steps Terry would take, after creating a game (TerrysGame ) that calls the HighScore getHighScore and setHighScore methods to get and set, respectively, the user's high scores, are:

Compile the Game Class

javac TerrysGame.java -classpath hs.jar -d .

Place its class file in a JAR File

jar cvf terry.jar com/gamedev/games/TerrysGame.class

Create a Keystore and Keys for Signing

keytool -genkey -keystore terry.keystore -alias signTJars
Specify whatever you want for the passwords and distinguished name information.

Sign the JAR File

jarsigner -keystore terry.keystore terry.jar signTJars

Export the Public Key Certificate

keytool -export -keystore terry.keystore
    -alias signTJars -file Terry.cer

Supply Files and Information Needed by Users

That is, supply them
  • the signed JAR File terry.jar,

  • the public key certificate file Terry.cer, and

  • information as to the permissions the TerrysGame class needs. For this, Terry could supply the exact grant entry needed.
Game users also need files and information from Chris. For their convenience, Terry may forward this information to them:
  • the signed JAR File hs.jar,

  • the public key certificate file Chris.cer, and

  • information as to the permissions the HighScore and HighScorePermission classes must be granted in a policy file in order to work. This could be the exact grant entry needed.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Steps for the HighScore Developer (Chris)
Next page: Steps for a User Running TerrysGame (Kim)


Steps for a User Running TerrysGame (Kim) (The Java™ Tutorials > Security Features in Java SE > Implementing Your Own Permission)

Trail: Security Features in Java SE
Lesson: Implementing Your Own Permission
Section: Putting It All Together
Implementing Your Own Permission
TerrysGame
The HighScore Class
The HighScorePermission Class
A Sample Policy File
Putting It All Together
Steps for the HighScore Developer (Chris)
Steps for the TerrysGame Developer (Terry)
Steps for a User Running TerrysGame (Kim)
Home Page > Security Features in Java SE > Implementing Your Own Permission
« Previous • Trail • Next »
Steps for a User Running TerrysGame (Kim)

The steps a user, such as Kim, would take, are:

Import the Certificates as Trusted Certificates

keytool -import -alias chris -file Chris.cer -keystore kim.keystore
keytool -import -alias terry -file Terry.cer -keystore kim.keystore

Set Up a Policy File With the Required Permissions

Here's the complete kim.policy policy file, as described in A Sample Policy File.

Run TerrysGame

To set the high score:
java -Djava.security.manager -Djava.security.policy=kim.policy
 -classpath hs.jar;terry.jar com.gamedev.games.TerrysGame set 456
To get the high score:
java -Djava.security.manager -Djava.security.policy=kim.policy
 -classpath hs.jar;terry.jar com.gamedev.games.TerrysGame get
Notes:
  • If you don't specify -Djava.security.manager, the application will run unrestricted (policy files and permissions won't be checked).

  • The -Djava.security.policy=kim.policy tells where the policy file is. Note: There are other ways of specifying the policy file. For example, you can add an entry in the security properties file that specifies the inclusion of kim.policy, as discussed at the end of the See the Policy File Effects lesson.

  • -classpath hs.jar;terry.jar specifies the JAR files that contain the class files needed. For Windows, use a semicolon (";") to separate JAR files; for Unix, use a colon (":").

  • The policy file kim.policy specifies the keystore kim.keystore. Since it does not provide an absolute URL location for the keystore, the keystore is assumed to be in the same directory as the policy file.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Steps for the TerrysGame Developer (Terry)
Next page: End of Trail


Trail: The Extension Mechanism (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: The Extension Mechanism
The extension mechanism was introduced as a new feature in the JavaTM 1.2 platform. The extension mechanism provides a standard, scalable way to make custom APIs available to all applications running on the Java platform. As of the Java 1.3 platform release, Java extensions are also referred to as optional packages. This trail may use both terms interchangeably.

Extensions are groups of packages and classes that augment the Java platform through the extension mechanism. The extension mechanism enables the runtime environment to find and load extension classes without the extension classes having to be named on the class path. In that respect, extension classes are similar to the Java platform's core classes. That's also where extensions get their name -- they, in effect, extend the platform's core API.

Since this mechanism extends the platform's core API, its use should be judiciously applied. Most commonly it is used for well standarized interfaces such as those defined by the Java Community ProcessSM, although it may also be appropriate for site wide interfaces.

This figure shows the relationships between Application, Java Platform, and Extensions.

As the diagram indicates, extensions act as "add-on" modules to the Java platform. Their classes and public APIs are automatically available to any applications running on the platform.

The extension mechanism also provides a means for extension classes to be downloaded from remote locations for use by applets.

Extensions are bundled as Java Archive (JAR) files, and this trail assumes that you are familiar with the JAR file format. If you're not up to speed on JAR files, you might want to review some JAR-file documentation before proceeding with the lessons in this trail:

  • The Packaging Programs in JAR Files lesson in this tutorial.
  • The JAR Guide in the JDKTM documentation.

This trail has two lessons:

Creating and Using Extensions

This section shows you what you need to do to add an extension to your Java platform and how applets can benefit from the extension mechanism by downloading remote extension classes.

Making Extensions Secure

This section describes security privileges and permissions that are granted to extensions on your platform. You'll see how to use the Java platform's security architecture if you're writing extensions classes of your own.

Additional Documentation

You can find further information about extensions in the The Java Extensions Mechanism section of the JDK documentation.
« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Creating and Using Extensions


Lesson: Creating and Using Extensions (The Java™ Tutorials > The Extension Mechanism)

Creating and Using Extensions
Installed Extensions
Download Extensions
Understanding Extension Class Loading
Trail: The Extension Mechanism
Home Page > The Extension Mechanism
« Previous • Trail • Next »
Lesson: Creating and Using Extensions
Any set of packages or classes can easily be made to play the role of an extension. The first step in turning a set of classes into an extension is to bundle them in a JAR file. Once that's done, you can turn the software into an extension in two ways:
  • by placing the JAR file in a special location in the directory structure of the Java Runtime Environment, in which case it's called an installed extension.
  • by referencing the JAR file in a specified way from the manifest of the another JAR file, in which case it's called a download extension.

This lesson shows you how the extension mechanism works by using a simple "toy" extension as an example.

Installed Extensions

In this section, you'll create a simple installed extension and see how extension software is treated as part of the platform by the runtime environment.

Download Extensions

This section will show you how modify a JAR file's manifest so that the JAR-bundled software can make use of download extensions.

Understanding Extension Class Loading

This section is a short detour that summarizes the Java platform's delegation model for loading classes, and shows how it relates to loading classes in extensions.

The next lesson, Making Extensions Secure uses the same extension to show how the Java platform controls the security permissions that are granted to extensions.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: Installed Extensions


Installed Extensions (The Java™ Tutorials > The Extension Mechanism > Creating and Using Extensions)

Trail: The Extension Mechanism
Lesson: Creating and Using Extensions
Creating and Using Extensions
Installed Extensions
Download Extensions
Understanding Extension Class Loading
Home Page > The Extension Mechanism > Creating and Using Extensions
« Previous • Trail • Next »
Installed Extensions
Installed extensions are JAR files in the lib/ext directory of the Java Runtime Environment (JRETM) software. As its name implies, the JRE is the runtime portion of the Java Development Kit containing the platform's core API but without development tools such as compilers and debuggers. The JRE is available either by itself or as part of the Java Development Kit.

As of the Java 1.2 platform, the JRE is a strict subset of the JDKTM software. A subset of the JDK software directory tree looks like this:

The JRE consists of those directories within the highlighted box in the diagram. Whether your JRE is stand-alone or part of the JDK software, any JAR file in the lib/ext of the JRE directory is automatically treated by the runtime environment as an extension.

Since installed extensions extend the platform's core API, use them judiciously. They are rarely appropriate for interfaces used by a single, or small set of applications.

Furthermore, since the symbols defined by installed extensions will be visible in all Java processes, care should be taken to ensure that all visible symbols follow the appropriate "reverse domain name" and "class hierarchy" conventions. For example, com.mycompany.MyClass.

As of Java 6, extension JAR files may also be placed in a location that is independent of any particular JRE, so that extensions can be shared by all JREs that are installed on a system. Prior to Java 6, the value of java.ext.dirs referred to a single directory, but as of Java 6 it is a list of directories (like CLASSPATH) that specifies the locations in which extensions are searched for. The first element of the path is always the lib/ext directory of the JRE. The second element is a directory outside of the JRE. This other location allows extension JAR files to be installed once and used by several JREs installed on that system. The location varies depending on the operating system:

  • SolarisTM Operating System: /usr/jdk/packages/lib/ext
  • Linux: /usr/java/packages/lib/ext
  • Microsoft Windows: %SystemRoot%\Sun\Java\lib\ext

Note that an installed extension placed in one of the above directories extends the platform of each of the JREs (Java 6 or later) on that system.

A Simple Example

Let's create a simple installed extension. Our extension consists of one class, RectangleArea, that computes the areas of rectangles:
public final class RectangleArea {
    public static int area(java.awt.Rectangle r) {
        return r.width * r.height;
    }
}
This class has a single method, area, that takes an instance of java.awt.Rectangle and returns the rectangle's area.

Suppose that you want to test RectangleArea with an application called AreaApp:

import java.awt.*;

public class AreaApp {
    public static void main(String[] args) {
        int width = 10;
        int height = 5;

        Rectangle r = new Rectangle(width, height);
        System.out.println("The rectangle's area is "
                           + RectangleArea.area(r));
    }
}
This application instantiates a 10 x 5 rectangle, and then prints out the rectangle's area using the RectangleArea.area method.

Running AreaApp Without the Extension Mechanism

Let's first review how you would run the AreaApp application without using the extension mechanism. We'll assume that the RectangleArea class is bundled in a JAR file named area.jar.

The RectangleArea class is not part of the Java platform, of course, so you would need to place the area.jar file on the class path in order to run AreaApp without getting a runtime exception. If area.jar was in the directory /home/user, for example, you could use this command:

java -classpath .:/home/user/area.jar AreaApp
The class path specified in this command contains both the current directory, containing AreaApp.class, and the path to the JAR file containing the RectangleArea package. You would get the desired output by running this command:
The rectangle's area is 50

Running AreaApp by Using the Extension Mechanism

Now let's look at how you would run AreaApp by using the RectangleArea class as an extension.

To make the RectangleArea class into an extension, you place the file area.jar in the lib/ext directory of the JRE. Doing so automatically gives the RectangleArea the status of being an installed extension.

With area.jar installed as an extension, you can run AreaApp without needing to specify the class path:

java AreaApp

Because you're using area.jar as an installed extension, the runtime environment will be able to find and to load the RectangleArea class even though you haven't specified it on the class path. Similarly, any applet or application being run by any user on your system would be able to find and use the RectangleArea class.

If there are multiple JREs (Java 6 or later) installed on a system and want the RectangleArea class to be available as an extension to all of them, instead of installing it in the lib/ext directory of a particular JRE, install it in the system-wide location. For example, on system running Linux, install area.jar in the directory /usr/java/packages/lib/ext. Then AreaApp can run using different JREs that are installed on that system, for example if different browsers are configured to use different JREs.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating and Using Extensions
Next page: Download Extensions


Download Extensions (The Java™ Tutorials > The Extension Mechanism > Creating and Using Extensions)

Trail: The Extension Mechanism
Lesson: Creating and Using Extensions
Creating and Using Extensions
Installed Extensions
Download Extensions
Understanding Extension Class Loading
Home Page > The Extension Mechanism > Creating and Using Extensions
« Previous • Trail • Next »
Download Extensions
Download extensions are sets of classes (and related resources) in JAR files. A JAR file's manifest can contain headers that refer to one or more download extensions. The extensions can be referenced in one of two ways:
  • by a Class-Path header
  • by an Extension-List header
Note that at most one of each is allowed in a manifest. Download extensions indicated by a Class-Path header are downloaded only for the lifetime of the application that downloads them, such as a web browser. Their advantage is that nothing is installed on the client; their disadvantage is that they are downloaded each time they are needed. Download extensions that are downloaded by an Extension-List header are installed into the /lib/ext directory of the JRE that downloads them. Their advantage is that they are downloaded the first time they're needed; subsequently they can be used without downloading. But as shown later in this tutorial, they are more complex to deploy.

Since download extensions that use the Class-Path headers are simpler, lets consider them first. Assume for example that a.jar and b.jar are two JAR files in the same directory, and that the manifest of a.jar contains this header:

Class-Path: b.jar
Then the classes in b.jar serve as extension classes for purposes of the classes in a.jar. The classes in a.jar can invoke classes in b.jar without b.jar's classes having to be named on the class path. a.jar may or may not itself be an extension. If b.jar weren't in the same directory as a.jar, then the value of the Class-Path header should be set to the relative pathname of b.jar.

There's nothing special about the classes that are playing the role of a download extension. They are treated as extensions solely because they're referenced by the manifest of some other JAR file.

To get a better understanding of how download extensions work, let's create one and put it to use.

An Example

Suppose you want to create an applet that makes use of the RectangleArea class of the previous section:
public final class RectangleArea {
    public static int area(java.awt.Rectangle r) {
        return r.width * r.height;
    }
}
In the previous section, you made the RectangleArea class into an installed extension by placing the JAR file containing it into the lib/ext directory of the JRE. By making it an installed extension, you enabled any application to use the RectangleArea class as if it were part of the Java platform.

If you want to be able to use the RectangleArea class from an applet, the situation is a little different. Suppose, for example, that you have an applet, AreaApplet, that makes use of class RectangleArea:

import java.applet.Applet;
import java.awt.*;

public class AreaApplet extends Applet {
    Rectangle r;

    public void init() {
        int width = 10;
        int height = 5;

        r = new Rectangle(width, height);
    }

    public void paint(Graphics g) {
        g.drawString("The rectangle's area is "
                      + RectangleArea.area(r), 10, 10);
    }
}
This applet instantiates a 10 x 5 rectangle and then displays the rectangle's area by using the RectangleArea.area method.

However, you can't assume that everyone who downloads and uses your applet is going to have the RectangleArea class available on their system, as an installed extension or otherwise. One way around that problem is to make the RectangleArea class available from the server side, and you can do that by using it as a download extension.

To see how that's done, let's assume that you've bundled AreaApplet in a JAR file called AreaApplet.jar and that the class RectangleArea is bundled in RectangleArea.jar. In order for RectangleArea.jar to be treated as a download extension, RectangleArea.jar must be listed in the Class-Path header in AreaApplet.jar's manifest. AreaApplet.jar's manifest might look like this, for example:

Manifest-Version: 1.0
Class-Path: RectangleArea.jar
The value of the Class-Path header in this manifest is RectangleArea.jar with no path specified, indicating that RectangleArea.jar is located in the same directory as the applet's JAR file.

More about the Class-Path Header

If an applet or application uses more than one extension, you can list multiple URLs in a manifest. For example, the following is a valid header:
Class-Path: area.jar servlet.jar images/
In the Class-Path header any URLs listed that don't end with '/' are assumed to be JAR files. URLs ending in '/' indicate directories. In the preceding example, images/ might be a directory containing resources needed by the applet or the application.

Note that only one Class-Path header is allowed in a manifest file, and that each line in a manifest must be no more than 72 characters long. If you need to specify more class path entries than will fit on one line, you can extend them onto subsequent continuation lines. Begin each continuation line with two spaces. For example:

Class-Path: area.jar servlet.jar monitor.jar datasource.jar
  provider.jar gui.jar
A future release may remove the limitation of having only one instance of each header, and of limiting lines to only 72 characters.

Download extensions can be "daisy chained", meaning that the manifest of one download extension can have a Class-Path header that refers to a second extension, which can refer to a third extension, and so on.

Installing Download Extensions

In the above example, the extension downloaded by the applet is available only while the browser which loaded the applet is still running. However, applets can trigger installation of extensions, if additional information is included in the manifests of both the applet and the extension.

Since this mechanism extends the platform's core API, its use should be judiciously applied. It is rarely appropriate for interfaces used by a single, or small set of applications. All visible symbols should follow reverse domain name and class hierarchy conventions.

The basic requirements are that both the applet and the extensions it uses provide version information in their manifests, and that they be signed. The version information allows Java Plug-in to ensure that the extension code has the version expected by the applet. For example, the AreaApplet could specify an areatest extension in its manifest:

Manifest-Version: 1.0
Extension-List: areatest
areatest-Extension-Name: area
areatest-Specification-Version: 1.1
areatest-Implementation-Version: 1.1.2
areatest-Implementation-Vendor-Id: com.sun
areatest-Implementation-URL: http://www.sun.com/test/area.jar
(Please note that there is no area.jar file at the above URL; this is just an example!) The manifest in area.jar would provide corresponding information:
Manifest-Version: 1.0
Extension-Name: area
Specification-Vendor: Sun Microsystems, Inc
Specification-Version: 1.1
Implementation-Vendor-Id: com.sun
Implementation-Vendor: Sun Microsystems, Inc
Implementation-Version: 1.1.2
Both the applet and the extension must be signed, by the same signer. Signing the jar files will modify them in-place, providing more information in their manifest files. Signing helps ensure that only trusted code gets installed. A simple way to sign jar files is to first create a keystore, and then use that to hold certificates for the applet and extension. For example:
keytool -genkey -dname "cn=Fred" -alias test -keypass mykeypass -storepass mystorepass -validity 180
Then the jar files can be signed:
jarsigner -storepass mystorepass -keypass mykeypass AreaApplet.jar test
jarsigner -storepass mystorepass -keypass mykeypass area.jar test
More information on keytool, jarsigner, and other security tools is at the Summary of Tools for the Java 2 Platform Security.

Here is AreaDemo.html, which loads the applet and causes the extension code to be downloaded and installed:

<html>
<body>
  <applet code="AreaApplet.class" archive="AreaApplet.jar"/>
</body>
</html>
When the page is loaded for the first time, the user is told that the applet requires installation of the extension. A subsequent dialog informs the user about the signed applet. Accepting both installs the extension in the lib/ext folder of the JRE and runs the applet.

After restarting the web browser and load the same web page, only the dialog about the applet's signer is presented, because area.jar is already installed. This is also true if AreaDemo.html is opened in a different web browser (assuming both browsers use the same JRE).

For more information about installing download extensions, please see Deploying Java Extensions. A more detailed example is at Deploying Java Media Framework as Java Extension.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Installed Extensions
Next page: Understanding Extension Class Loading


Understanding Extension Class Loading (The Java™ Tutorials > The Extension Mechanism > Creating and Using Extensions)

Trail: The Extension Mechanism
Lesson: Creating and Using Extensions
Creating and Using Extensions
Installed Extensions
Download Extensions
Understanding Extension Class Loading
Home Page > The Extension Mechanism > Creating and Using Extensions
« Previous • Trail • Next »
Understanding Extension Class Loading
The extension framework makes use of the class-loading delegation mechanism. When the runtime environment needs to load a new class for an application, it looks for the class in the following locations, in order:
  1. Bootstrap classes: the runtime classes in rt.jar, internationalization classes in i18n.jar, and others.
  2. Installed extensions: classes in JAR files in the lib/ext directory of the JRE, and in the system-wide, platform-specific extension directory (such as /usr/jdk/packages/lib/ext on the SolarisTM Operating System, but note that use of this directory applies only to JavaTM 6 and later).
  3. The class path: classes, including classes in JAR files, on paths specified by the system property java.class.path. If a JAR file on the class path has a manifest with the Class-Path attribute, JAR files specified by the Class-Path attribute will be searched also. By default, the java.class.path property's value is ., the current directory. You can change the value by using the -classpath or -cp command-line options, or setting the CLASSPATH environment variable. The command-line options override the setting of the CLASSPATH environment variable.

The precedence list tells you, for example, that the class path is searched only if a class to be loaded hasn't been found among the classes in rt.jar, i18n.jar or the installed extensions.

Unless your software instantiates its own class loaders for special purposes, you don't really need to know much more than to keep this precedence list in mind. In particular, you should be aware of any class name conflicts that might be present. For example, if you list a class on the class path, you'll get unexpected results if the runtime environment instead loads another class of the same name that it found in an installed extension.

The Java Class Loading Mechanism

The Java platform uses a delegation model for loading classes. The basic idea is that every class loader has a "parent" class loader. When loading a class, a class loader first "delegates" the search for the class to its parent class loader before attempting to find the class itself.

Here are some highlights of the class-loading API:

  • Constructors in java.lang.ClassLoader and its subclasses allow you to specify a parent when you instantiate a new class loader. If you don't explicitly specify a parent, the virtual machine's system class loader will be assigned as the default parent.
  • The loadClass method in ClassLoader performs these tasks, in order, when called to load a class:
    1. If a class has already been loaded, it returns it.
    2. Otherwise, it delegates the search for the new class to the parent class loader.
    3. If the parent class loader does not find the class, loadClass calls the method findClass to find and load the class.
  • The findClass method of ClassLoader searches for the class in the current class loader if the class wasn't found by the parent class loader. You will probably want to override this method when you instantiate a class loader subclass in your application.
  • The class java.net.URLClassLoader serves as the basic class loader for extensions and other JAR files, overriding the findClass method of java.lang.ClassLoader to search one or more specified URLs for classes and resources.

To see a sample application that uses some of the API as it relates to JAR files, see the Using JAR-related APIs lesson in this tutorial.

Class Loading and the java Command

The Java platform's class-loading mechanism is reflected in the java command.
  • In the java tool, the -classpath option is a shorthand way to set the java.class.path property.
  • The -cp and -classpath options are equivalent.
  • The -jar option runs applications that are packaged in JAR files. For a description and examples of this option, see the Running JAR-Packaged Software lesson in this tutorial.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Download Extensions
Next page: Making Extensions Secure


Lesson: Making Extensions Secure (The Java™ Tutorials > The Extension Mechanism)

Making Extensions Secure
Setting Privileges for Extensions
Sealing Packages in Extensions
Trail: The Extension Mechanism
Home Page > The Extension Mechanism
« Previous • Trail • Next »
Lesson: Making Extensions Secure
Now that you've seen how to use extensions, you may be wondering what security privileges extensions have. If you're developing an extension that does file I/O, for example, you'll need to know how your extension is granted the appropriate permissions for reading and writing files. Conversely, if you're thinking about using an extension developed by someone else, you'll want to understand clearly what security privileges the extension has and how to change those privileges should you desire to do so.

This lesson shows you how the JavaTM platform's security architecture treats extensions. You'll see how to tell what privileges are granted to extension software, and you'll learn how to modify extension privileges by following some simple steps. In addition, you'll learn how to seal packages within your extensions to restrict access to specified parts of your code.

This lesson has two sections:

Setting Privileges for Extensions

This section contains some examples that show you what conditions must be met for extensions to be granted permissions to perform security-sensitive operations.

Sealing Packages in Extensions

You can optionally seal packages in extension JAR files as an additional security measure. If a package is sealed, it means that all classes defined in that package must originate from a single JAR file. This section shows you how to modify an extension's manifest to seal extension packages.

Additional Documentation

You'll find links and references to relevant security documentation at appropriate places throughout this lesson.

For complete information on security, you can refer to the following:

  • the Security Features in Java SE trail in this tutorial
  • the security section of the JDKTM documentation
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Setting Privileges for Extensions


Setting Privileges for Extensions (The Java™ Tutorials > The Extension Mechanism > Making Extensions Secure)

Trail: The Extension Mechanism
Lesson: Making Extensions Secure
Making Extensions Secure
Setting Privileges for Extensions
Sealing Packages in Extensions
Home Page > The Extension Mechanism > Making Extensions Secure
« Previous • Trail • Next »
Setting Privileges for Extensions
If a security manager is in force, the following conditions must be met to enable any software, including extension software, to perform security-sensitive operations:
  • The security-sensitive code in the extension must be wrapped in a PrivilegedAction object.
  • The security policy implemented by the security manager must grant the appropriate permission to the extension. By default, installed extensions are granted all security permissions as if they were part of the core platform API. The permissions granted by the security policy apply only to code wrapped in the PrivilegedAction instance.

Let's look at each of these conditions in a little more detail, with some examples.

Using the PrivilegedAction Class

Suppose that you want to modify the RectangleArea class in the extension example of the previous lesson to write rectangle areas to a file rather than to stdout. Writing to a file, however, is a security-sensitive operation, so if your software is going to be running under a security manager, you'll need to mark your code as being privileged. There are two steps you need to take to do so:
  1. You need to place code that performs security-sensitive operations within the run method of an object of type java.security.PrivilegedAction.
  2. You must use that PrivilegedAction object as the argument in a call to the doPrivileged method of java.security.AccessController.

If we apply those guidelines to the RectangleArea class, our class definition would look something like this:

import java.io.*;
import java.security.*;

public final class RectangleArea {
    public static void writeArea(final java.awt.Rectangle r) {
        AccessController.doPrivileged(new PrivilegedAction() {
        public Object run() {
            try {
            int area = r.width * r.height;
                    String userHome = System.getProperty("user.home");
            FileWriter fw = new FileWriter(
                        userHome + File.separator
                        + "test" + File.separator
                        + "area.txt");
            fw.write("The rectangle's area is " + area);
            fw.flush();
            fw.close();
            } catch(IOException ioe) {
            System.err.println(ioe);
            }
            return null;
        }
        });
    }
}

The single method in this class, writeArea, computes the area of a rectangle, and writes the area to a file called area.txt in the test directory under the user's home directory.

The security-sensitive statements dealing with the output file are placed within the run method of a new instance of PrivilegedAction. (Note that run requires that an Object instance be returned. The returned object can be null.) The new PrivilegedAction instance is then passed as an argument in a call to AccessController.doPrivileged.

For more information about using doPrivileged, see API for Privileged Blocks in the JDKTM documentation.

Wrapping security-sensitive code in a PrivilegedAction object in this manner is the first requirement for enabling an extension to perform security-sensitive operations. The second requirement is: getting the security manager to grant the privileged code the appropriate permissions.

Specifying Permissions with the Security Policy

The security policy in force at runtime is specified by a policy file. The default policy is set by the file lib/security/java.policy in the JRE software.

The policy file assigns security privileges to software by using grant entries. The policy file can contain any number of grant entries. The default policy file has this grant entry for installed extensions:

grant codeBase "file:${{java.ext.dirs}}/*" {
    permission java.security.AllPermission;
};
This entry specifies that files in the directories specified by file:${{java.ext.dirs}}/* are to be granted the permission called java.security.AllPermission. (Note that as of Java 6, java.ext.dirs refers to a classpath-like path of directories, each of which can hold installed extensions.) It's not too hard to guess that java.security.AllPermission grants installed extensions all the security privileges that it's possible to grant.

By default, then, installed extensions have no security restrictions. Extension software can perform security-sensitive operations as if there were no security manager installed, provided that security-sensitive code is contained in an instance of PrivilegedAction passed as an argument in a doPrivileged call.

To limit the privileges granted to extensions, you need to modify the policy file. To deny all privileges to all extensions, you could simply remove the above grant entry.

Not all permissions are as comprehensive as the java.security.AllPermission granted by default. After deleting the default grant entry, you can enter a new grant entry for particular permissions, including:

  • java.awt.AWTPermission
  • java.io.FilePermission
  • java.net.NetPermission
  • java.util.PropertyPermission
  • java.lang.reflect.ReflectPermission
  • java.lang.RuntimePermission
  • java.security.SecurityPermission
  • java.io.SerializablePermission
  • java.net.SocketPermission

The Permissions in the JDK documentation provides details about each of these permissions. Let's look at those needed to use RectangleArea as an extension.

The RectangleArea.writeArea method needs two permissions: one to determine the path to the user's home directory, and the other to write to a file. Assuming that the RectangleArea class is bundled in the file area.jar, you could grant write privileges by adding this entry to the policy file:

grant codeBase "file:${java.home}/lib/ext/area.jar" {
    permission java.io.PropertyPermission "user.home", "read";
    permission java.io.FilePermission "${user.home}${/}test${/}*", "write";
};
The codeBase "file:${java.home}/lib/ext/area.jar" part of this entry guarantees that any permissions specified by this entry will apply only to the area.jar. The java.io.PropertyPermission permits access to properties. The first argument, "user.home", names the property, and the second argument, "read", indicates that the property can be read. (The other choice is "write".)

The java.io.FilePermission permits access to files. The first argument, "${user.home}${/}test${/}*", indicates that area.jar is being granted permission to access all files in the test directory that is in the user's home directory. (Note that ${/} is a platform-independent file separator.) The second argument indicates that the file access being granted is only for writing. (Other choices for the second argument are "read", "delete", and "execute".)

Signing Extensions

You can use the policy file to place additional restrictions on the permissions granted to extensions by requiring them to be signed by a trusted entity. (For a review of signing and verifying JAR files, see the Signing JAR Files lesson in this tutorial.)

To allow signature verification of extensions or other software in conjunction with granting permissions, the policy file must contain a keystore entry. The keystore entry specifies which keystore is to be used in the verification. Keystore entries have the form

keystore "keystore_url";
The URL keystore_url is either an absolute or relative. If it's relative, the URL is relative to the location of the policy file. For example, to use the default keystore used by keytool, add this entry to java.policy
keystore "file://${user.home}/.keystore";

To indicate that an extension must be signed in order to be granted security privileges, you use the signedBy field. For example, the following entry indicates that the extension area.jar is to be granted the listed privileges only if it is signed by the users identified in the keystore by the aliases Robert and Rita:

grant signedBy "Robert,Rita",
    codeBase "file:${java.home}/lib/ext/area.jar" {
        permission java.io.PropertyPermission "user.home", "read";
        permission java.io.FilePermission "${user.home}${/}test${/}*", "write";
};
If the codeBase field is omitted, as in the following "grant", the permissions are granted to any software, including installed or download extensions, that are signed by "Robert" or "Rita":
grant signedBy "Robert,Rita" {
    permission java.io.FilePermission "*", "write";
};

For further details about the policy file format, see section 3.3.1 of the Security Architecture Specification in the JDK documentation.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Making Extensions Secure
Next page: Sealing Packages in Extensions


Sealing Packages in Extensions (The Java™ Tutorials > The Extension Mechanism > Making Extensions Secure)

Trail: The Extension Mechanism
Lesson: Making Extensions Secure
Making Extensions Secure
Setting Privileges for Extensions
Sealing Packages in Extensions
Home Page > The Extension Mechanism > Making Extensions Secure
« Previous • Trail • Next »
Sealing Packages in Extensions
You can optionally seal packages in extension JAR files as an additional security measure. If a package is sealed, all classes defined in that package must originate from a single JAR file.

Without sealing, a "hostile" program could create a class and define it to be a member of one of your extension packages. The hostile software would then have free access to package-protected members of your extension package.

Sealing packages in extensions is no different than sealing any JAR-packaged classes. To seal your extension packages, you must add the Sealed header to the manifest of the JAR file containing your extension. You can seal individual packages by associating a Sealed header with the packages' Name headers. A Sealed header not associated with an individual package in the archive signals that all packages are sealed. Such a "global" Sealed header is overridden by any Sealed headers associated with individual packages. The value associated with the Sealed header is either true or false.

Examples

Let's look at a few sample manifest files. For these examples suppose that the JAR file contains these packages:
com/myCompany/package_1/
com/myCompany/package_2/
com/myCompany/package_3/
com/myCompany/package_4/

Suppose that you want to seal all the packages. You could do so by simply adding an archive-level Sealed header to the manifest like this:

Manifest-Version: 1.0
Sealed: true
All packages in any JAR file having this manifest will be sealed.

If you wanted to seal only com.myCompany.package_3, you could do so with this manifest:

Manifest-Version: 1.0

Name: com/myCompany/package_3/
Sealed: true
In this example the only Sealed header is that associated with the Name header of package com.myCompany.package_3, so only that package is sealed. (The Sealed header is associated with the Name header because there are no blank lines between them.)

For a final example, suppose that you wanted to seal all packages except for com.myCompany.package_2. You could accomplish that with a manifest like this:

Manifest-Version: 1.0
Sealed: true

Name: com/myCompany/package_2/
Sealed: false
In this example the archive-level Sealed: true header indicates that all of the packages in the JAR file are to be sealed. However, the manifest also has a Sealed: false header associated with package com.myCompany.package_2, and that header overrides the archive-level sealing for that package. Therefore this manifest will cause all packages to be sealed except for com.myCompany.package_2.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Setting Privileges for Extensions
Next page: End of Trail


Trail: The Reflection API (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: The Reflection API

Uses of Reflection

Reflection is commonly used by programs which require the ability to examine or modify the runtime behavior of applications running in the Java virtual machine. This is a relatively advanced feature and should be used only by developers who have a strong grasp of the fundamentals of the language. With that caveat in mind, reflection is a powerful technique and can enable applications to perform operations which would otherwise be impossible.

Extensibility Features
An application may make use of external, user-defined classes by creating instances of extensibility objects using their fully-qualified names.
Class Browsers and Visual Development Environments
A class browser needs to be able to enumerate the members of classes. Visual development environments can benefit from making use of type information available in reflection to aid the developer in writing correct code.
Debuggers and Test Tools
Debuggers need to be able to examine private members on classes. Test harnesses can make use of reflection to systematically call a discoverable set APIs defined on a class, to insure a high level of code coverage in a test suite.

Drawbacks of Reflection

Reflection is powerful, but should not be used indiscriminately. If it is possible to perform an operation without using reflection, then it is preferable to avoid using it. The following concerns should be kept in mind when accessing code via reflection.
Performance Overhead
Because reflection involves types that are dynamically resolved, certain Java virtual machine optimizations can not be performed. Consequently, reflective operations have slower performance than their non-reflective counterparts, and should be avoided in sections of code which are called frequently in performance-sensitive applications.
Security Restrictions
Reflection requires a runtime permission which may not be present when running under a security manager. This is in an important consideration for code which has to run in a restricted security context, such as in an Applet.
Exposure of Internals
Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform.

Trail Lessons

This trail covers common uses of reflection for accessing and manipulating classes, fields, methods, and constructors. Each lesson contains code examples, tips, and troubleshooting information.
Classes
This lesson shows the various ways to obtain a Class object and use it to examine properties of a class, including its declaration and contents.
Members
This lesson describes how to use the Reflection APIs to find the fields, methods, and constructors of a class. Examples are provided for setting and getting field values, invoking methods, and creating new instances of objects using specific constructors.
Arrays and Enumerated Types
This lesson introduces two special types of classes: arrays, which are generated at runtime, and enum types, which define unique named object instances. Sample code shows how to retrieve the component type for an array and how to set and get fields with array or enum types.
Note: The examples in this trail are designed for experimenting with the Reflection APIs. The handling of exceptions therefore is not the same as would be used in production code. In particular, in production code it is not recommended to dump stack traces that are visible to the user.
« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Classes


Lesson: Classes (The Java™ Tutorials > The Reflection API)

Classes
Retrieving Class Objects
Examining Class Modifiers and Types
Discovering Class Members
Troubleshooting
Trail: The Reflection API
Home Page > The Reflection API
« Previous • Trail • Next »
Lesson: Classes
Every object is either a reference or primitive type. Reference types all inherit from java.lang.Object. Classes, enums, arrays, and interfaces are all reference types. There is a fixed set of primitive types: boolean, byte, short, int, long, char, float, and double. Examples of reference types include java.lang.String, all of the wrapper classes for primitive types such as java.lang.Double, the interface java.io.Serializable, and the enum javax.swing.SortOrder.

For every type of object, the Java virtual machine instantiates an immutable instance of java.lang.Class which provides methods to examine the runtime properties of the object including its members and type information. Class also provides the ability to create new classes and objects. Most importantly, it is the entry point for all of the Reflection APIs. This lesson covers the most commonly used reflection operations involving classes:

  • Retrieving Class Objects describes the ways to get a Class
  • Examining Class Modifiers and Types shows how to access the class declaration information
  • Discovering Class Members illustrates how to list the constructors, fields, methods, and nested classes in a class
  • Troubleshooting describes common errors encountered when using Class
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: Retrieving Class Objects


Retrieving Class Objects (The Java™ Tutorials > The Reflection API > Classes)

Trail: The Reflection API
Lesson: Classes
Section: Sealing Packages in Extensions
Classes
Retrieving Class Objects
Examining Class Modifiers and Types
Discovering Class Members
Troubleshooting
Home Page > The Reflection API > Classes
« Previous • Trail • Next »
Retrieving Class Objects
The entry point for all reflection operations is java.lang.Class. With the exception of java.lang.reflect.ReflectPermission, none of the classes in java.lang.reflect have public constructors. To get to these classes, it is necessary to invoke appropriate methods on Class. There are several ways to get a Class depending on whether the code has access to an object, the name of class, a type, or an existing Class.

Object.getClass()

If an instance of an object is available, then the simplest way to get its Class is to invoke Object.getClass(). Of course, this only works for reference types which all inherit from Object. Some examples follow.
Class c = "foo".getClass();
Returns the Class for String
Class c = System.console().getClass();
There is a unique console associated with the virtual machine which is returned by the static method System.console(). The value returned by getClass() is the Class corresponding to java.io.Console.
enum E { A, B }
Class c = A.getClass();
A is is an instance of the enum E; thus getClass() returns the Class corresponding to the enumeration type E.
byte[] bytes = new byte[1024];
Class c = bytes.getClass();
Since arrays are Objects, it is also possible to invoke getClass() on an instance of an array. The returned Class corresponds to an array with component type byte.
import java.util.HashSet;
import java.util.Set;

Set<String> s = new HashSet<String>();
Class c = s.getClass();
In this case, java.util.Set is an interface to an object of type java.util.HashSet. The value returned by getClass() is the class corresponding to java.util.HashSet.

The .class Syntax

If the type is available but there is no instance then it is possible to obtain a Class by appending ".class" to the name of the type. This is also the easiest way to obtain the Class for a primitive type.
boolean b;
Class c = b.getClass();   // compile-time error

Class c = boolean.class;  // correct
Note that the statement boolean.getClass() would produce a compile-time error because a boolean is a primitive type and cannot be dereferenced. The .class syntax returns the Class corresponding to the type boolean.
Class c = java.io.PrintStream.class;
The variable c will be the Class corresponding to the type java.io.PrintStream.
Class c = int[][][].class;
The .class syntax may be used to retrieve a Class corresponding to a multi-dimensional array of a given type.

Class.forName()

If the fully-qualified name of a class is available, it is possible to get the corresponding Class using the static method Class.forName(). This cannot be used for primitive types. The syntax for names of array classes is described by Class.getName(). This syntax is applicable to references and primitive types.
Class c = Class.forName("com.duke.MyLocaleServiceProvider");
This statement will create a class from the given fully-qualified name.
CLass cDoubleArray = Class.forName("[D");

Class cStringArray = Class.forName("[[Ljava.lang.String;");
The variable cDoubleArray will contain the Class corresponding to an array of primitive type double (i.e. the same as double[].class). The cStringArray variable will contain the Class corresponding to a two-dimensional array of String (i.e. identical to String[][].class).

TYPE Field for Primitive Type Wrappers

The .class syntax is a more convenient and the preferred way to obtain the Class for a primitive type; however there is another way to acquire the Class. Each of the primitive types and void has a wrapper class in java.lang that is used for boxing of primitive types to reference types. Each wrapper class contains a field named TYPE which is equal to the Class for the primitive type being wrapped.
Class c = Double.TYPE;
There is a class java.lang.Double which is used to wrap the primitive type double whenever an Object is required. The value of Double.TYPE is identical to that of double.class.
Class c = Void.TYPE;
Void.TYPE is identical to void.class.

Methods that Return Classes

There are several Reflection APIs which return classes but these may only be accessed if a Class has already been obtained either directly or indirectly.
Class.getSuperclass()
Returns the super class for the given class.
Class c = javax.swing.JButton.class.getSuperclass();
The super class of javax.swing.JButton is javax.swing.AbstractButton.
Class.getClasses()
Returns all the public classes, interfaces, and enums that are members of the class including inherited members.
Class<?>[] c = Character.class.getClasses();
Character contains two member classes Character.Subset and Character.UnicodeBlock.
Class.getDeclaredClasses()
Returns all of the classes interfaces, and enums that are explicitly declared in this class.
Class<?>[] c = Character.class.getDeclaredClasses();
Character contains two public member classes Character.Subset and Character.UnicodeBlock and one private class Character.CharacterCache.
{ Class , java.lang.reflect. { Field, Method, Constructor } }.getDeclaringClass()
Returns the Class in which these members were declared. Anonymous classes will not have a declaring class but will have an enclosing class.
import java.lang.reflect.Field;

Field f = System.class.getField("out");
Class c = f.getDeclaringClass();
The field out is declared in System.
public class MyClass {
    static Object o = new Object() { public void m() {} };
    static Class<c> = o.getClass().getEnclosingClass();
}
The declaring class of the anonymous class defined by o is null.
Class.getEnclosingClass()
Returns the immediately enclosing class of the class.
Class c = Thread.State.class().getEnclosingClass();
The enclosing class of the enum Thread.State is Thread.
public class MyClass {
    static Object o = new Object() { public void m() {} };
    static Class<c> = o.getClass().getEnclosingClass();
}
The anonymous class defined by o is enclosed by MyClass.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Classes
Next page: Examining Class Modifiers and Types


Examining Class Modifiers and Types (The Java™ Tutorials > The Reflection API > Classes)

Trail: The Reflection API
Lesson: Classes
Section: Sealing Packages in Extensions
Classes
Retrieving Class Objects
Examining Class Modifiers and Types
Discovering Class Members
Troubleshooting
Home Page > The Reflection API > Classes
« Previous • Trail • Next »
Examining Class Modifiers and Types
A class may be declared with one or more modifiers which affect its runtime behavior:
  • Access modifiers: public, protected, and private
  • Modifier requiring override: abstract
  • Modifier restricting to one instance: static
  • Modifier prohibiting value modification: final
  • Modifier forcing strict floating point behavior: strictfp
  • Annotations
Not all modifiers are allowed on all classes, for example an interface cannot be final and an enum cannot be abstract. java.lang.reflect.Modifier contains declarations for all possible modifiers. It also contains methods which may be used to decode the set of modifiers returned by Class.getModifiers().

The ClassDeclarationSpy example shows how to obtain the declaration components of a class including the modifiers, generic type parameters, implemented interfaces, and the inheritance path. Since Class implements the java.lang.reflect.AnnotatedElement interface it is also possible to query the runtime annotations.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.annotation.Annotation;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
import static java.lang.System.out;

public class ClassDeclarationSpy {
    public static void main(String... args) {
    try {
        Class<?> c = Class.forName(args[0]);
        out.format("Class:%n  %s%n%n", c.getCanonicalName());
        out.format("Modifiers:%n  %s%n%n",
               Modifier.toString(c.getModifiers()));

        out.format("Type Parameters:%n");
        TypeVariable[] tv = c.getTypeParameters();
        if (tv.length != 0) {
        out.format("  ");
        for (TypeVariable t : tv)
            out.format("%s ", t.getName());
        out.format("%n%n");
        } else {
        out.format("  -- No Type Parameters --%n%n");
        }

        out.format("Implemented Interfaces:%n");
        Type[] intfs = c.getGenericInterfaces();
        if (intfs.length != 0) {
        for (Type intf : intfs)
            out.format("  %s%n", intf.toString());
        out.format("%n");
        } else {
        out.format("  -- No Implemented Interfaces --%n%n");
        }

        out.format("Inheritance Path:%n");
        List<Class> l = new ArrayList<Class>();
        printAncestor(c, l);
        if (l.size() != 0) {
        for (Class<?> cl : l)
            out.format("  %s%n", cl.getCanonicalName());
        out.format("%n");
        } else {
        out.format("  -- No Super Classes --%n%n");
        }

        out.format("Annotations:%n");
        Annotation[] ann = c.getAnnotations();
        if (ann.length != 0) {
        for (Annotation a : ann)
            out.format("  %s%n", a.toString());
        out.format("%n");
        } else {
        out.format("  -- No Annotations --%n%n");
        }

        // production code should handle this exception more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    }
    }

    private static void printAncestor(Class<?> c, List<Class> l) {
    Class<?> ancestor = c.getSuperclass();
     if (ancestor != null) {
        l.add(ancestor);
        printAncestor(ancestor, l);
     }
    }
}
A few samples of the output follows. User input is in italics.
$ java ClassDeclarationSpy java.util.concurrent.ConcurrentNavigableMap
Class:
  java.util.concurrent.ConcurrentNavigableMap

Modifiers:
  public abstract interface

Type Parameters:
  K V

Implemented Interfaces:
  java.util.concurrent.ConcurrentMap<K, V>
  java.util.NavigableMap<K, V>

Inheritance Path:
  -- No Super Classes --

Annotations:
  -- No Annotations --
This is the actual declaration for java.util.concurrent.ConcurrentNavigableMap in the source code:
public interface ConcurrentNavigableMap<K,V>
    extends ConcurrentMap, NavigableMap<K,V>
Note that since this is an interface, it is implicitly abstract. The compiler adds this modifier for every interface. Also, this declaration contains two generic type parameters, K and V. The example code simply prints the names of these parameters, but is it possible to retrieve additional information about them using methods in java.lang.reflect.TypeVariable. Interfaces may also implement other interfaces as shown above.
$ java ClassDeclarationSpy "[Ljava.lang.String;"
Class:
  java.lang.String[]

Modifiers:
  public abstract final

Type Parameters:
  -- No Type Parameters --

Implemented Interfaces:
  interface java.lang.Cloneable
  interface java.io.Serializable

Inheritance Path:
  java.lang.Object

Annotations:
  -- No Annotations --
Since arrays are runtime objects, all of the type information is defined by the Java virtual machine. In particular, arrays implement Cloneable and java.io.Serializable and their direct superclass is always Object.
$ java ClassDeclarationSpy java.io.InterruptedIOException
Class:
  java.io.InterruptedIOException

Modifiers:
  public

Type Parameters:
  -- No Type Parameters --

Implemented Interfaces:
  -- No Implemented Interfaces --

Inheritance Path:
  java.io.IOException
  java.lang.Exception
  java.lang.Throwable
  java.lang.Object

Annotations:
  -- No Annotations --
From the inheritance path, it may be deduced that java.io.InterruptedIOException is a checked exception because RuntimeException is not present.
$ java ClassDeclarationSpy java.security.Identity
Class:
  java.security.Identity

Modifiers:
  public abstract

Type Parameters:
  -- No Type Parameters --

Implemented Interfaces:
  interface java.security.Principal
  interface java.io.Serializable

Inheritance Path:
  java.lang.Object

Annotations:
  @java.lang.Deprecated()
This output shows that java.security.Identity, a deprecated API, possesses the annotation java.lang.Deprecated. This may be used by reflective code to detect deprecated APIs.
Note: Not all annotations are available via reflection. Only those which have a java.lang.annotation.RetentionPolicy of RUNTIME are accessible. Of the three annotations pre-defined in the language @Deprecated, @Override, and @SuppressWarnings only @Deprecated is available at runtime.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Retrieving Class Objects
Next page: Discovering Class Members


Discovering Class Members (The Java™ Tutorials > The Reflection API > Classes)

Trail: The Reflection API
Lesson: Classes
Section: Sealing Packages in Extensions
Classes
Retrieving Class Objects
Examining Class Modifiers and Types
Discovering Class Members
Troubleshooting
Home Page > The Reflection API > Classes
« Previous • Trail • Next »
Discovering Class Members
There are two categories of methods provided in Class for accessing fields, methods, and constructors: methods which enumerate these members and methods which search for particular members. Also there are distinct methods for accessing members declared directly on the class versus methods which search the superinterfaces and superclasses for inherited members. The following table provides a summary of all the member-locating methods and their characteristics.

Class Methods for Locating Members
Member | Class API | List of members? | Inherited members? | Private members?
Field | getDeclaredField() | no | no | yes
getField() | no | yes | no
getDeclaredFields() | yes | no | yes
getFields() | yes | yes | no
Method | getDeclaredMethod() | no | no | yes
getMethod() | no | yes | no
getDeclaredMethods() | yes | no | yes
getMethods() | yes | yes | no
Constructor | getDeclaredConstructor() | no | N/A1 | yes
getConstructor() | no | N/A1 | no
getDeclaredConstructors() | yes | N/A1 | yes
getConstructors() | yes | N/A1 | no

1 Constructors are not inherited.

Given a class name and an indication of which members are of interest, the ClassSpy example uses the get*s() methods to determine the list of all public elements, including any which are inherited.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Member;
import static java.lang.System.out;

enum ClassMember { CONSTRUCTOR, FIELD, METHOD, CLASS, ALL }

public class ClassSpy {
    public static void main(String... args) {
    try {
        Class<?> c = Class.forName(args[0]);
        out.format("Class:%n  %s%n%n", c.getCanonicalName());

        Package p = c.getPackage();
        out.format("Package:%n  %s%n%n",
               (p != null ? p.getName() : "-- No Package --"));

        for (int i = 1; i < args.length; i++) {
        switch (ClassMember.valueOf(args[i])) {
        case CONSTRUCTOR:
            printMembers(c.getConstructors(), "Constructor");
            break;
        case FIELD:
            printMembers(c.getFields(), "Fields");
            break;
        case METHOD:
            printMembers(c.getMethods(), "Methods");
            break;
        case CLASS:
            printClasses(c);
            break;
        case ALL:
            printMembers(c.getConstructors(), "Constuctors");
            printMembers(c.getFields(), "Fields");
            printMembers(c.getMethods(), "Methods");
            printClasses(c);
            break;
        default:
            assert false;
        }
        }

        // production code should handle these exceptions more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    }
    }

    private static void printMembers(Member[] mbrs, String s) {
    out.format("%s:%n", s);
    for (Member mbr : mbrs) {
        if (mbr instanceof Field)
        out.format("  %s%n", ((Field)mbr).toGenericString());
        else if (mbr instanceof Constructor)
        out.format("  %s%n", ((Constructor)mbr).toGenericString());
        else if (mbr instanceof Method)
        out.format("  %s%n", ((Method)mbr).toGenericString());
    }
    if (mbrs.length == 0)
        out.format("  -- No %s --%n", s);
    out.format("%n");
    }

    private static void printClasses(Class<?> c) {
    out.format("Classes:%n");
    Class<?>[] clss = c.getClasses();
    for (Class<?> cls : clss)
        out.format("  %s%n", cls.getCanonicalName());
    if (clss.length == 0)
        out.format("  -- No member interfaces, classes, or enums --%n");
    out.format("%n");
    }
}

This example is relatively compact; however the printMembers() method is slightly awkward due to the fact that the java.lang.reflect.Member interface has existed since the earliest implementations of reflection and it could not be modified to include the more useful getGenericString() method when generics were introduced. The only alternatives are to test and cast as shown, replace this method with printConstructors(), printFields(), and printMethods(), or to be satisfied with the relatively spare results of Member.getName().

Samples of the output and their interpretation follows. User input is in italics.

$ java ClassSpy java.lang.ClassCastException CONSTRUCTOR
Class:
  java.lang.ClassCastException

Package:
  java.lang

Constructor:
  public java.lang.ClassCastException()
  public java.lang.ClassCastException(java.lang.String)

Since constructors are not inherited, the exception chaining mechanism constructors (those with a Throwable parameter) which are defined in the immediate super class RuntimeException and other super classes are not found.

$ java ClassSpy java.nio.channels.ReadableByteChannel METHOD
Class:
  java.nio.channels.ReadableByteChannel

Package:
  java.nio.channels

Methods:
  public abstract int java.nio.channels.ReadableByteChannel.read(java.nio.ByteBuffer) throws java.io.IOException
  public abstract void java.nio.channels.Channel.close() throws java.io.IOException
  public abstract boolean java.nio.channels.Channel.isOpen()
The interface java.nio.channels.ReadableByteChannel defines read(). The remaining methods are inherited from a super interface. This code could easily be modified to list only those methods that are actually declared in the class by replacing get*s() with getDeclared*s().
$ java ClassSpy ClassMember FIELD METHOD
Class:
  ClassMember

Package:
  -- No Package --

Fields:
  public static final ClassMember ClassMember.CONSTRUCTOR
  public static final ClassMember ClassMember.FIELD
  public static final ClassMember ClassMember.METHOD
  public static final ClassMember ClassMember.CLASS
  public static final ClassMember ClassMember.ALL

Methods:
  public static ClassMember ClassMember.valueOf(java.lang.String)
  public static ClassMember[] ClassMember.values()
  public final int java.lang.Enum.hashCode()
  public final int java.lang.Enum.compareTo(E)
  public int java.lang.Enum.compareTo(java.lang.Object)
  public final java.lang.String java.lang.Enum.name()
  public final boolean java.lang.Enum.equals(java.lang.Object)
  public java.lang.String java.lang.Enum.toString()
  public static <T> T java.lang.Enum.valueOf(java.lang.Class<T>,java.lang.String)
  public final java.lang.Class<E> java.lang.Enum.getDeclaringClass()
  public final int java.lang.Enum.ordinal()
  public final native java.lang.Class<?> java.lang.Object.getClass()
  public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
  public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
  public final void java.lang.Object.wait() throws java.lang.InterruptedException
  public final native void java.lang.Object.notify()
  public final native void java.lang.Object.notifyAll()

In the fields portion of these results, enum constants are listed. While these are technically fields, it might be useful to distinguish them from other fields. This example could be modified to use java.lang.reflect.Field.isEnumConstant() for this purpose. The EnumSpy example in a later section of this trail, Examining Enums, contains a possible implementation.

In the methods section of the output, observe that the method name includes the name of the declaring class. Thus, the toString() method is implemented by Enum, not inherited from Object. The code could be amended to make this more obvious by using Field.getDeclaringClass(). The following fragment illustrates part of a potential solution.

if (mbr instanceof Field) {
    Field f = (Field)mbr;
    out.format("  %s%n", f.toGenericString());
    out.format("  -- declared in: %s%n", f.getDeclaringClass());
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Examining Class Modifiers and Types
Next page: Troubleshooting


Troubleshooting (The Java™ Tutorials > The Reflection API > Classes)

Trail: The Reflection API
Lesson: Classes
Section: Sealing Packages in Extensions
Classes
Retrieving Class Objects
Examining Class Modifiers and Types
Discovering Class Members
Troubleshooting
Home Page > The Reflection API > Classes
« Previous • Trail • Next »
Troubleshooting
The following examples show typical errors which may be encountered when reflecting on classes.

Compiler Warning: "Note: ... uses unchecked or unsafe operations"

When a method is invoked, the types of the argument values are checked and possibly converted. ClassWarning invokes getMethod() to cause a typical unchecked conversion warning:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Method;

public class ClassWarning {
    void m() {
    try {
        Class c = ClassWarning.class;
        Method m = c.getMethod("m");  // warning

        // production code should handle this exception more gracefully
    } catch (NoSuchMethodException x) {
            x.printStackTrace();
        }
    }
}

$ javac ClassWarning.java
Note: ClassWarning.java uses unchecked or unsafe operations.
Note: Recompile with -Xlint:unchecked for details.
$ javac -Xlint:unchecked ClassWarning.java
ClassWarning.java:7: warning: [unchecked] unchecked call to getMethod(java.lang.String,java.lang.Class<?>...) as a member of the raw type java.lang.Class
            Method m = c.getMethod("m");  // warning
                                  ^
1 warning
Many library methods have been retrofitted with generic declarations including several in Class. Since c is declared as a raw type (has no type parameters) and the corresponding parameter of getMethod() is a parameterized type, an unchecked conversion occurs. The compiler is required to generate a warning. (See The Java Language Specification, Third Edition, sections 5.1.9 and 5.3.)

There are two possible solutions. The more preferable it to modify the declaration of c to include an appropriate generic type. In this case, the declaration should be:

Class<?> c = warn.getClass();
Alternatively, the warning could be explicitly suppressed using the predefined annotation @SuppressWarnings preceding the problematic statement.
Class c = ClassWarning.class;
@SuppressWarnings("unchecked")
Method m = c.getMethod("m");  // warning gone
Tip: As a general principle, warnings should not be ignored as they may indicate the presence of a bug. Parameterized declarations should be used as appropriate. If that is not possible (perhaps because an application must interact with a library vendor's code), annotate the offending line using @SuppressWarnings.

InstantiationException when the Constructor is Not Accessible

Class.newInstance() will throw an InstantiationException if an attempt is made to create a new instance of the class and the zero-argument constructor is not visible. The ClassTrouble example illustrates the resulting stack trace.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

class Cls {
    private Cls() {}
}

public class ClassTrouble {
    public static void main(String... args) {
    try {
        Class<?> c = Class.forName("Cls");
        c.newInstance();  // InstantiationException

        // production code should handle these exceptions more gracefully
    } catch (InstantiationException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    }
    }
}

$ java ClassTrouble
java.lang.IllegalAccessException: Class ClassTrouble can not access a member of
class Cls with modifiers "private"
        at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
        at java.lang.Class.newInstance0(Class.java:349)
        at java.lang.Class.newInstance(Class.java:308)
        at ClassTrouble.main(ClassTrouble.java:9)
Class.newInstance() behaves very much like the new keyword and will fail for the same reasons new would fail. The typical solution in reflection is to take advantage of the java.lang.reflect.AccessibleObject class which provides the ability to suppress access control checks; however, this approach will not work because java.lang.Class does not extend AccessibleObject. The only solution is to modify the code to use Constructor.newInstance() which does extend AccessibleObject.
Tip: In general, it is preferable to use Constructor.newInstance() for the reasons described in the Creating New Class Instances section in the Members lesson.

Additional examples of potential problems using Constructor.newInstance() may be found in the Constructor Troubleshooting section of the Members lesson.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Discovering Class Members
Next page: Members


Lesson: Members (The Java™ Tutorials > The Reflection API)

Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Trail: The Reflection API
Home Page > The Reflection API
« Previous • Trail • Next »
Lesson: Members
Reflection defines an interface java.lang.reflect.Member which is implemented by java.lang.reflect.Field, java.lang.reflect.Method, and java.lang.reflect.Constructor . These objects will be discussed in this lesson. For each member, the lesson will describe the associated APIs to retrieve declaration and type information, any operations unique to the member (for example, setting the value of a field or invoking a method), and commonly encountered errors. Each concept will be illustrated with code samples and related output which approximate some expected reflection uses.
Note: According to The Java Language Specification, Third Edition, the members of a class are the inherited components of the class body including fields, methods, nested classes, interfaces, and enumerated types. Since constructors are not inherited, they are not members. This differs from the implementing classes of java.lang.reflect.Member.

Fields

Fields have a type and a value. The java.lang.reflect.Field class provides methods for accessing type information and setting and getting values of a field on a given object.

  • Obtaining Field Types describes how to get the declared and generic types of a field
  • Retrieving and Parsing Field Modifiers shows how to get portions of the field declaration such as public or transient
  • Getting and Setting Field Values illustrates how to access field values
  • Troubleshooting describes some common coding errors which may cause confusion

Methods

Methods have return values, parameters, and may throw exceptions. The java.lang.reflect.Method class provides methods for obtained the type information for the parameters and return value. It may also be used to invoke methods on a given object.

  • Obtaining Method Type Information shows how to enumerate methods declared in a class and obtains type information
  • Retrieving and Parsing Method Modifiers describes how to access and decode modifiers and other information associated with the method
  • Invoking Methods illustrates how to execute a method and obtain its return value
  • Troubleshooting covers common errors encountered when finding or invoking methods

Constructors

The Reflection APIs for constructors are defined in java.lang.reflect.Constructor and are similar to those for methods, with two major exceptions: first, constructors have no return values; second, the invocation of a constructor creates a new instance of an object for a given class.

  • Finding Constructors illustrates how to retrieve constructors with specific parameters
  • Retrieving and Parsing Constructor Modifiers shows how to obtain the modifiers of a constructor declaration and other information about the constructor
  • Creating New Class Instances shows how to instantiate an instance of an object by invoking its constructor
  • Troubleshooting describes common errors which may be encountered while finding or invoking constructors
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Fields


Fields (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Fields
A field is a class, interface, or enum with an associated value. Methods in the java.lang.reflect.Field class can retrieve information about the field, such as its name, type, modifiers, and annotations. (The section Examining Class Modifiers and Types in the Classes lesson describes how to retrieve annotations.) There are also methods which enable dynamic access and modification of the value of the field. These tasks are covered in the following sections:
  • Obtaining Field Types describes how to get the declared and generic types of a field
  • Retrieving and Parsing Field Modifiers shows how to get portions of the field declaration such as public or transient
  • Getting and Setting Field Values illustrates how to access field values
  • Troubleshooting describes some common coding errors which may cause confusion

When writing an application such as a class browser, it might be useful to find out which fields belong to a particular class. A class's fields are identified by invoking Class.getFields(). The getFields() method returns an array of Field objects containing one object per accessible public field.

A public field is accessible if it is a member of either:

  • this class
  • a superclass of this class
  • an interface implemented by this class
  • an interface extended from an interface implemented by this class

A field may be a class (instance) field, such as java.io.Reader.lock , a static field, such as java.lang.Integer.MAX_VALUE , or an enum constant, such as java.lang.Thread.State.WAITING.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Members
Next page: Obtaining Field Types


Obtaining Field Types (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Section: Fields
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Obtaining Field Types

A field may be either of primitive or reference type. There are eight primitive types: boolean, byte, short, int, long, char, float, and double. A reference type is anything that is a direct or indirect subclass of java.lang.Object including interfaces, arrays, and enumerated types.

The FieldSpy example prints the field's type and generic type given a fully-qualified binary class name and field name.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Field;
import java.util.List;

public class FieldSpy<T> {
    public boolean[][] b = {{ false, false }, { true, true } };
    public String name  = "Alice";
    public List<Integer> list;
    public T val;

    public static void main(String... args) {
    try {
        Class<?> c = Class.forName(args[0]);
        Field f = c.getField(args[1]);
        System.out.format("Type: %s%n", f.getType());
        System.out.format("GenericType: %s%n", f.getGenericType());

        // production code should handle these exceptions more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    } catch (NoSuchFieldException x) {
        x.printStackTrace();
    }
    }
}
Sample output to retrieve the type of the three public fields in this class (b, name, and the parameterized type list), follows. User input is in italics.
$ java FieldSpy FieldSpy b
Type: class [[Z
GenericType: class [[Z
$ java FieldSpy FieldSpy name
Type: class java.lang.String
GenericType: class java.lang.String
$ java FieldSpy FieldSpy list
Type: interface java.util.List
GenericType: java.util.List
$ java FieldSpy FieldSpy T
Type: class java.lang.Object
GenericType: T

The type for the field b is two-dimensional array of boolean. The syntax for the type name is described in Class.getName().

The type for the field val is reported as java.lang.Object because generics are implemented via type erasure which removes all information regarding generic types during compilation. Thus T is replaced by the upper bound of the type variable, in this case, java.lang.Object.

Field.getGenericType() will consult the Signature Attribute in the class file if it's present. If the attribute isn't available, it falls back on Field.getType() which was not changed by the introduction of generics. The other methods in reflection with name getGenericFoo for some value of Foo are implemented similarly.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Fields
Next page: Retrieving and Parsing Field Modifiers


Retrieving and Parsing Field Modifiers (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Section: Fields
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Retrieving and Parsing Field Modifiers
There are several modifiers that may be part of a field declaration:
  • Access modifiers: public, protected, and private
  • Field-specific modifiers governing runtime behavior: transient and volatile
  • Modifier restricting to one instance: static
  • Modifier prohibiting value modification: final
  • Annotations

The method Field.getModifiers() can be used to return the integer representing the set of declared modifiers for the field. The bits representing the modifiers in this integer are defined in java.lang.reflect.Modifier.

The FieldModifierSpy example illustrates how to search for fields with a given modifier. It also determines whether the located field is synthetic (compiler-generated) or is an enum constant by invoking Field.isSynthetic() and Field.isEnumCostant() respectively.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import static java.lang.System.out;

enum Spy { BLACK , WHITE }

public class FieldModifierSpy {
    volatile int share;
    int instance;
    class Inner {}

    public static void main(String... args) {
    try {
        Class<?> c = Class.forName(args[0]);
        int searchMods = 0x0;
        for (int i = 1; i < args.length; i++) {
        searchMods |= modifierFromString(args[i]);
        }

        Field[] flds = c.getDeclaredFields();
        out.format("Fields in Class '%s' containing modifiers:  %s%n",
               c.getName(),
               Modifier.toString(searchMods));
        boolean found = false;
        for (Field f : flds) {
        int foundMods = f.getModifiers();
        // Require all of the requested modifiers to be present
        if ((foundMods & searchMods) == searchMods) {
            out.format("%-8s [ synthetic=%-5b enum_constant=%-5b ]%n",
                   f.getName(), f.isSynthetic(),
                   f.isEnumConstant());
            found = true;
        }
        }

        if (!found) {
        out.format("No matching fields%n");
        }

        // production code should handle this exception more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    }
    }

    private static int modifierFromString(String s) {
    int m = 0x0;
    if ("public".equals(s))           m |= Modifier.PUBLIC;
    else if ("protected".equals(s))   m |= Modifier.PROTECTED;
    else if ("private".equals(s))     m |= Modifier.PRIVATE;
    else if ("static".equals(s))      m |= Modifier.STATIC;
    else if ("final".equals(s))       m |= Modifier.FINAL;
    else if ("transient".equals(s))   m |= Modifier.TRANSIENT;
    else if ("volatile".equals(s))    m |= Modifier.VOLATILE;
    return m;
    }
}

Sample output follows:

$ java FieldModifierSpy FieldModifierSpy volatile
Fields in Class 'FieldModifierSpy' containing modifiers:  volatile
share    [ synthetic=false enum_constant=false ]
$ java FieldModifierSpy Spy public
Fields in Class 'Spy' containing modifiers:  public
BLACK    [ synthetic=false enum_constant=true  ]
WHITE    [ synthetic=false enum_constant=true  ]
$ java FieldModifierSpy FieldModifierSpy\$Inner final
Fields in Class 'FieldModifierSpy$Inner' containing modifiers:  final
this$0   [ synthetic=true  enum_constant=false ]
$ java FieldModifierSpy Spy private static final
Fields in Class 'Spy' containing modifiers:  private static final
$VALUES  [ synthetic=true  enum_constant=false ]

Notice that some fields are reported even though they are not declared in the original code. This is because the compiler will generate some synthetic fields which are needed during runtime. To test whether a field is synthetic, the example invokes Field.isSynthetic(). The set of synthetic fields is compiler-dependent; however commonly used fields include this$0 for inner classes (i.e. nested classes that are not static member classes) to reference the outermost enclosing class and $VALUES used by enums to implement the implicitly defined static method values(). The names of synthetic class members are not specified and may not be the same in all compiler implementations or releases. These and other synthetic fields will be included in the array returned by Class.getDeclaredFields() but not identified by Class.getField() since synthetic members are not typically public.

Because Field implements the interface java.lang.reflect.AnnotatedElement, it is possible to retrieve any runtime annotation with java.lang.annotation.RetentionPolicy.RUNTIME. For an example of obtaining annotations see the section Examining Class Modifiers and Types.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Obtaining Field Types
Next page: Getting and Setting Field Values


Getting and Setting Field Values (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Section: Fields
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Getting and Setting Field Values

Given an instance of a class, it is possible to use reflection to set the values of fields in that class. This is typically done only in special circumstances when setting the values in the usual way is not possible. Because such access usually violates the design intentions of the class, it should be used with the utmost discretion.

The Book class illustrates how to set the values for long, array, and enum field types. Methods for getting and setting other primitive types are described in Field.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Field;
import java.util.Arrays;
import static java.lang.System.out;

enum Tweedle { DEE, DUM }

public class Book {
    public long chapters = 0;
    public String[] characters = { "Alice", "White Rabbit" };
    public Tweedle twin = Tweedle.DEE;

    public static void main(String... args) {
    Book book = new Book();
    String fmt = "%6S:  %-12s = %s%n";

    try {
        Class<?> c = book.getClass();

        Field chap = c.getDeclaredField("chapters");
        out.format(fmt, "before", "chapters", book.chapters);
          chap.setLong(book, 12);
        out.format(fmt, "after", "chapters", chap.getLong(book));

        Field chars = c.getDeclaredField("characters");
        out.format(fmt, "before", "characters",
               Arrays.asList(book.characters));
        String[] newChars = { "Queen", "King" };
        chars.set(book, newChars);
        out.format(fmt, "after", "characters",
               Arrays.asList(book.characters));

        Field t = c.getDeclaredField("twin");
        out.format(fmt, "before", "twin", book.twin);
        t.set(book, Tweedle.DUM);
        out.format(fmt, "after", "twin", t.get(book));

        // production code should handle these exceptions more gracefully
    } catch (NoSuchFieldException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    }
    }
}

This is the corresponding output:

$ java Book
BEFORE:  chapters     = 0
 AFTER:  chapters     = 12
BEFORE:  characters   = [Alice, White Rabbit]
 AFTER:  characters   = [Queen, King]
BEFORE:  twin         = DEE
 AFTER:  twin         = DUM
Note: Setting a field's value via reflection has a certain amount of performance overhead because various operations must occur such as validating access permissions. From the runtime's point of view, the effects are the same, and the operation is as atomic as if the value was changed in the class code directly.

Use of reflection can cause some runtime optimizations to be lost. For example, the following code is highly likely be optimized by a Java virtual machine:

int x = 1;
x = 2;
x = 3;
Equivalent code using Field.set*() may not.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Retrieving and Parsing Field Modifiers
Next page: Troubleshooting


Troubleshooting (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Section: Fields
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Troubleshooting

Here are a few common problems encountered by developers with explanations for why the occur and how to resolve them.

IllegalArgumentException due to Inconvertible Types

The FieldTrouble example will generate an IllegalArgumentException. Field.setInt() is invoked to set a field that is of the reference type Integer with a value of primitive type. In the non-reflection equivalent Integer val = 42, the compiler would convert (or box) the primitive type 42 to a reference type as new Integer(42) so that its type checking will accept the statement. When using reflection, type checking only occurs at runtime so there is no opportunity to box the value.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Field;

public class FieldTrouble {
    public Integer val;

    public static void main(String... args) {
    FieldTrouble ft = new FieldTrouble();
    try {
        Class<?> c = ft.getClass();
        Field f = c.getDeclaredField("val");
          f.setInt(ft, 42);               // IllegalArgumentException

        // production code should handle these exceptions more gracefully
    } catch (NoSuchFieldException x) {
        x.printStackTrace();
     } catch (IllegalAccessException x) {
         x.printStackTrace();
    }
    }
}

$ java FieldTrouble
Exception in thread "main" java.lang.IllegalArgumentException: Can not set
java.lang.Object field FieldTrouble.val to (long)42
        at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
        at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:174)
        at sun.reflect.UnsafeObjectFieldAccessorImpl.setLong(UnsafeObjectFieldAccessorImpl.java:102)
        at java.lang.reflect.Field.setLong(Field.java:831)
        at FieldTrouble.main(FieldTrouble.java:11)

To eliminate this exception, the problematic line should be replaced by the following invocation of Field.set(Object obj, Object value):

f.set(ft, new Integer(43));
Tip: When using reflection to set or get a field, the compiler does not have an opportunity to perform boxing. It can only convert types that are related as described by the specification for Class.isAssignableFrom(). The example is expected to fail because isAssignableFrom() will return false in this test which can be used programmatically to verify whether a particular conversion is possible:
Integer.class.isAssignableFrom(int.class) == false
Similarly, automatic conversion from primitive to reference type is also impossible in reflection.
int.class.isAssignableFrom(Integer.class) == false

NoSuchFieldException for Non-Public Fields

The astute reader may notice that if the FieldSpy example shown earlier is used to get information on a non-public field, it will fail:

$ java FieldSpy java.lang.String count
java.lang.NoSuchFieldException: count
        at java.lang.Class.getField(Class.java:1519)
        at FieldSpy.main(FieldSpy.java:12)
Tip: The Class.getField() and Class.getFields() methods return the public member field(s) of the class, enum, or interface represented by the Class object. To retrieve all fields declared (but not inherited) in the Class, use the Class.getDeclaredFields() method.

IllegalAccessException when Modifying Final Fields

An IllegalAccessException may be thrown if an attempt is made to get or set the value of a private or otherwise inaccessible field or to set the value of a final field (regardless of its access modifiers).

The FieldTroubleToo example illustrates the type of stack trace which results from attempting to set a final field.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Field;

public class FieldTroubleToo {
    public final boolean b = true;

    public static void main(String... args) {
    FieldTroubleToo ft = new FieldTroubleToo();
    try {
        Class<?> c = ft.getClass();
        Field f = c.getDeclaredField("b");
// 	    f.setAccessible(true);  // solution
        f.setBoolean(ft, Boolean.FALSE);   // IllegalAccessException

        // production code should handle these exceptions more gracefully
    } catch (NoSuchFieldException x) {
        x.printStackTrace();
    } catch (IllegalArgumentException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    }
    }
}

$ java FieldTroubleToo
java.lang.IllegalAccessException: Can not set final boolean field FieldTroubleToo.b to (boolean)false
        at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:55)
        at sun.reflect.UnsafeFieldAccessorImpl.throwFinalFieldIllegalAccessException(UnsafeFieldAccessorImpl.java:63)
        at sun.reflect.UnsafeQualifiedBooleanFieldAccessorImpl.setBoolean(UnsafeQualifiedBooleanFieldAccessorImpl.java:78)
        at java.lang.reflect.Field.setBoolean(Field.java:686)
        at FieldTroubleToo.main(FieldTroubleToo.java:12)
Tip: An access restriction exists which prevents final fields from being set after initialization of the class. However, Field is declared to extend AccessibleObject which provides the ability to suppress this check.

If AccessibleObject.setAccessible() succeeds, then subsequent operations on this field value will not fail do to this problem. This may have unexpected side-effects; for example, sometimes the original value will continue to be used by some sections of the application even though the value has been modified. AccessibleObject.setAccessible() will only succeed if the operation is allowed by the security context.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Getting and Setting Field Values
Next page: Methods


Methods (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Methods
A method contains executable code which may be invoked. Methods are inherited and in non-reflective code behaviors such as overloading, overriding, and hiding are enforced by the compiler. In contrast, reflective code makes it possible for method selection to be restricted to a specific class without considering its superclasses. Superclass methods may be accessed but it is possible to determine their declaring class; this is impossible to discover programmatically without reflection and is the source of many subtle bugs.

The java.lang.reflect.Method class provides APIs to access information about a method's modifiers, return type, parameters, annotations, and thrown exceptions. It also be used to invoke methods. These topics are covered by the following sections:

  • Obtaining Method Type Information shows how to enumerate methods declared in a class and obtains type information
  • Retrieving and Parsing Method Modifiers describes how to access and decode modifiers and other information associated with the method
  • Invoking Methods illustrates how to execute a method and obtain its return value
  • Troubleshooting covers common errors encountered when finding or invoking methods
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Troubleshooting
Next page: Obtaining Method Type Information


Obtaining Method Type Information (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Section: Methods
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Obtaining Method Type Information

A method declaration includes the name, modifiers, parameters, return type, and list of throwable exceptions. The java.lang.reflect.Method class provides a way to obtain this information.

The MethodSpy example illustrates how to enumerate all of the declared methods in a given class and retrieve the return, parameter, and exception types for all the methods of the given name.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import static java.lang.System.out;

public class MethodSpy {
    private static final String  fmt = "%24s: %s%n";

    // for the morbidly curious
    <E extends RuntimeException> void genericThrow() throws E {}

    public static void main(String... args) {
    try {
        Class<?> c = Class.forName(args[0]);
        Method[] allMethods = c.getDeclaredMethods();
        for (Method m : allMethods) {
        if (!m.getName().equals(args[1])) {
            continue;
        }
        out.format("%s%n", m.toGenericString());

        out.format(fmt, "ReturnType", m.getReturnType());
        out.format(fmt, "GenericReturnType", m.getGenericReturnType());

        Class<?>[] pType  = m.getParameterTypes();
        Type[] gpType = m.getGenericParameterTypes();
        for (int i = 0; i < pType.length; i++) {
            out.format(fmt,"ParameterType", pType[i]);
            out.format(fmt,"GenericParameterType", gpType[i]);
        }

        Class<?>[] xType  = m.getExceptionTypes();
        Type[] gxType = m.getGenericExceptionTypes();
        for (int i = 0; i < xType.length; i++) {
            out.format(fmt,"ExceptionType", xType[i]);
            out.format(fmt,"GenericExceptionType", gxType[i]);
        }
        }

        // production code should handle these exceptions more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    }
    }
}

Here is the output for Class.getConstructor() which is an example of a method with parameterized types and a variable number of parameters.

$ java MethodSpy java.lang.Class getConstructor
public java.lang.reflect.Constructor<T> java.lang.Class.getConstructor(java.lang.Class<?>[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException
              ReturnType: class java.lang.reflect.Constructor
       GenericReturnType: java.lang.reflect.Constructor<T>
           ParameterType: class [Ljava.lang.Class;
    GenericParameterType: java.lang.Class<?>[]
           ExceptionType: class java.lang.NoSuchMethodException
    GenericExceptionType: class java.lang.NoSuchMethodException
           ExceptionType: class java.lang.SecurityException
    GenericExceptionType: class java.lang.SecurityException

This is the actual declaration of the method in source code:

public Constructor<T> getConstructor(Class<?>... parameterTypes)

First note that the return and parameter types are generic. Method.getGenericReturnType() will consult the Signature Attribute in the class file if it's present. If the attribute isn't available, it falls back on Method.getReturnType() which was not changed by the introduction of generics. The other methods with name getGenericFoo() for some value of Foo in reflection are implemented similarly.

Next, notice that the last (and only) parameter, parameterType, is of variable arity (has a variable number of parameters) of type java.lang.Class. It is represented as a single-dimension array of type java.lang.Class. This can be distinguished from a parameter that is explicitly an array of java.lang.Class by invoking Method.isVarArgs(). The syntax for the returned values of Method.get*Types() is described in Class.getName().

The following example illustrates a method with a generic return type.

$ java MethodSpy java.lang.Class cast
public T java.lang.Class.cast(java.lang.Object)
              ReturnType: class java.lang.Object
       GenericReturnType: T
           ParameterType: class java.lang.Object
    GenericParameterType: class java.lang.Object

The generic return type for the method Class.cast() is reported as java.lang.Object because generics are implemented via type erasure which removes all information regarding generic types during compilation. The erasure of T is defined by the declaration of Class:

public final class Class<T> implements ...
Thus T is replaced by the upper bound of the type variable, in this case, java.lang.Object.

The last example illustrates the output for a method with multiple overloads.

$ java MethodSpy java.io.PrintStream format
public java.io.PrintStream java.io.PrintStream.format(java.util.Locale,java.lang.String,java.lang.Object[])
              ReturnType: class java.io.PrintStream
       GenericReturnType: class java.io.PrintStream
           ParameterType: class java.util.Locale
    GenericParameterType: class java.util.Locale
           ParameterType: class java.lang.String
    GenericParameterType: class java.lang.String
           ParameterType: class [Ljava.lang.Object;
    GenericParameterType: class [Ljava.lang.Object;
public java.io.PrintStream java.io.PrintStream.format(java.lang.String,java.lang.Object[])
              ReturnType: class java.io.PrintStream
       GenericReturnType: class java.io.PrintStream
           ParameterType: class java.lang.String
    GenericParameterType: class java.lang.String
           ParameterType: class [Ljava.lang.Object;
    GenericParameterType: class [Ljava.lang.Object;

If multiple overloads of the same method name are discovered, they are all returned by Class.getDeclaredMethods(). Since format() has two overloads (with with a Locale and one without), both are shown by MethodSpy.

Note: Method.getGenericExceptionTypes() exists because it is actually possible to declare a method with a generic exception type. However this is rarely used since it is not possible to catch a generic exception type.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Methods
Next page: Retrieving and Parsing Method Modifiers


Retrieving and Parsing Method Modifiers (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Section: Methods
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Retrieving and Parsing Method Modifiers

There a several modifiers that may be part of a method declaration:

  • Access modifiers: public, protected, and private
  • Modifier restricting to one instance: static
  • Modifier prohibiting value modification: final
  • Modifier requiring override: abstract
  • Modifier preventing reentrancy: synchronized
  • Modifier indicating implementation in another programming language: native
  • Modifier forcing strict floating point behavior: strictfp
  • Annotations

The MethodModifierSpy example lists the modifiers of a method with a given name. It also displays whether the method is synthetic (compiler-generated), of variable arity, or a bridge method (compiler-generated to support generic interfaces).

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import static java.lang.System.out;

public class MethodModifierSpy {

    private static int count;
    private static synchronized void inc() { count++; }
    private static synchronized int cnt() { return count; }

    public static void main(String... args) {
    try {
        Class<?> c = Class.forName(args[0]);
        Method[] allMethods = c.getDeclaredMethods();
        for (Method m : allMethods) {
        if (!m.getName().equals(args[1])) {
            continue;
        }
        out.format("%s%n", m.toGenericString());
        out.format("  Modifiers:  %s%n",
               Modifier.toString(m.getModifiers()));
        out.format("  [ synthetic=%-5b var_args=%-5b bridge=%-5b ]%n",
               m.isSynthetic(), m.isVarArgs(), m.isBridge());
        inc();
        }
        out.format("%d matching overload%s found%n", cnt(),
               (cnt() == 1 ? "" : "s"));

        // production code should handle this exception more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    }
    }
}

A few examples of the output MethodMdifierSpy produces follow.

$ java MethodModifierSpy java.lang.Object wait
public final native void java.lang.Object.wait(long) throws java.lang.InterruptedException
  Modifiers:  public final native
  [ synthetic=false var_args=false bridge=false ]
public final void java.lang.Object.wait(long,int) throws java.lang.InterruptedException
  Modifiers:  public final
  [ synthetic=false var_args=false bridge=false ]
public final void java.lang.Object.wait() throws java.lang.InterruptedException
  Modifiers:  public final
  [ synthetic=false var_args=false bridge=false ]
3 matching overloads found
$ java MethodModifierSpy java.lang.StrictMath toRadians
public static double java.lang.StrictMath.toRadians(double)
  Modifiers:  public static strictfp
  [ synthetic=false var_args=false bridge=false ]
1 matching overload found
$ java MethodModifierSpy MethodModifierSpy inc
private synchronized void MethodModifierSpy.inc()
  Modifiers:  private synchronized
  [ synthetic=false var_args=false bridge=false ]
1 matching overload found
$ java MethodModifierSpy java.lang.Class getConstructor
public java.lang.reflect.Constructor<T> java.lang.Class.getConstructor(java.lang.Class<T>[]) throws java.lang.NoSuchMethodException,java.lang.SecurityException
  Modifiers:  public transient
  [ synthetic=false var_args=true  bridge=false ]
1 matching overload found
$ java MethodModifierSpy java.lang.String compareTo
public int java.lang.String.compareTo(java.lang.String)
  Modifiers:  public
  [ synthetic=false var_args=false bridge=false ]
public int java.lang.String.compareTo(java.lang.Object)
  Modifiers:  public volatile
  [ synthetic=true  var_args=false bridge=true  ]
2 matching overloads found

Note that Method.isVarArgs() returns true for Class.getConstructor(). This indicates that the method declaration looks like this:

public Constructor<T> getConstructor(Class<?>... parameterTypes)
not like this:
public Constructor<T> getConstructor(Class<?> [] parameterTypes)

Notice that the output for String.compareTo() contains two methods. The method declared in String.java:

public int compareTo(String anotherString);
and a second synthetic or compiler-generated bridge method. This occurs because String implements the parameterized interface Comparable. During type erasure, the argument type of the inherited method Comparable.compareTo() is changed from java.lang.Object to java.lang.String. Since the parameter types for the compareTo methods in Comparable and String no longer match after erasure, overriding can not occur. In all other circumstances, this would produce a compile-time error because the interface is not implemented. The addition of the bridge method avoids this problem.

Method implements java.lang.reflect.AnnotatedElement. Thus any runtime annotations with java.lang.annotation.RetentionPolicy.RUNTIME may be retrieved. For an example of obtaining annotations see the section Examining Class Modifiers and Types.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Obtaining Method Type Information
Next page: Invoking Methods


Invoking Methods (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Section: Methods
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Invoking Methods
Reflection provides a means for invoking methods on a class. Typically, this would only be necessary if it is not possible to cast an instance of the class to the desired type in non-reflective code. Methods are invoked with java.lang.reflect.Method.invoke(). The first argument is the object instance on which this particular method is to be invoked. (If the method is static, the first argument should be null.) Subsequent arguments are the method's parameters. If the underlying method throws an exception, it will be wrapped by an java.lang.reflect.InvocationTargetException. The method's original exception may be retrieved using the exception chaining mechanism's InvocationTargetException.getCause() method.

Finding and Invoking a Method with a Specific Declaration

Consider a test suite which uses reflection to invoke private test methods in a given class. The Deet example searches for public methods in a class which begin with the string "test", have a boolean return type, and a single Locale parameter. It then invokes each matching method.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Locale;
import static java.lang.System.out;
import static java.lang.System.err;

public class Deet<T> {
    private boolean testDeet(Locale l) {
    // getISO3Language() may throw a MissingResourceException
    out.format("Locale = %s, ISO Language Code = %s%n", l.getDisplayName(), l.getISO3Language());
    return true;
    }

    private int testFoo(Locale l) { return 0; }
    private boolean testBar() { return true; }

    public static void main(String... args) {
    if (args.length != 4) {
        err.format("Usage: java Deet <classname> <langauge> <country> <variant>%n");
        return;
    }

    try {
        Class<?> c = Class.forName(args[0]);
        Object t = c.newInstance();

        Method[] allMethods = c.getDeclaredMethods();
        for (Method m : allMethods) {
        String mname = m.getName();
        if (!mname.startsWith("test")
            || (m.getGenericReturnType() != boolean.class)) {
            continue;
        }
         Type[] pType = m.getGenericParameterTypes();
         if ((pType.length != 1)
            || Locale.class.isAssignableFrom(pType[0].getClass())) {
             continue;
         }

        out.format("invoking %s()%n", mname);
        try {
            m.setAccessible(true);
            Object o = m.invoke(t, new Locale(args[1], args[2], args[3]));
            out.format("%s() returned %b%n", mname, (Boolean) o);

        // Handle any exceptions thrown by method to be invoked.
        } catch (InvocationTargetException x) {
            Throwable cause = x.getCause();
            err.format("invocation of %s failed: %s%n",
                   mname, cause.getMessage());
        }
        }

        // production code should handle these exceptions more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    } catch (InstantiationException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    }
    }
}

Deet invokes getDeclaredMethods() which will return all methods explicitly declared in the class. Also, Class.isAssignableFrom() is used to determine whether the parameters of the located method are compatible with the desired invocation. Technically the code could have tested whether the following statement is true since Locale is final:

Locale.class == pType[0].getClass()
However, Class.isAssignableFrom() is more general.
$ java Deet Deet ja JP JP
invoking testDeet()
Locale = Japanese (Japan,JP), ISO Language Code = jpn
testDeet() returned true
$ java Deet Deet xx XX XX
invoking testDeet()
invocation of testDeet failed: Couldn't find 3-letter language code for xx

First, note that only testDeet() meets the declaration restrictions enforced by the code. Next, when testDeet() is passed an invalid argument it throws an unchecked java.util.MissingResourceException. In reflection, there is no distinction in the handling of checked versus unchecked exceptions. They are all wrapped in an InvocationTargetException

Invoking Methods with a Variable Number of Arguments

Method.invoke() may be used to pass a variable number of arguments to a method. The key concept to understand is that methods of variable arity are implemented as if the variable arguments are packed in an array.

The InvokeMain example illustrates how to invoke the main() entry point in any class and pass a set of arguments determined at runtime.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;

public class InvokeMain {
    public static void main(String... args) {
    try {
        Class<?> c = Class.forName(args[0]);
        Class[] argTypes = new Class[] { String[].class };
        Method main = c.getDeclaredMethod("main", argTypes);
          String[] mainArgs = Arrays.copyOfRange(args, 1, args.length);
        System.out.format("invoking %s.main()%n", c.getName());
        main.invoke(null, (Object)mainArgs);

        // production code should handle these exceptions more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    } catch (NoSuchMethodException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    } catch (InvocationTargetException x) {
        x.printStackTrace();
    }
    }
}

First, to find the main() method the code searches for a class with the name "main" with a single parameter that is an array of String Since main() is static, null is the first argument to Method.invoke(). The second argument is the array of arguments to be passed.

$ java InvokeMain Deet Deet ja JP JP
invoking Deet.main()
invoking testDeet()
Locale = Japanese (Japan,JP), ISO Language Code = jpn
testDeet() returned true
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Retrieving and Parsing Method Modifiers
Next page: Troubleshooting


Troubleshooting (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Section: Methods
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Troubleshooting

This section contains examples of problems developers might encounter when using reflection to locate, invoke, or get information about methods.

NoSuchMethodException Due to Type Erasure

The MethodTrouble example illustrates what happens when type erasure is not taken into consideration by code which searches for a particular method in a class.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Method;

public class MethodTrouble<T>  {
    public void lookup(T t) {}
    public void find(Integer i) {}

    public static void main(String... args) {
    try {
        String mName = args[0];
        Class cArg = Class.forName(args[1]);
        Class<?> c = (new MethodTrouble<Integer>()).getClass();
        Method m = c.getMethod(mName, cArg);
        System.out.format("Found:%n  %s%n", m.toGenericString());

        // production code should handle these exceptions more gracefully
    } catch (NoSuchMethodException x) {
        x.printStackTrace();
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    }
    }
}

$ java MethodTrouble lookup java.lang.Integer
java.lang.NoSuchMethodException: MethodTrouble.lookup(java.lang.Integer)
        at java.lang.Class.getMethod(Class.java:1605)
        at MethodTrouble.main(MethodTrouble.java:12)
$ java MethodTrouble lookup java.lang.Object
Found:
  public void MethodTrouble.lookup(T)

When a method is declared with a generic parameter type, the compiler will replace the generic type with its upper bound, in this case, the upper bound of T is Object. Thus, when the code searches for lookup(Integer), no method is found, despite the fact that the instance of MethodTrouble was created as follows:

Class c = (new MethodTrouble()).getClass();

Searching for lookup(Object) succeeds as expected.

$ java MethodTrouble find java.lang.Integer
Found:
  public void MethodTrouble.find(java.lang.Integer)
$ java MethodTrouble find java.lang.Object
java.lang.NoSuchMethodException: MethodTrouble.find(java.lang.Object)
        at java.lang.Class.getMethod(Class.java:1605)
        at MethodTrouble.main(MethodTrouble.java:12)

In this case, find() has no generic parameters, so the parameter types searched for by getMethod() must match exactly.

Tip: Always pass the upper bound of the parameterized type when searching for a method.

IllegalAccessException when Invoking a Method

An IllegalAccessException is thrown if an attempt is made to invoke a private or otherwise inaccessible method.

The MethodTroubleAgain example shows a typical stack trace which results from trying to invoke a private method in an another class.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

class AnotherClass {
    private void m() {}
}

public class MethodTroubleAgain {
    public static void main(String... args) {
    AnotherClass ac = new AnotherClass();
    try {
        Class<?> c = ac.getClass();
         Method m = c.getDeclaredMethod("m");
//  	    m.setAccessible(true);      // solution
         Object o = m.invoke(ac);    // IllegalAccessException

        // production code should handle these exceptions more gracefully
    } catch (NoSuchMethodException x) {
        x.printStackTrace();
    } catch (InvocationTargetException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    }
    }
}

The stack trace for the exception thrown follows.

$ java MethodTroubleAgain
java.lang.IllegalAccessException: Class MethodTroubleAgain can not access a member of class AnotherClass with modifiers "private"
        at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
        at java.lang.reflect.Method.invoke(Method.java:588)
        at MethodTroubleAgain.main(MethodTroubleAgain.java:15)
Tip: An access restriction exists which prevents reflective invocation of methods which normally would not be accessible via direct invocation. (This includes---but is not limited to---private methods in a separate class and public methods in a separate private class.) However, Method is declared to extend AccessibleObject which provides the ability to suppress this check via AccessibleObject.setAccessible(). If it succeeds, then subsequent invocations of this method object will not fail due to this problem.

IllegalArgumentException from Method.invoke()

Method.invoke() has been retrofitted to be a variable-arity method. This is an enormous convenience, however it can lead to unexpected behavior. The MethodTroubleToo example shows various ways in which Method.invoke() can produce confusing results.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Method;

public class MethodTroubleToo {
    public void ping() { System.out.format("PONG!%n"); }

    public static void main(String... args) {
    try {
        MethodTroubleToo mtt = new MethodTroubleToo();
        Method m = MethodTroubleToo.class.getMethod("ping");

         switch(Integer.parseInt(args[0])) {
        case 0:
          m.invoke(mtt);                 // works
        break;
        case 1:
         m.invoke(mtt, null);           // works (expect compiler warning)
        break;
        case 2:
        Object arg2 = null;
        m.invoke(mtt, arg2);           // IllegalArgumentException
        break;
        case 3:
        m.invoke(mtt, new Object[0]);  // works
        break;
        case 4:
        Object arg4 = new Object[0];
        m.invoke(mtt, arg4);           // IllegalArgumentException
        break;
        default:
        System.out.format("Test not found%n");
        }

        // production code should handle these exceptions more gracefully
    } catch (Exception x) {
        x.printStackTrace();
    }
    }
}

$ java MethodTroubleToo 0
PONG!

Since all of the parameters of Method.invoke() are optional except for the first, they can be omitted when the method to be invoked has no parameters.

$ java MethodTroubleToo 1
PONG!

The code in this case generates this compiler warning because null is ambiguous.

$ javac MethodTroubleToo.java
MethodTroubleToo.java:16: warning: non-varargs call of varargs method with inexact argument type for last parameter;
cast to java.lang.Object for a varargs call
cast to java.lang.Object[] for a non-varargs call and to suppress this warning
                m.invoke(mtt, null);           // works (expect compiler warning)
                              ^
1 warning

It is not possible to determine whether null represents an empty array of arguments or a first argument of null.

$ java MethodTroubleToo 2
java.lang.IllegalArgumentException: wrong number of arguments
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at MethodTroubleToo.main(MethodTroubleToo.java:21)

This fails despite the fact that the argument is null, because the type is a Object and ping() expects no arguments at all.

$ java MethodTroubleToo 3
PONG!

This works because new Object[0] creates an empty array, and to a varargs method, this is equivalent to not passing any of the optional arguments.

$ java MethodTroubleToo 4
java.lang.IllegalArgumentException: wrong number of arguments
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
        at java.lang.reflect.Method.invoke(Method.java:597)
        at MethodTroubleToo.main(MethodTroubleToo.java:28)

Unlike the previous example, if the empty array is stored in an Object, then it is treated as an Object. This fails for the same reason that case 2 fails, ping() does not expect an argument.

Tip: When a method foo(Object... o) is declared the compiler will put all of the arguments passed to foo() in an array of type Object. The implementation of foo() is the same as if it were declared foo(Object[] o). Understanding this may help avoid the types of problems illustrated above.

InvocationTargetException when Invoked Method Fails

An InvocationTargetException wraps all exceptions (checked and unchecked) produced when a method object is invoked. The MethodTroubleReturns example shows how to retrieve the original exception thrown by the invoked method.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

public class MethodTroubleReturns {
    private void drinkMe(int liters) {
    if (liters < 0)
        throw new IllegalArgumentException("I can't drink a negative amount of liquid");
    }

    public static void main(String... args) {
    try {
        MethodTroubleReturns mtr  = new MethodTroubleReturns();
         Class<?> c = mtr.getClass();
           Method m = c.getDeclaredMethod("drinkMe", int.class);
        m.invoke(mtr, -1);

        // production code should handle these exceptions more gracefully
    } catch (InvocationTargetException x) {
        Throwable cause = x.getCause();
        System.err.format("drinkMe() failed: %s%n", cause.getMessage());
    } catch (Exception x) {
        x.printStackTrace();
    }
    }
}

$ java MethodTroubleReturns
drinkMe() failed: I can't drink a negative amount of liquid
Tip: If an InvocationTargetException is thrown, the method was invoked. Diagnosis of the problem would be the same as if the method was called directly and threw the exception that is retrieved by getCause(). This exception does not indicate a problem with the reflection package or its usage.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Invoking Methods
Next page: Constructors


Constructors (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Constructors
A constructor is used in the creation of an object that is an instance of a class. Typically it performs operations required to initialize the class before methods are invoked or fields are accessed. Constructors are never inherited.

Similar to methods, reflection provides APIs to discover and retrieve the constructors of a class and obtain declaration information such as the modifiers, parameters, annotations, and thrown exceptions. New instances of classes may also be created using a specified constructor. The key classes used when working with constructors are Class and java.lang.reflect.Constructor. Common operations involving constructors are covered in the following sections:

  • Finding Constructors illustrates how to retrieve constructors with specific parameters
  • Retrieving and Parsing Constructor Modifiers shows how to obtain the modifiers of a constructor declaration and other information about the constructor
  • Creating New Class Instances shows how to instantiate an instance of an object by invoking its constructor
  • Troubleshooting describes common errors which may be encountered while finding or invoking constructors
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Troubleshooting
Next page: Finding Constructors


Finding Constructors (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Section: Constructors
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Finding Constructors
A constructor declaration includes the name, modifiers, parameters, and list of throwable exceptions. The java.lang.reflect.Constructor class provides a way to obtain this information.

The ConstructorSift example illustrates how to search a class's declared constructors for one which has a parameter of a given type.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Constructor;
import java.lang.reflect.Type;
import static java.lang.System.out;

public class ConstructorSift {
    public static void main(String... args) {
    try {
        Class<?> cArg = Class.forName(args[1]);

        Class<?> c = Class.forName(args[0]);
        Constructor[] allConstructors = c.getDeclaredConstructors();
        for (Constructor ctor : allConstructors) {
        Class<?>[] pType  = ctor.getParameterTypes();
        for (int i = 0; i < pType.length; i++) {
            if (pType[i].equals(cArg)) {
            out.format("%s%n", ctor.toGenericString());

            Type[] gpType = ctor.getGenericParameterTypes();
            for (int j = 0; j < gpType.length; j++) {
                char ch = (pType[j].equals(cArg) ? '*' : ' ');
                out.format("%7c%s[%d]: %s%n", ch,
                       "GenericParameterType", j, gpType[j]);
            }
            break;
            }
        }
        }

        // production code should handle this exception more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    }
    }
}
Method.getGenericParameterTypes() will consult the Signature Attribute in the class file if it's present. If the attribute isn't available, it falls back on Method.getParameterType() which was not changed by the introduction of generics. The other methods with name getGenericFoo() for some value of Foo in reflection are implemented similarly. The syntax for the returned values of Method.get*Types() is described in Class.getName().

Here is the output for all constructors in java.util.Formatter which have a Locale argument.

$ java ConstructorSift java.util.Formatter java.util.Locale
public
java.util.Formatter(java.io.OutputStream,java.lang.String,java.util.Locale)
throws java.io.UnsupportedEncodingException
       GenericParameterType[0]: class java.io.OutputStream
       GenericParameterType[1]: class java.lang.String
      *GenericParameterType[2]: class java.util.Locale
public java.util.Formatter(java.lang.String,java.lang.String,java.util.Locale)
throws java.io.FileNotFoundException,java.io.UnsupportedEncodingException
       GenericParameterType[0]: class java.lang.String
       GenericParameterType[1]: class java.lang.String
      *GenericParameterType[2]: class java.util.Locale
public java.util.Formatter(java.lang.Appendable,java.util.Locale)
       GenericParameterType[0]: interface java.lang.Appendable
      *GenericParameterType[1]: class java.util.Locale
public java.util.Formatter(java.util.Locale)
      *GenericParameterType[0]: class java.util.Locale
public java.util.Formatter(java.io.File,java.lang.String,java.util.Locale)
throws java.io.FileNotFoundException,java.io.UnsupportedEncodingException
       GenericParameterType[0]: class java.io.File
       GenericParameterType[1]: class java.lang.String
      *GenericParameterType[2]: class java.util.Locale

The next example output illustrates how to search for a parameter of type char[] in String.

$ java ConstructorSift java.lang.String "[C"
java.lang.String(int,int,char[])
       GenericParameterType[0]: int
       GenericParameterType[1]: int
      *GenericParameterType[2]: class [C
public java.lang.String(char[],int,int)
      *GenericParameterType[0]: class [C
       GenericParameterType[1]: int
       GenericParameterType[2]: int
public java.lang.String(char[])
      *GenericParameterType[0]: class [C

The syntax for expressing arrays of reference and primitive types acceptable to Class.forName() is described in Class.getName(). Note that the first listed constructor is package-private, not public. It is returned because the example code uses Class.getDeclaredConstructors() rather than Class.getConstructors(), which returns only public constructors.

This example shows that searching for arguments of variable arity (which have a variable number of parameters) requires use of array syntax:

$ java ConstructorSift java.lang.ProcessBuilder "[Ljava.lang.String;"
public java.lang.ProcessBuilder(java.lang.String[])
      *GenericParameterType[0]: class [Ljava.lang.String;

This is the actual declaration of the ProcessBuilder constructor in source code:

public ProcessBuilder(String... command)
The parameter is represented as a single-dimension array of type java.lang.String. This can be distinguished from a parameter that is explicitly an array of java.lang.String by invoking Constructor.isVarArgs().

The final example reports the output for a constructor which has been declared with a generic parameter type:

$ java ConstructorSift java.util.HashMap java.util.Map
public java.util.HashMap(java.util.Map<? extends K, ? extends V>)
      *GenericParameterType[0]: java.util.Map<? extends K, ? extends V>

Exception types may be retrieved for constructors in a similar way as for methods. See the MethodSpy example described in Obtaining Method Type Information section for further details.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Constructors
Next page: Retrieving and Parsing Constructor Modifiers


Retrieving and Parsing Constructor Modifiers (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Section: Constructors
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Retrieving and Parsing Constructor Modifiers

Because of the role of constructors in the language, fewer modifiers are meaningful than for methods:

  • Access modifiers: public, protected, and private
  • Annotations

The ConstructorAccess example searches for constructors in a given class with the specified access modifier. It also displays whether the constructor is synthetic (compiler-generated) or of variable arity.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Constructor;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import static java.lang.System.out;

public class ConstructorAccess {
    public static void main(String... args) {
    try {
        Class<?> c = Class.forName(args[0]);
        Constructor[] allConstructors = c.getDeclaredConstructors();
        for (Constructor ctor : allConstructors) {
        int searchMod = modifierFromString(args[1]);
        int mods = accessModifiers(ctor.getModifiers());
        if (searchMod == mods) {
            out.format("%s%n", ctor.toGenericString());
            out.format("  [ synthetic=%-5b var_args=%-5b ]%n",
                   ctor.isSynthetic(), ctor.isVarArgs());
        }
        }

        // production code should handle this exception more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    }
    }

    private static int accessModifiers(int m) {
    return m & (Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED);
    }

    private static int modifierFromString(String s) {
    if ("public".equals(s))               return Modifier.PUBLIC;
    else if ("protected".equals(s))       return Modifier.PROTECTED;
    else if ("private".equals(s))         return Modifier.PRIVATE;
    else if ("package-private".equals(s)) return 0;
    else return -1;
    }
}

There is not an explicit Modifier constant which corresponds to "package-private" access, so it is necessary to check for the absence of all three access modifiers to identify a package-private constructor.

This output shows the private constructors in java.io.File:

$ java ConstructorAccess java.io.File private
private java.io.File(java.lang.String,int)
  [ synthetic=false var_args=false ]
private java.io.File(java.lang.String,java.io.File)
  [ synthetic=false var_args=false ]

Synthetic constructors are rare; however the SyntheticConstructor example illustrates a typical situation where this may occur:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class SyntheticConstructor {
    private SyntheticConstructor() {}
    class Inner {
    // Compiler will generate a synthetic constructor since
    // SyntheticConstructor() is private.
    Inner() { new SyntheticConstructor(); }
    }
}

$ java ConstructorAccess SyntheticConstructor package-private
SyntheticConstructor(SyntheticConstructor$1)
  [ synthetic=true  var_args=false ]

Since the inner class's constructor references the private constructor of the enclosing class, the compiler must generate a package-private constructor. The parameter type SyntheticConstructor$1 is arbitrary and dependent on the compiler implementation. Code which depends on the presence of any synthetic or non-public class members may not be portable.

Constructors implement java.lang.reflect.AnnotatedElement, which provides methods to retrieve runtime annotations with java.lang.annotation.RetentionPolicy.RUNTIME. For an example of obtaining annotations see the Examining Class Modifiers and Types section.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Finding Constructors
Next page: Creating New Class Instances


Creating New Class Instances (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Section: Constructors
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Creating New Class Instances
There are two reflective methods for creating instances of classes: java.lang.reflect.Constructor.newInstance() and Class.newInstance(). The former is preferred and is thus used in these examples because:
  • Class.newInstance() can only invoke the zero-argument constructor, while Constructor.newInstance() may invoke any constructor, regardless of the number of parameters.
  • Class.newInstance() throws any exception thrown by the constructor, regardless of whether it is checked or unchecked. InvocationTargetException .
  • Class.newInstance()
requires that the constructor be visible;
Constructor.newInstance()
may invoke private constructors under certain circumstances.

Sometimes it may be desirable to retrieve internal state from an object which is only set after construction. Consider a scenario where it is necessary to obtain the internal character set used by java.io.Console. (The Console character set is stored in an private field and is not necessarily the same as the Java virtual machine default character set returned by java.nio.charset.Charset.defaultCharset()). The ConsoleCharset example shows how this might be achieved:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.Console;
import java.nio.charset.Charset;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import static java.lang.System.out;

public class ConsoleCharset {
    public static void main(String... args) {
    Constructor[] ctors = Console.class.getDeclaredConstructors();
    Constructor ctor = null;
    for (int i = 0; i < ctors.length; i++) {
        ctor = ctors[i];
        if (ctor.getGenericParameterTypes().length == 0)
        break;
    }

    try {
        ctor.setAccessible(true);
         Console c = (Console)ctor.newInstance();
        Field f = c.getClass().getDeclaredField("cs");
        f.setAccessible(true);
        out.format("Console charset         :  %s%n", f.get(c));
        out.format("Charset.defaultCharset():  %s%n",
               Charset.defaultCharset());

        // production code should handle these exceptions more gracefully
    } catch (InstantiationException x) {
        x.printStackTrace();
     } catch (InvocationTargetException x) {
         x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    } catch (NoSuchFieldException x) {
        x.printStackTrace();
    }
    }
}
Note: Class.newInstance() will only succeed if the constructor is has zero arguments and is already accessible. Otherwise, it is necessary to use Constructor.newInstance() as in the above example.
Example output for a Unix system:
$ java ConsoleCharset
Console charset          :  ISO-8859-1
Charset.defaultCharset() :  ISO-8859-1
Example output for a Windows system:
C:\> java ConsoleCharset
Console charset          :  IBM437
Charset.defaultCharset() :  windows-1252

Another common application of Constructor.newInstance() is to invoke constructors which take arguments. The RestoreAliases example finds a specific single-argument constructor and invokes it:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import static java.lang.System.out;

class EmailAliases {
    private Set<String> aliases;
    private EmailAliases(HashMap<String, String> h) {
    aliases = h.keySet();
    }

    public void printKeys() {
    out.format("Mail keys:%n");
    for (String k : aliases)
        out.format("  %s%n", k);
    }
}

public class RestoreAliases {

    private static Map<String, String> defaultAliases = new HashMap<String, String>();
    static {
    defaultAliases.put("Duke", "duke@i-love-java");
    defaultAliases.put("Fang", "fang@evil-jealous-twin");
    }

    public static void main(String... args) {
    try {
        Constructor ctor = EmailAliases.class.getDeclaredConstructor(HashMap.class);
        ctor.setAccessible(true);
        EmailAliases email = (EmailAliases)ctor.newInstance(defaultAliases);
        email.printKeys();

        // production code should handle these exceptions more gracefully
    } catch (InstantiationException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    } catch (InvocationTargetException x) {
        x.printStackTrace();
    } catch (NoSuchMethodException x) {
        x.printStackTrace();
    }
    }
}
This example uses Class.getDeclaredConstructor() to find the constructor with a single argument of type java.util.HashMap. Note that it is sufficient to pass HashMap.class since the parameter to any get*Constructor() method requires a class only for type purposes. Due to type erasure, the following expression evaluates to true:
HashMap.class == defaultAliases.getClass()
The example then creates a new instance of the class using this constructor with Constructor.newInstance().
$ java RestoreAliases
Mail keys:
  Duke
  Fang
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Retrieving and Parsing Constructor Modifiers
Next page: Troubleshooting


Troubleshooting (The Java™ Tutorials > The Reflection API > Members)

Trail: The Reflection API
Lesson: Members
Section: Constructors
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Home Page > The Reflection API > Members
« Previous • Trail • Next »
Troubleshooting

The following problems are sometimes encountered by developers when trying to invoke constructors via reflection.

InstantiationException Due to Missing Zero-Argument Constructor

The ConstructorTrouble example illustrates what happens when code attempts to create a new instance of a class using Class.newInstance() and there is no accessible zero-argument constructor:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class ConstructorTrouble {
    private ConstructorTrouble(int i) {}

    public static void main(String... args){
    try {
        Class<?> c = Class.forName("ConstructorTrouble");
        Object o = c.newInstance();  // InstantiationException

        // production code should handle these exceptions more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    } catch (InstantiationException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    }
    }
}

$ java ConstructorTrouble
java.lang.InstantiationException: ConstructorTrouble
        at java.lang.Class.newInstance0(Class.java:340)
        at java.lang.Class.newInstance(Class.java:308)
        at ConstructorTrouble.main(ConstructorTrouble.java:7)
Tip: There a number of different reasons an InstantiationException can occur. In this case, the problem is that the presence of the constructor with an int argument prevents the compiler from generating the default (or zero-argument) constructor and there is no explicit zero-argument constructor in the code. Remember that Class.newInstance() behaves very much like the new keyword and will fail whenever new would fail.

Class.newInstance() Throws Unexpected Exception

The ConstructorTroubleToo example shows an unresolvable problem in Class.newInstance(). Namely, it propagates any exception — checked or unchecked — thrown by the constructor.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.InvocationTargetException;
import static java.lang.System.err;

public class ConstructorTroubleToo {
    public ConstructorTroubleToo() {
     throw new RuntimeException("exception in constructor");
    }

    public static void main(String... args) {
    try {
        Class<?> c = Class.forName("ConstructorTroubleToo");
        // Method propagetes any exception thrown by the constructor
        // (including checked exceptions).
        if (args.length > 0 && args[0].equals("class")) {
        Object o = c.newInstance();
        } else {
        Object o = c.getConstructor().newInstance();
        }

        // production code should handle these exceptions more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    } catch (InstantiationException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    } catch (NoSuchMethodException x) {
        x.printStackTrace();
    } catch (InvocationTargetException x) {
        x.printStackTrace();
        err.format("%n%nCaught exception: %s%n", x.getCause());
    }
    }
}

$ java ConstructorTroubleToo class
Exception in thread "main" java.lang.RuntimeException: exception in constructor
        at ConstructorTroubleToo.<init>(ConstructorTroubleToo.java:6)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at java.lang.Class.newInstance0(Class.java:355)
        at java.lang.Class.newInstance(Class.java:308)
        at ConstructorTroubleToo.main(ConstructorTroubleToo.java:15)

This situation is unique to reflection. Normally, it is impossible to write code which ignores a checked exception because it would not compile. It is possible to wrap any exception thrown by a constructor by using Constructor.newInstance() rather than Class.newInstance().

$ java ConstructorTroubleToo
java.lang.reflect.InvocationTargetException
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at ConstructorTroubleToo.main(ConstructorTroubleToo.java:17)
Caused by: java.lang.RuntimeException: exception in constructor
        at ConstructorTroubleToo.<init>(ConstructorTroubleToo.java:6)
        ... 5 more

Caught exception: java.lang.RuntimeException: exception in constructor

If an InvocationTargetException is thrown, the method was invoked. Diagnosis of the problem would be the same as if the constructor was called directly and threw the exception that is retrieved by InvocationTargetException.getCause(). This exception does not indicate a problem with the reflection package or its usage.

Tip: It is preferable to use Constructor.newInstance() over Class.newInstance() because the former API permits examination and handling of arbitrary exceptions thrown by constructors.

Problems Locating or Invoking the Correct Constructor

The ConstructorTroubleAgain class illustrates various ways in which incorrect code can fail to locate or invoke the expected constructor.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.InvocationTargetException;
import static java.lang.System.out;

public class ConstructorTroubleAgain {
    public ConstructorTroubleAgain() {}

    public ConstructorTroubleAgain(Integer i) {}

    public ConstructorTroubleAgain(Object o) {
    out.format("Constructor passed Object%n");
    }

    public ConstructorTroubleAgain(String s) {
    out.format("Constructor passed String%n");
    }

    public static void main(String... args){
    String argType = (args.length == 0 ? "" : args[0]);
    try {
        Class<?> c = Class.forName("ConstructorTroubleAgain");
        if ("".equals(argType)) {
        // IllegalArgumentException: wrong number of arguments
        Object o = c.getConstructor().newInstance("foo");
        } else if ("int".equals(argType)) {
        // NoSuchMethodException - looking for int, have Integer
        Object o = c.getConstructor(int.class);
        } else if ("Object".equals(argType)) {
        // newInstance() does not perform method resolution
        Object o = c.getConstructor(Object.class).newInstance("foo");
        } else {
        assert false;
        }

        // production code should handle these exceptions more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    } catch (NoSuchMethodException x) {
        x.printStackTrace();
    } catch (InvocationTargetException x) {
        x.printStackTrace();
    } catch (InstantiationException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    }
    }
}

$ java ConstructorTroubleAgain
Exception in thread "main" java.lang.IllegalArgumentException: wrong number of arguments
        at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
        at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
        at ConstructorTroubleAgain.main(ConstructorTroubleAgain.java:23)

An IllegalArgumentException is thrown because the zero-argument constructor was requested and an attempt was made to pass an argument. The same exception would be thrown if the constructor was passed an argument of the wrong type.

$ java ConstructorTroubleAgain int
java.lang.NoSuchMethodException: ConstructorTroubleAgain.<init>(int)
        at java.lang.Class.getConstructor0(Class.java:2706)
        at java.lang.Class.getConstructor(Class.java:1657)
        at ConstructorTroubleAgain.main(ConstructorTroubleAgain.java:26)

This exception may occur if the developer mistakenly believes that reflection will autobox or unbox types. Boxing (conversion of a primitive to a reference type) occurs only during compilation. There is no opportunity in reflection for this operation to occur, so the specific type must be used when locating a constructor.

$ java ConstructorTroubleAgain Object
Constructor passed Object

Here, it might be expected that the constructor taking a String argument would be invoked since newInstance() was invoked with the more specific String type. However it is too late! The constructor which was found is already the constructor with an Object argument. newInstance() makes no attempt to do method resolution; it simply operates on the existing constructor object.

Tip: An important difference between new and Constructor.newInstance() is that new performs method argument type checking, boxing, and method resolution. None of these occur in reflection, where explicit choices must be made.

IllegalAccessException When Attempting to Invoke an Inaccessible Constructor

An IllegalAccessException may be thrown if an attempt is made to invoke a private or otherwise inaccessible constructor. The ConstructorTroubleAccess example illustrates the resulting stack trace.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;

class Deny {
    private Deny() {
    System.out.format("Deny constructor%n");
    }
}

public class ConstructorTroubleAccess {
    public static void main(String... args) {
    try {
        Constructor c = Deny.class.getDeclaredConstructor();
//  	    c.setAccessible(true);   // solution
        c.newInstance();

        // production code should handle these exceptions more gracefully
    } catch (InvocationTargetException x) {
        x.printStackTrace();
    } catch (NoSuchMethodException x) {
        x.printStackTrace();
    } catch (InstantiationException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    }
    }
}

$ java ConstructorTroubleAccess
java.lang.IllegalAccessException: Class ConstructorTroubleAccess can not access a member of class Deny with modifiers "private"
        at sun.reflect.Reflection.ensureMemberAccess(Reflection.java:65)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:505)
        at ConstructorTroubleAccess.main(ConstructorTroubleAccess.java:15)
Tip: An access restriction exists which prevents reflective invocation of constructors which normally would not be accessible via direct invocation. (This includes---but is not limited to---private constructors in a separate class and public constructors in a separate private class.) However, Constructor is declared to extend AccessibleObject which provides the ability to suppress this check via AccessibleObject.setAccessible().
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating New Class Instances
Next page: Arrays and Enumerated Types


Lesson: Arrays and Enumerated Types (The Java™ Tutorials > The Reflection API)

Arrays and Enumerated Types
Arrays
Identifying Array Types
Creating New Arrays
Getting and Setting Arrays and Their Components
Troubleshooting
Enumerated Types
Examining Enums
Getting and Setting Fields with Enum Types
Troubleshooting
Trail: The Reflection API
Home Page > The Reflection API
« Previous • Trail • Next »
Lesson: Arrays and Enumerated Types
From the Java virtual machine's perspective, arrays and enumerated types (or enums) are just classes. Many of the methods in Class may be used on them. Reflection provides a few specific APIs for arrays and enums. This lesson uses a series of code samples to describe how to distinguish each of these objects from other classes and operate on them. Various errors are also be examined.

Arrays

Arrays have a component type and a length (which is not part of the type). Arrays may be maniuplated either in their entirety or component by component. Reflection provides the java.lang.reflect.Array class for the latter purpose.

  • Identifying Array Types describes how to determine if a class member is a field of array type
  • Creating New Arrays illustrates how to create new instances of arrays with simple and complex component types
  • Getting and Setting Arrays and Their Components shows how to access fields of type array and individually access array elements
  • Troubleshooting covers common errors and programming misconceptions

Enumerated Types

Enums are treated very much like ordinary classes in reflection code. Class.isEnum() tells whether a Class represents and enum. Class.getEnumConstants() retrieves the enum constants defined in an enum. java.lang.reflect.Field.isEnumConstant() indicates whether a field is an enumerated type.

  • Examining Enums illustrates how to retrieve an enum's constants and any other fields, constructors, and methods
  • Getting and Setting Fields with Enum Types shows how to set and get fields with an enum constant value
  • Troubleshooting describes common errors associated with enums
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Arrays


Arrays (The Java™ Tutorials > The Reflection API > Arrays and Enumerated Types)

Trail: The Reflection API
Lesson: Arrays and Enumerated Types
Arrays and Enumerated Types
Arrays
Identifying Array Types
Creating New Arrays
Getting and Setting Arrays and Their Components
Troubleshooting
Enumerated Types
Examining Enums
Getting and Setting Fields with Enum Types
Troubleshooting
Home Page > The Reflection API > Arrays and Enumerated Types
« Previous • Trail • Next »
Arrays
An array is an object of reference type which contains a fixed number of components of the same type; the length of an array is immutable. Creating an instance of an array requires knowledge of the length and component type. Each component may be a primitive type (e.g. byte, int, or double), a reference type (e.g. String, Object, or java.nio.CharBuffer), or an array. Multi-dimensional arrays are really just arrays which contain components of array type.

Arrays are implemented in the Java virtual machine. The only methods on arrays are those inherited from Object. The length of an array is not part of its type; arrays have a length field which is accessible via java.lang.reflect.Array.getLength().

Reflection provides methods for accessing array types and array component types, creating new arrays, and retrieving and setting array component values. The following sections include examples of common operations on arrays:

  • Identifying Array Types describes how to determine if a class member is a field of array type
  • Creating New Arrays illustrates how to create new instances of arrays with simple and complex component types
  • Getting and Setting Arrays and Their Components shows how to access fields of type array and individually access array elements
  • Troubleshooting covers common errors and programming misconceptions

All of these operations are supported via static methods in java.lang.reflect.Array.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Arrays and Enumerated Types
Next page: Identifying Array Types


Identifying Array Types (The Java™ Tutorials > The Reflection API > Arrays and Enumerated Types)

Trail: The Reflection API
Lesson: Arrays and Enumerated Types
Section: Arrays
Arrays and Enumerated Types
Arrays
Identifying Array Types
Creating New Arrays
Getting and Setting Arrays and Their Components
Troubleshooting
Enumerated Types
Examining Enums
Getting and Setting Fields with Enum Types
Troubleshooting
Home Page > The Reflection API > Arrays and Enumerated Types
« Previous • Trail • Next »
Identifying Array Types

Array types may be identified by invoking Class.isArray(). To obtain a Class use one of the methods described in Retrieving Class Objects section of this trail.

The ArrayFind example identifies the fields in the named class that are of array type and reports the component type for each of them.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import static java.lang.System.out;

public class ArrayFind {
    public static void main(String... args) {
    boolean found = false;
     try {
        Class<?> cls = Class.forName(args[0]);
        Field[] flds = cls.getDeclaredFields();
        for (Field f : flds) {
         Class<?> c = f.getType();
        if (c.isArray()) {
            found = true;
            out.format("%s%n"
                               + "           Field: %s%n"
                   + "            Type: %s%n"
                   + "  Component Type: %s%n",
                   f, f.getName(), c, c.getComponentType());
        }
        }
        if (!found) {
        out.format("No array fields%n");
        }

        // production code should handle this exception more gracefully
     } catch (ClassNotFoundException x) {
        x.printStackTrace();
    }
    }
}

The syntax for the returned value of Class.get*Type() is described in Class.getName(). The number of '[' characters at the beginning of the type name indicates the number of dimensions (i.e. depth of nesting) of the array.

Samples of the output follows. User input is in italics. An array of primitive type byte:

$ java ArrayFind java.nio.ByteBuffer
final byte[] java.nio.ByteBuffer.hb
           Field: hb
            Type: class [B
  Component Type: byte

An array of reference type StackTraceElement:

$ java ArrayFind java.lang.Throwable
private java.lang.StackTraceElement[] java.lang.Throwable.stackTrace
           Field: stackTrace
            Type: class [Ljava.lang.StackTraceElement;
  Component Type: class java.lang.StackTraceElement

predefined is a one-dimensional array of reference type java.awt.Cursor and cursorProperties is a two-dimensional array of reference type String:

$ java ArrayFind java.awt.Cursor
protected static java.awt.Cursor[] java.awt.Cursor.predefined
           Field: predefined
            Type: class [Ljava.awt.Cursor;
  Component Type: class java.awt.Cursor
static final java.lang.String[][] java.awt.Cursor.cursorProperties
           Field: cursorProperties
            Type: class [[Ljava.lang.String;
  Component Type: class [Ljava.lang.String;
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Arrays
Next page: Creating New Arrays


Creating New Arrays (The Java™ Tutorials > The Reflection API > Arrays and Enumerated Types)

Trail: The Reflection API
Lesson: Arrays and Enumerated Types
Section: Arrays
Arrays and Enumerated Types
Arrays
Identifying Array Types
Creating New Arrays
Getting and Setting Arrays and Their Components
Troubleshooting
Enumerated Types
Examining Enums
Getting and Setting Fields with Enum Types
Troubleshooting
Home Page > The Reflection API > Arrays and Enumerated Types
« Previous • Trail • Next »
Creating New Arrays

Just as in non-reflective code, reflection supports the ability to dynamically create arrays of arbitrary type and dimensions via java.lang.reflect.Array.newInstance(). Consider ArrayCreator, a basic interpreter capable of dynamically creating arrays. The syntax that will be parsed is as follows:

fully_qualified_class_name variable_name[] = { val1, val2, val3, ... }
Assume that the fully_qualified_class_name represents a class that has a constructor with a single String argument. The dimensions of the array are determined by the number of values provided. The following example will construct an instance of an array of fully_qualified_class_name and populate its values with instances given by val1, val2, etc. (This example assumes familiarity with Class.getConstructor() and java.lang.reflect.Constructor.newInstance(). For a discussion of the reflection APIs for Constructor see the Creating New Class Instances section of this trail.)
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.Arrays;
import static java.lang.System.out;

public class ArrayCreator {
    private static String s = "java.math.BigInteger bi[] = { 123, 234, 345 }";
    private static Pattern p = Pattern.compile("^\\s*(\\S+)\\s*\\w+\\[\\].*\\{\\s*([^}]+)\\s*\\}");

    public static void main(String... args) {
        Matcher m = p.matcher(s);

        if (m.find()) {
            String cName = m.group(1);
            String[] cVals = m.group(2).split("[\\s,]+");
            int n = cVals.length;

            try {
                Class<?> c = Class.forName(cName);
                Object o = Array.newInstance(c, n);
                for (int i = 0; i < n; i++) {
                    String v = cVals[i];
                    Constructor ctor = c.getConstructor(String.class);
                    Object val = ctor.newInstance(v);
                    Array.set(o, i, val);
                }

                Object[] oo = (Object[])o;
                out.format("%s[] = %s%n", cName, Arrays.toString(oo));

            // production code should handle these exceptions more gracefully
            } catch (ClassNotFoundException x) {
                x.printStackTrace();
            } catch (NoSuchMethodException x) {
                x.printStackTrace();
            } catch (IllegalAccessException x) {
                x.printStackTrace();
            } catch (InstantiationException x) {
                x.printStackTrace();
            } catch (InvocationTargetException x) {
                x.printStackTrace();
            }
        }
    }
}

$ java ArrayCreator
java.math.BigInteger [] = [123, 234, 345]

The above example shows one case where it may be desirable to create an array via reflection; namely if the component type is not known until runtime. In this case, the code uses Class.forName() to get a class for the desired component type and then calls a specific constructor to initialize each component of the array before setting the corresponding array value.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Identifying Array Types
Next page: Getting and Setting Arrays and Their Components


Getting and Setting Arrays and Their Components (The Java™ Tutorials > The Reflection API > Arrays and Enumerated Types)

Trail: The Reflection API
Lesson: Arrays and Enumerated Types
Section: Arrays
Arrays and Enumerated Types
Arrays
Identifying Array Types
Creating New Arrays
Getting and Setting Arrays and Their Components
Troubleshooting
Enumerated Types
Examining Enums
Getting and Setting Fields with Enum Types
Troubleshooting
Home Page > The Reflection API > Arrays and Enumerated Types
« Previous • Trail • Next »
Getting and Setting Arrays and Their Components
Just as in non-reflective code, an array field may be set or retrieved in its entirety or component by component. To set the entire array at once, use java.lang.reflect.Field.set(Object obj, Object value). To retrieve the entire array, use Field.get(Object). Individual components can be set or retrieved using methods in java.lang.reflect.Array.

Array provides methods of the form setFoo() and getFoo() for setting and getting components of any primitive type. For example, the component of an int array may be set with Array.setInt(Object array, int index, int value) and may be retrieved with Array.getInt(Object array, int index).

These methods support automatic widening of data types. Therefore, Array.getShort() may be used to set the values of an int array since a 16-bit short may be widened to a 32-bit int without loss of data; on the other hand, invoking Array.setLong() on an array of int will cause an IllegalArgumentException to be thrown because a 64-bit long can not be narrowed to for storage in a 32-bit int with out loss of information. This is true regardless of whether the actual values being passed could be accurately represented in the target data type. The Java Language Specification, Third Edition, sections 5.1.2 and 5.1.3 contains a complete discussion of widening and narrowing conversions.

The components of arrays of reference types (including arrays of arrays) are set and retrieved using Array.set(Object array, int index, int value)and Array.get(Object array, int index).

Setting a Field of Type Array

The GrowBufferedReader example illustrates how to replace the value of a field of type array. In this case, the code replaces the backing array for a java.io.BufferedReader with a larger one. (This assumes that the creation of the original BufferedReader is in code that is not modifiable; otherwise, it would be trivial to simply use the alternate constructor BufferedReader(java.io.Reader in, int size) which accepts an input buffer size.)

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.BufferedReader;
import java.io.CharArrayReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.Arrays;
import static java.lang.System.out;

public class GrowBufferedReader {
    private static final int srcBufSize = 10 * 1024;
    private static char[] src = new char[srcBufSize];
    static {
    src[srcBufSize - 1] = 'x';
    }
    private static CharArrayReader car = new CharArrayReader(src);

    public static void main(String... args) {
    try {
        BufferedReader br = new BufferedReader(car);

        Class<?> c = br.getClass();
        Field f = c.getDeclaredField("cb");

        // cb is a private field
        f.setAccessible(true);
        char[] cbVal = char[].class.cast(f.get(br));

        char[] newVal = Arrays.copyOf(cbVal, cbVal.length * 2);
        if (args.length > 0 && args[0].equals("grow"))
        f.set(br, newVal);

        for (int i = 0; i < srcBufSize; i++)
        br.read();

        // see if the new backing array is being used
        if (newVal[srcBufSize - 1] == src[srcBufSize - 1])
        out.format("Using new backing array, size=%d%n", newVal.length);
        else
        out.format("Using original backing array, size=%d%n", cbVal.length);

        // production code should handle these exceptions more gracefully
    } catch (FileNotFoundException x) {
        x.printStackTrace();
    } catch (NoSuchFieldException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    } catch (IOException x) {
        x.printStackTrace();
    }
    }
}

$ java GrowBufferedReader grow
Using new backing array, size=16384
$ java GrowBufferedReader
Using original backing array, size=8192

Note that the above example makes use of the array utility method java.util.Arrays.copyOf). java.util.Arrays contains many methods which are convenient when operating on arrays.

Accessing Elements of a Multidimensional Array

Multi-dimensional arrays are simply nested arrays. A two-dimensional array is an array of arrays. A three-dimensional array is an array of two-dimensional arrays, and so on. The CreateMatrix example illustrates how to create and initialize a multi-dimensional array using reflection.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Array;
import static java.lang.System.out;

public class CreateMatrix {
    public static void main(String... args) {
        Object matrix = Array.newInstance(int.class, 2, 2);
        Object row0 = Array.get(matrix, 0);
        Object row1 = Array.get(matrix, 1);

        Array.setInt(row0, 0, 1);
        Array.setInt(row0, 1, 2);
        Array.setInt(row1, 0, 3);
        Array.setInt(row1, 1, 4);

        for (int i = 0; i < 2; i++)
            for (int j = 0; j < 2; j++)
                out.format("matrix[%d][%d] = %d%n", i, j, ((int[][])matrix)[i][j]);
    }
}

$ java CreateMatrix
matrix[0][0] = 1
matrix[0][1] = 2
matrix[1][0] = 3
matrix[1][1] = 4

The same result could be obtained by using the following code fragment:

Object matrix = Array.newInstance(int.class, 2);
Object row0 = Array.newInstance(int.class, 2);
Object row1 = Array.newInstance(int.class, 2);

Array.setInt(row0, 0, 1);
Array.setInt(row0, 1, 2);
Array.setInt(row1, 0, 3);
Array.setInt(row1, 1, 4);

Array.set(matrix, 0, row0);
Array.set(matrix, 1, row1);

The variable argument Array.newInstance(Class<?> componentType, int... dimensions) provides a convenient way to create multi-dimensional arrays, but the components still need to initialized using the principle that that multi-dimensional arrays are nested arrays. (Reflection does not provide multiple indexed get/set methods for this purpose.)

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating New Arrays
Next page: Troubleshooting


Troubleshooting (The Java™ Tutorials > The Reflection API > Arrays and Enumerated Types)

Trail: The Reflection API
Lesson: Arrays and Enumerated Types
Section: Arrays
Arrays and Enumerated Types
Arrays
Identifying Array Types
Creating New Arrays
Getting and Setting Arrays and Their Components
Troubleshooting
Enumerated Types
Examining Enums
Getting and Setting Fields with Enum Types
Troubleshooting
Home Page > The Reflection API > Arrays and Enumerated Types
« Previous • Trail • Next »
Troubleshooting
The following examples show typical errors which may occur when operating on arrays.

IllegalArgumentException due to Inconvertible Types

The ArrayTroubleAgain example will generate an IllegalArgumentException. Array.setInt() is invoked to set a component that is of the reference type Integer with a value of primitive type int. In the non-reflection equivalent ary[0] = 1, the compiler would convert (or box) the value 1 to a reference type as new Integer(1) so that its type checking will accept the statement. When using reflection, type checking only occurs at runtime so there is no opportunity to box the value.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Array;
import static java.lang.System.err;

public class ArrayTroubleAgain {
    public static void main(String... args) {
    Integer[] ary = new Integer[2];
    try {
        Array.setInt(ary, 0, 1);  // IllegalArgumentException

        // production code should handle these exceptions more gracefully
    } catch (IllegalArgumentException x) {
        err.format("Unable to box%n");
    } catch (ArrayIndexOutOfBoundsException x) {
        x.printStackTrace();
    }
    }
}

$ java ArrayTroubleAgain
Unable to box

To eliminate this exception, the problematic line should be replaced by the following invocation of Array.set(Object array, int index, Object value):

Array.set(ary, 0, new Integer(1));
Tip: When using reflection to set or get an array component, the compiler does not have an opportunity to perform boxing. It can only convert types that are related as described by the specification for Class.isAssignableFrom(). The example is expected to fail because isAssignableFrom() will return false in this test which can be used programmatically to verify whether a particular conversion is possible:
Integer.class.isAssignableFrom(int.class) == false
Similarly, automatic conversion from primitive to reference type is also impossible in reflection.
int.class.isAssignableFrom(Integer.class) == false

ArrayIndexOutOfBoundsException for Empty Arrays

The ArrayTrouble example illustrates an error which will occur if an attempt is made to access the elements of an array of zero length:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Array;
import static java.lang.System.out;

public class ArrayTrouble {
    public static void main(String... args) {
        Object o = Array.newInstance(int.class, 0);
        int[] i = (int[])o;
        int[] j = new int[0];
        out.format("i.length = %d, j.length = %d, args.length = %d%n",
                   i.length, j.length, args.length);
        Array.getInt(o, 0);  // ArrayIndexOutOfBoundsException
    }
}

$ java ArrayTrouble
i.length = 0, j.length = 0, args.length = 0
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException
        at java.lang.reflect.Array.getInt(Native Method)
        at ArrayTrouble.main(ArrayTrouble.java:11)
Tip: It is possible to have arrays with no elements (empty arrays). There are only a few cases in common code where they are seen but they can occur in reflection inadvertently. Of course, it is not possible to set/get the values of an empty array because an ArrayIndexOutOfBoundsException will be thrown.

IllegalArgumentException if Narrowing is Attempted

The ArrayTroubleToo example contains code which fails because it attempts perform an operation which could potentially lose data:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Array;
import static java.lang.System.out;

public class ArrayTroubleToo {
    public static void main(String... args) {
        Object o = new int[2];
        Array.setShort(o, 0, (short)2);  // widening, succeeds
        Array.setLong(o, 1, 2L);         // narrowing, fails
    }
}

$ java ArrayTroubleToo
Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch
        at java.lang.reflect.Array.setLong(Native Method)
        at ArrayTroubleToo.main(ArrayTroubleToo.java:9)
Tip: The Array.set*() and Array.get*() methods will perform automatic widening conversion but will throw an IllegalArgumentException if a narrowing conversion is attempted. For complete discussion of widening and narrowing conversions, see The Java Language Specification, Third Edition, sections 5.1.2 and 5.1.3 respectively.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Getting and Setting Arrays and Their Components
Next page: Enumerated Types


Enumerated Types (The Java™ Tutorials > The Reflection API > Arrays and Enumerated Types)

Trail: The Reflection API
Lesson: Arrays and Enumerated Types
Arrays and Enumerated Types
Arrays
Identifying Array Types
Creating New Arrays
Getting and Setting Arrays and Their Components
Troubleshooting
Enumerated Types
Examining Enums
Getting and Setting Fields with Enum Types
Troubleshooting
Home Page > The Reflection API > Arrays and Enumerated Types
« Previous • Trail • Next »
Enumerated Types
An enum is a language construct that is used to define type-safe enumerations which can be used when a fixed set of named values is desired. All enums implicitly extend java.lang.Enum. Enums may contain one or more enum constants, which define unique instances of the enum type. An enum declaration defines an enum type which is very similar to a class in that it may have members such as fields, methods, and constructors (with some restrictions).

Since enums are classes, reflection has no need to define an explicit java.lang.reflect.Enum class. The only Reflection APIs that are specific to enums are Class.isEnum(), Class.getEnumConstants(), and java.lang.reflect.Field.isEnumConstant(). Most reflective operations involving enums are the same as any other class or member. For example, enum constants are implemented as public static final fields on the enum. The following sections show how to use Class and java.lang.reflect.Field with enums.

  • Examining Enums illustrates how to retrieve an enum's constants and any other fields, constructors, and methods
  • Getting and Setting Fields with Enum Types shows how to set and get fields with an enum constant value
  • Troubleshooting describes common errors associated with enums

For an introduction to enums, see the Enum Types section of the Java Tutorial Trail Learning the Java Language.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Troubleshooting
Next page: Examining Enums


Examining Enums (The Java™ Tutorials > The Reflection API > Arrays and Enumerated Types)

Trail: The Reflection API
Lesson: Arrays and Enumerated Types
Section: Enumerated Types
Arrays and Enumerated Types
Arrays
Identifying Array Types
Creating New Arrays
Getting and Setting Arrays and Their Components
Troubleshooting
Enumerated Types
Examining Enums
Getting and Setting Fields with Enum Types
Troubleshooting
Home Page > The Reflection API > Arrays and Enumerated Types
« Previous • Trail • Next »
Examining Enums
Reflection provides three enum-specific APIs:
Class.isEnum()
Indicates whether this class represents an enum type
Class.getEnumConstants()
Retrieves the list of enum constants defined by the enum in the order they're declared
java.lang.reflect.Field.isEnumConstant()
Indicates whether this field represents an element of an enumerated type

Sometimes it is necessary to dynamically retrieve the list of enum constants; in non-reflective code this is accomplished by invoking the implicitly declared static method values() on the enum. If an instance of an enum type is not available the only way to get a list of the possible values is to invoke Class.getEnumConstants() since it is impossible to instantiate an enum type.

Given a fully qualified name, the EnumConstants example shows how to retrieve an ordered list of constants in an enum using Class.getEnumConstants().

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.Arrays;
import static java.lang.System.out;

enum Eon { HADEAN, ARCHAEAN, PROTEROZOIC, PHANEROZOIC }

public class EnumConstants {
    public static void main(String... args) {
    try {
        Class<?> c = (args.length == 0 ? Eon.class : Class.forName(args[0]));
        out.format("Enum name:  %s%nEnum constants:  %s%n",
               c.getName(), Arrays.asList(c.getEnumConstants()));
        if (c == Eon.class)
        out.format("  Eon.values():  %s%n",
               Arrays.asList(Eon.values()));

        // production code should handle this exception more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    }
    }
}
Samples of the output follows. User input is in italics.
$ java EnumConstants java.lang.annotation.RetentionPolicy
Enum name:  java.lang.annotation.RetentionPolicy
Enum constants:  [SOURCE, CLASS, RUNTIME]
$ java EnumConstants java.util.concurrent.TimeUnit
Enum name:  java.util.concurrent.TimeUnit
Enum constants:  [NANOSECONDS, MICROSECONDS, MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS]
This example also shows that value returned by Class.getEnumConstants() is identical to the value returned by invoking values() on an enum type.
$ java EnumConstants
Enum name:  Eon
Enum constants:  [HADEAN, ARCHAEAN, PROTEROZOIC, PHANEROZOIC]
  Eon.values():  [HADEAN, ARCHAEAN, PROTEROZOIC, PHANEROZOIC]

Since enums are classes, other information may be obtained using the same Reflection APIs described in the Fields, Methods, and Constructors sections of this trail. The EnumSpy code illustrates how to use these APIs to get additional information about the enum's declaration. The example uses Class.isEnum() to restrict the set of classes examined. It also uses Field.isEnumConstant() to distinguish enum constants from other fields in the enum declaration (not all fields are enum constants).

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Member;
import java.util.List;
import java.util.ArrayList;
import static java.lang.System.out;

public class EnumSpy {
    private static final String fmt = "  %11s:  %s %s%n";

    public static void main(String... args) {
    try {
        Class<?> c = Class.forName(args[0]);
        if (!c.isEnum()) {
        out.format("%s is not an enum type%n", c);
        return;
        }
        out.format("Class:  %s%n", c);

        Field[] flds = c.getDeclaredFields();
        List<Field> cst = new ArrayList<Field>();  // enum constants
        List<Field> mbr = new ArrayList<Field>();  // member fields
        for (Field f : flds) {
        if (f.isEnumConstant())
            cst.add(f);
        else
            mbr.add(f);
        }
        if (!cst.isEmpty())
        print(cst, "Constant");
        if (!mbr.isEmpty())
        print(mbr, "Field");

        Constructor[] ctors = c.getDeclaredConstructors();
        for (Constructor ctor : ctors) {
        out.format(fmt, "Constructor", ctor.toGenericString(),
               synthetic(ctor));
        }

        Method[] mths = c.getDeclaredMethods();
        for (Method m : mths) {
        out.format(fmt, "Method", m.toGenericString(),
               synthetic(m));
        }

        // production code should handle this exception more gracefully
    } catch (ClassNotFoundException x) {
        x.printStackTrace();
    }
    }

    private static void print(List<Field> lst, String s) {
    for (Field f : lst) {
         out.format(fmt, s, f.toGenericString(), synthetic(f));
    }
    }

    private static String synthetic(Member m) {
    return (m.isSynthetic() ? "[ synthetic ]" : "");
    }
}

$ java EnumSpy java.lang.annotation.RetentionPolicy
Class:  class java.lang.annotation.RetentionPolicy
     Constant:  public static final java.lang.annotation.RetentionPolicy java.lang.annotation.RetentionPolicy.SOURCE
     Constant:  public static final java.lang.annotation.RetentionPolicy java.lang.annotation.RetentionPolicy.CLASS
     Constant:  public static final java.lang.annotation.RetentionPolicy java.lang.annotation.RetentionPolicy.RUNTIME
        Field:  private static final java.lang.annotation.RetentionPolicy[] java.lang.annotation.RetentionPolicy. [ synthetic ]
  Constructor:  private java.lang.annotation.RetentionPolicy()
       Method:  public static java.lang.annotation.RetentionPolicy java.lang.annotation.RetentionPolicy.valueOf(java.lang.String)
       Method:  public static java.lang.annotation.RetentionPolicy[] java.lang.annotation.RetentionPolicy.values()

The output shows that declaration of java.lang.annotation.RetentionPolicy only contains the three enum constants. The enum constants are exposed as public static final fields. The field, constructor, and methods are compiler generated. The $VALUES field is related to the implementation of the values() method.

Note: For various reasons, including support for evolution of the enum type, the declaration order of enum constants is important. Class.getFields() and Class.getDeclaredFields() do not make any guarantee that the order of the returned values matches the order in the declaring source code. If ordering is required by an application, use Class.getEnumConstants().
The output for java.util.concurrent.TimeUnit shows that much more complicated enums are possible. This class includes several methods as well as additional fields declared static final which are not enum constants.
$ java EnumSpy java.util.concurrent.TimeUnit
Class:  class java.util.concurrent.TimeUnit
     Constant:  public static final java.util.concurrent.TimeUnit java.util.concurrent.TimeUnit.NANOSECONDS
     Constant:  public static final java.util.concurrent.TimeUnit java.util.concurrent.TimeUnit.MICROSECONDS
     Constant:  public static final java.util.concurrent.TimeUnit java.util.concurrent.TimeUnit.MILLISECONDS
     Constant:  public static final java.util.concurrent.TimeUnit java.util.concurrent.TimeUnit.SECONDS
     Constant:  public static final java.util.concurrent.TimeUnit java.util.concurrent.TimeUnit.MINUTES
     Constant:  public static final java.util.concurrent.TimeUnit java.util.concurrent.TimeUnit.HOURS
     Constant:  public static final java.util.concurrent.TimeUnit java.util.concurrent.TimeUnit.DAYS
        Field:  static final long java.util.concurrent.TimeUnit.C0
        Field:  static final long java.util.concurrent.TimeUnit.C1
        Field:  static final long java.util.concurrent.TimeUnit.C2
        Field:  static final long java.util.concurrent.TimeUnit.C3
        Field:  static final long java.util.concurrent.TimeUnit.C4
        Field:  static final long java.util.concurrent.TimeUnit.C5
        Field:  static final long java.util.concurrent.TimeUnit.C6
        Field:  static final long java.util.concurrent.TimeUnit.MAX
        Field:  private static final java.util.concurrent.TimeUnit[] java.util.concurrent.TimeUnit. [ synthetic ]
  Constructor:  private java.util.concurrent.TimeUnit()
  Constructor:  java.util.concurrent.TimeUnit(java.lang.String,int,java.util.concurrent.TimeUnit) [ synthetic ]
       Method:  public static java.util.concurrent.TimeUnit java.util.concurrent.TimeUnit.valueOf(java.lang.String)
       Method:  public static java.util.concurrent.TimeUnit[] java.util.concurrent.TimeUnit.values()
       Method:  public void java.util.concurrent.TimeUnit.sleep(long) throws java.lang.InterruptedException
       Method:  public long java.util.concurrent.TimeUnit.toNanos(long)
       Method:  public long java.util.concurrent.TimeUnit.convert(long,java.util.concurrent.TimeUnit)
       Method:  abstract int java.util.concurrent.TimeUnit.excessNanos(long,long)
       Method:  public void java.util.concurrent.TimeUnit.timedJoin(java.lang.Thread,long) throws java.lang.InterruptedException
       Method:  public void java.util.concurrent.TimeUnit.timedWait(java.lang.Object,long) throws java.lang.InterruptedException
       Method:  public long java.util.concurrent.TimeUnit.toDays(long)
       Method:  public long java.util.concurrent.TimeUnit.toHours(long)
       Method:  public long java.util.concurrent.TimeUnit.toMicros(long)
       Method:  public long java.util.concurrent.TimeUnit.toMillis(long)
       Method:  public long java.util.concurrent.TimeUnit.toMinutes(long)
       Method:  public long java.util.concurrent.TimeUnit.toSeconds(long)
       Method:  static long java.util.concurrent.TimeUnit.x(long,long,long)
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Enumerated Types
Next page: Getting and Setting Fields with Enum Types


Getting and Setting Fields with Enum Types (The Java™ Tutorials > The Reflection API > Arrays and Enumerated Types)

Trail: The Reflection API
Lesson: Arrays and Enumerated Types
Section: Enumerated Types
Arrays and Enumerated Types
Arrays
Identifying Array Types
Creating New Arrays
Getting and Setting Arrays and Their Components
Troubleshooting
Enumerated Types
Examining Enums
Getting and Setting Fields with Enum Types
Troubleshooting
Home Page > The Reflection API > Arrays and Enumerated Types
« Previous • Trail • Next »
Getting and Setting Fields with Enum Types
Fields which store enums are set and retrieved as any other reference type, using Field.set() and Field.get(). For more information on accessing fields, see the Fields section of this trail.

Consider application which needs to dynamically modify the trace level in a server application which normally does not allow this change during runtime. Assume the instance of the server object is available. The SetTrace example shows how code can translate the String representation of an enum into an enum type and retrieve and set the value of a field storing an enum.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Field;
import static java.lang.System.out;

enum TraceLevel { OFF, LOW, MEDIUM, HIGH, DEBUG }

class MyServer {
    private TraceLevel level = TraceLevel.OFF;
}

public class SetTrace {
    public static void main(String... args) {
    TraceLevel newLevel = TraceLevel.valueOf(args[0]);

    try {
        MyServer svr = new MyServer();
        Class<?> c = svr.getClass();
        Field f = c.getDeclaredField("level");
        f.setAccessible(true);
        TraceLevel oldLevel = (TraceLevel)f.get(svr);
        out.format("Original trace level:  %s%n", oldLevel);

        if (oldLevel != newLevel) {
         f.set(svr, newLevel);
        out.format("    New  trace level:  %s%n", f.get(svr));
        }

        // production code should handle these exceptions more gracefully
    } catch (IllegalArgumentException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    } catch (NoSuchFieldException x) {
        x.printStackTrace();
    }
    }
}

Since the enum constants are singletons, the == and != operators may be used to compare enum constants of the same type.

$ java SetTrace OFF
Original trace level:  OFF
$ java SetTrace DEBUG
Original trace level:  OFF
    New  trace level:  DEBUG
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Examining Enums
Next page: Troubleshooting


Troubleshooting (The Java™ Tutorials > The Reflection API > Arrays and Enumerated Types)

Trail: The Reflection API
Lesson: Arrays and Enumerated Types
Section: Enumerated Types
Arrays and Enumerated Types
Arrays
Identifying Array Types
Creating New Arrays
Getting and Setting Arrays and Their Components
Troubleshooting
Enumerated Types
Examining Enums
Getting and Setting Fields with Enum Types
Troubleshooting
Home Page > The Reflection API > Arrays and Enumerated Types
« Previous • Trail • Next »
Troubleshooting
The following examples show problems which may be encountered when using enumerated types.

IllegalArgumentException When Attempting to Instantiate an Enum Type

As has been mentioned, instantiation of enum types is forbidden. The EnumTrouble example attempts this.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import static java.lang.System.out;

enum Charge {
    POSITIVE, NEGATIVE, NEUTRAL;
    Charge() {
    out.format("under construction%n");
    }
}

public class EnumTrouble {

    public static void main(String... args) {
    try {
        Class<?> c = Charge.class;

         Constructor[] ctors = c.getDeclaredConstructors();
         for (Constructor ctor : ctors) {
        out.format("Constructor: %s%n",  ctor.toGenericString());
         ctor.setAccessible(true);
         ctor.newInstance();
         }

        // production code should handle these exceptions more gracefully
    } catch (InstantiationException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    } catch (InvocationTargetException x) {
        x.printStackTrace();
    }
    }
}

$ java EnumTrouble
Constructor: private Charge()
Exception in thread "main" java.lang.IllegalArgumentException: Cannot reflectively create enum objects
        at java.lang.reflect.Constructor.newInstance(Constructor.java:511)
        at EnumTrouble.main(EnumTrouble.java:22)
Tip: It is a compile-time error to attempt to explicitly instantiate an enum because that would prevent the defined enum constants from being unique. This restriction is also enforced in reflective code. Code which attempts to instantiate classes using their default constructors should invoke Class.isEnum() first to determine if the class is an enum.

IllegalArgumentException when Setting a Field with an Incompatible Enum Type

Fields storing enums set with the appropriate enum type. (Actually, fields of any type must be set with compatible types.) The EnumTroubleToo example produces the expected error.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.lang.reflect.Field;

enum E0 { A, B }
enum E1 { A, B }

class ETest {
    private E0 fld = E0.A;
}

public class EnumTroubleToo {
    public static void main(String... args) {
    try {
        ETest test = new ETest();
        Field f = test.getClass().getDeclaredField("fld");
        f.setAccessible(true);
         f.set(test, E1.A);  // IllegalArgumentException

        // production code should handle these exceptions more gracefully
    } catch (NoSuchFieldException x) {
        x.printStackTrace();
    } catch (IllegalAccessException x) {
        x.printStackTrace();
    }
    }
}

$ java EnumTroubleToo
Exception in thread "main" java.lang.IllegalArgumentException: Can not set E0 field ETest.fld to E1
        at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:146)
        at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(UnsafeFieldAccessorImpl.java:150)
        at sun.reflect.UnsafeObjectFieldAccessorImpl.set(UnsafeObjectFieldAccessorImpl.java:63)
        at java.lang.reflect.Field.set(Field.java:657)
        at EnumTroubleToo.main(EnumTroubleToo.java:16)
Tip: Strictly speaking, any attempt to set a field of type X to a value of type Y can only succeed if the following statement holds:
X.class.isAssignableFrom(Y.class) == true
The code could be modified to perform the following test to verify whether the types are compatible:
if (f.getType().isAssignableFrom(E0.class))
    // compatible
else
    // expect IllegalArgumentException
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Getting and Setting Fields with Enum Types
Next page: End of Trail


Trail: Custom Networking (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Custom Networking
The Java platform is highly regarded in part because of its suitability for writing programs that use and interact with the resources on the Internet and the World Wide Web. In fact, Java-compatible browsers use this ability of the Java platform to the extreme to transport and run applets over the Internet.

This trail walks you through the complexities of writing Java applications and applets that can be used on the Internet.

Overview of Networking has two sections. The first describes the networking capabilities of the Java platform that you may already be using without realizing that you are using the network. The second provides a brief overview of networking to familiarize you with terms and concepts that you should understand before reading how to use URLs, sockets, and datagrams.

Working With URLs discusses how your Java programs can use URLs to access information on the Internet. A URL (Uniform Resource Locator) is the address of a resource on the Internet. Your Java programs can use URLs to connect to and retrieve information over a network. This lesson provides a more complete definition of a URL and shows you how to create and parse a URL, how to open a connection to a URL, and how to read from and write to that connection.

All About Sockets explains how to use sockets so that your programs can communicate with other programs on the network. A socket is one endpoint of a two-way communication link between two programs running on the network. This lesson shows you how a client can connect to a standard server, the Echo server, and communicate with it via a socket. It then walks you through the details of a complete client/server example, which shows you how to implement both the client side and the server side of a client/server pair.

All About Datagrams takes you step by step through a simple client/server example that uses datagrams to communicate. It then challenges you to rewrite the example using multicast socket instead.

Programmatic Access to Network Parameters explains why you might want to access network interface parameters and how to do so. It gives examples of how to list all the IP addresses assigned to the machine as well as other useful information such as whether the interface is running.

Working With Cookies discusses how cookies are used to create a session between a client and server, and how you can take advantage of cookies in your HTTP URL connections.

Security considerations: Note that communications over the network are subject to approval by the current security manager. The Security Manager describes what a security manager is and how it impacts your applications. For general information about the security features provided by the JDK, refer to Security Features in Java SE.

The example programs in the following lessons that cover URLs, sockets, and datagrams are standalone applications, which, by default, have no security manager. If you convert these applications to applets, they may be unable to communicate over the network, depending on the browser or viewer in which they are running. See Security Restrictions for information about the security restrictions placed on applets.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Overview of Networking


Lesson: Overview of Networking (The Java™ Tutorials > Custom Networking)

Overview of Networking
What You May Already Know About Networking in Java
Networking Basics
Trail: Custom Networking
Home Page > Custom Networking
« Previous • Trail • Next »
Lesson: Overview of Networking
Before plowing through the examples in the next several lessons, you should have an understanding of some networking basics. Also, to boost your confidence, we've included a section that reviews what you may already know about networking in Java without even realizing it.

What You May Already Know About Networking in Java

If you've been working on the other trails in this tutorial, you've probably loaded an applet over the Internet by now, and you've likely loaded images from the network into applets running over the network. All of this is using the network and you already know how to do it. This page highlights the networking features that are covered in other trails and lessons of this tutorial--features that you might already be familiar with--and provides links to the pages that discuss those features.

Networking Basics

You'll learn what you need to know about TCP, UDP, sockets, datagrams, and ports to get the most out of the remaining lessons in this trail. If you are already familiar with these concepts, feel free to skip this section.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: What You May Already Know About Networking in Java


What You May Already Know About Networking in Java (The Java™ Tutorials > Custom Networking > Overview of Networking)

Trail: Custom Networking
Lesson: Overview of Networking
Overview of Networking
What You May Already Know About Networking in Java
Networking Basics
Home Page > Custom Networking > Overview of Networking
« Previous • Trail • Next »
What You May Already Know About Networking in Java
The word networking strikes fear in the hearts of many programmers. Fear not! Using the networking capabilities provided in the Java environment is quite easy. In fact, you may be using the network already without even realizing it!

Loading Applets from the Network

If you have access to a Java-enabled browser, you have undoubtedly already executed many applets. The applets you've run are referenced by a special tag in an HTML file — the <APPLET> tag. Applets can be located anywhere, whether on your local machine or somewhere out on the Internet. The location of the applet is completely invisible to you, the user. However, the location of the applet is encoded within the <APPLET> tag. The browser decodes this information, locates the applet, and runs it. If the applet is on some machine other than your own, the browser must download the applet before it can be run.

This is the highest level of access that you have to the Internet from the Java development environment. Someone else has taken the time to write a browser that does all of the grunt work of connecting to the network and getting data from it, thereby enabling you to run applets from anywhere in the world.

For more information:
The "Hello World!" Application shows you how to write your first applet and run it.

The Applets trail describes how to write Java applets from A to Z.

Loading Images from URLs

If you've ventured into writing your own Java applets and applications, you may have run into a class in the java.net package called URL. This class represents a Uniform Resource Locator and is the address of some resource on the network. Your applets and applications can use a URL to reference and even connect to resources out on the network. For example, to load an image from the network, your Java program must first create a URL that contains the address to the image.

This is the next highest level of interaction you can have with the Internet — your Java program gets an address of something it wants, creates a URL for it, and then uses some existing function in the Java development environment that does the grunt work of connecting to the network and retrieving the resource.

For more information:
How to Use Icons shows you how to load an image into your Java program (whether applets or applications) when you have its URL. Before you can load the image you must create a URL object with the address of the resource in it.

Working with URLs, the next lesson in this trail, provides a complete discussion about URLs, including how your programs can connect to them and read from and write to that connection.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Overview of Networking
Next page: Networking Basics


Networking Basics (The Java™ Tutorials > Custom Networking > Overview of Networking)

Trail: Custom Networking
Lesson: Overview of Networking
Overview of Networking
What You May Already Know About Networking in Java
Networking Basics
Home Page > Custom Networking > Overview of Networking
« Previous • Trail • Next »
Networking Basics
Computers running on the Internet communicate to each other using either the Transmission Control Protocol (TCP) or the User Datagram Protocol (UDP), as this diagram illustrates:

When you write Java programs that communicate over the network, you are programming at the application layer. Typically, you don't need to concern yourself with the TCP and UDP layers. Instead, you can use the classes in the java.net package. These classes provide system-independent network communication. However, to decide which Java classes your programs should use, you do need to understand how TCP and UDP differ.

TCP

When two applications want to communicate to each other reliably, they establish a connection and send data back and forth over that connection. This is analogous to making a telephone call. If you want to speak to Aunt Beatrice in Kentucky, a connection is established when you dial her phone number and she answers. You send data back and forth over the connection by speaking to one another over the phone lines. Like the phone company, TCP guarantees that data sent from one end of the connection actually gets to the other end and in the same order it was sent. Otherwise, an error is reported.

TCP provides a point-to-point channel for applications that require reliable communications. The Hypertext Transfer Protocol (HTTP), File Transfer Protocol (FTP), and Telnet are all examples of applications that require a reliable communication channel. The order in which the data is sent and received over the network is critical to the success of these applications. When HTTP is used to read from a URL, the data must be received in the order in which it was sent. Otherwise, you end up with a jumbled HTML file, a corrupt zip file, or some other invalid information.

Definition: TCP (Transmission Control Protocol) is a connection-based protocol that provides a reliable flow of data between two computers.

UDP

The UDP protocol provides for communication that is not guaranteed between two applications on the network. UDP is not connection-based like TCP. Rather, it sends independent packets of data, called datagrams, from one application to another. Sending datagrams is much like sending a letter through the postal service: The order of delivery is not important and is not guaranteed, and each message is independent of any other.

Definition: UDP (User Datagram Protocol) is a protocol that sends independent packets of data, called datagrams, from one computer to another with no guarantees about arrival. UDP is not connection-based like TCP.

For many applications, the guarantee of reliability is critical to the success of the transfer of information from one end of the connection to the other. However, other forms of communication don't require such strict standards. In fact, they may be slowed down by the extra overhead or the reliable connection may invalidate the service altogether.

Consider, for example, a clock server that sends the current time to its client when requested to do so. If the client misses a packet, it doesn't really make sense to resend it because the time will be incorrect when the client receives it on the second try. If the client makes two requests and receives packets from the server out of order, it doesn't really matter because the client can figure out that the packets are out of order and make another request. The reliability of TCP is unnecessary in this instance because it causes performance degradation and may hinder the usefulness of the service.

Another example of a service that doesn't need the guarantee of a reliable channel is the ping command. The purpose of the ping command is to test the communication between two programs over the network. In fact, ping needs to know about dropped or out-of-order packets to determine how good or bad the connection is. A reliable channel would invalidate this service altogether.

The UDP protocol provides for communication that is not guaranteed between two applications on the network. UDP is not connection-based like TCP. Rather, it sends independent packets of data from one application to another. Sending datagrams is much like sending a letter through the mail service: The order of delivery is not important and is not guaranteed, and each message is independent of any others.

Note: Many firewalls and routers have been configured not to allow UDP packets. If you're having trouble connecting to a service outside your firewall, or if clients are having trouble connecting to your service, ask your system administrator if UDP is permitted.

Understanding Ports

Generally speaking, a computer has a single physical connection to the network. All data destined for a particular computer arrives through that connection. However, the data may be intended for different applications running on the computer. So how does the computer know to which application to forward the data? Through the use of ports.

Data transmitted over the Internet is accompanied by addressing information that identifies the computer and the port for which it is destined. The computer is identified by its 32-bit IP address, which IP uses to deliver data to the right computer on the network. Ports are identified by a 16-bit number, which TCP and UDP use to deliver the data to the right application.

In connection-based communication such as TCP, a server application binds a socket to a specific port number. This has the effect of registering the server with the system to receive all data destined for that port. A client can then rendezvous with the server at the server's port, as illustrated here:

Definition: The TCP and UDP protocols use ports to map incoming data to a particular process running on a computer.

In datagram-based communication such as UDP, the datagram packet contains the port number of its destination and UDP routes the packet to the appropriate application, as illustrated in this figure:

Port numbers range from 0 to 65,535 because ports are represented by 16-bit numbers. The port numbers ranging from 0 - 1023 are restricted; they are reserved for use by well-known services such as HTTP and FTP and other system services. These ports are called well-known ports. Your applications should not attempt to bind to them.

Networking Classes in the JDK

Through the classes in java.net, Java programs can use TCP or UDP to communicate over the Internet. The URL, URLConnection, Socket, and ServerSocket classes all use TCP to communicate over the network. The DatagramPacket, DatagramSocket, and MulticastSocket classes are for use with UDP.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: What You May Already Know About Networking in Java
Next page: Working with URLs


Lesson: Working with URLs (The Java™ Tutorials > Custom Networking)

Working with URLs
What Is a URL?
Creating a URL
Parsing a URL
Reading Directly from a URL
Connecting to a URL
Reading from and Writing to a URLConnection
Trail: Custom Networking
Home Page > Custom Networking
« Previous • Trail • Next »
Lesson: Working with URLs
URL is the acronym for Uniform Resource Locator. It is a reference (an address) to a resource on the Internet. You provide URLs to your favorite Web browser so that it can locate files on the Internet in the same way that you provide addresses on letters so that the post office can locate your correspondents.

Java programs that interact with the Internet also may use URLs to find the resources on the Internet they wish to access. Java programs can use a class called URL in the java.net package to represent a URL address.

Terminology Note: The term URL can be ambiguous. It can refer to an Internet address or a URL object in a Java program. Where the meaning of URL needs to be specific, this text uses "URL address" to mean an Internet address and "URL object" to refer to an instance of the URL class in a program.

What Is a URL?

A URL takes the form of a string that describes how to find a resource on the Internet. URLs have two main components: the protocol needed to access the resource and the location of the resource.

Creating a URL

Within your Java programs, you can create a URL object that represents a URL address. The URL object always refers to an absolute URL but can be constructed from an absolute URL, a relative URL, or from URL components.

Parsing a URL

Gone are the days of parsing a URL to find out the host name, filename, and other information. With a valid URL object you can call any of its accessor methods to get all of that information from the URL without doing any string parsing!

Reading Directly from a URL

This section shows how your Java programs can read from a URL using the openStream() method.

Connecting to a URL

If you want to do more than just read from a URL, you can connect to it by calling openConnection() on the URL. The openConnection() method returns a URLConnection object that you can use for more general communications with the URL, such as reading from it, writing to it, or querying it for content and other information.

Reading from and Writing to a URLConnection

Some URLs, such as many that are connected to cgi-bin scripts, allow you to (or even require you to) write information to the URL. For example, a search script may require detailed query data to be written to the URL before the search can be performed. This section shows you how to write to a URL and how to get results back.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: What Is a URL?


What Is a URL? (The Java™ Tutorials > Custom Networking > Working with URLs)

Trail: Custom Networking
Lesson: Working with URLs
Working with URLs
What Is a URL?
Creating a URL
Parsing a URL
Reading Directly from a URL
Connecting to a URL
Reading from and Writing to a URLConnection
Home Page > Custom Networking > Working with URLs
« Previous • Trail • Next »
What Is a URL?
If you've been surfing the Web, you have undoubtedly heard the term URL and have used URLs to access HTML pages from the Web.

It's often easiest, although not entirely accurate, to think of a URL as the name of a file on the World Wide Web because most URLs refer to a file on some machine on the network. However, remember that URLs also can point to other resources on the network, such as database queries and command output.

Definition: URL is an acronym for Uniform Resource Locator and is a reference (an address) to a resource on the Internet.

The following is an example of a URL which addresses the Java Web site hosted by Sun Microsystems:

As in the previous diagram, a URL has two main components:
  • Protocol identifier
  • Resource name
Note that the protocol identifier and the resource name are separated by a colon and two forward slashes. The protocol identifier indicates the name of the protocol to be used to fetch the resource. The example uses the Hypertext Transfer Protocol (HTTP), which is typically used to serve up hypertext documents. HTTP is just one of many different protocols used to access different types of resources on the net. Other protocols include File Transfer Protocol (FTP), Gopher, File, and News.

The resource name is the complete address to the resource. The format of the resource name depends entirely on the protocol used, but for many protocols, including HTTP, the resource name contains one or more of the components listed in the following table:

Host Name | The name of the machine on which the resource lives.
Filename | The pathname to the file on the machine.
Port Number | The port number to which to connect (typically optional).
Reference | A reference to a named anchor within a resource that usually identifies a specific location within a file (typically optional).

For many protocols, the host name and the filename are required, while the port number and reference are optional. For example, the resource name for an HTTP URL must specify a server on the network (Host Name) and the path to the document on that machine (Filename); it also can specify a port number and a reference. In the URL for the Java Web site java.sun.com is the host name and an empty path or the trailing slash is shorthand for the file named /index.html.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Working with URLs
Next page: Creating a URL


Creating a URL (The Java™ Tutorials > Custom Networking > Working with URLs)

Trail: Custom Networking
Lesson: Working with URLs
Working with URLs
What Is a URL?
Creating a URL
Parsing a URL
Reading Directly from a URL
Connecting to a URL
Reading from and Writing to a URLConnection
Home Page > Custom Networking > Working with URLs
« Previous • Trail • Next »
Creating a URL
The easiest way to create a URL object is from a String that represents the human-readable form of the URL address. This is typically the form that another person will use for a URL. For example, the URL for the Gamelan site, which is a directory of Java resources, takes the following form:
http://www.gamelan.com/
In your Java program, you can use a String containing this text to create a URL object:
URL gamelan = new URL("http://www.gamelan.com/");
The URL object created above represents an absolute URL. An absolute URL contains all of the information necessary to reach the resource in question. You can also create URL objects from a relative URL address.

Creating a URL Relative to Another

A relative URL contains only enough information to reach the resource relative to (or in the context of) another URL.

Relative URL specifications are often used within HTML files. For example, suppose you write an HTML file called JoesHomePage.html. Within this page, are links to other pages, PicturesOfMe.html and MyKids.html, that are on the same machine and in the same directory as JoesHomePage.html. The links to PicturesOfMe.html and MyKids.html from JoesHomePage.html could be specified just as filenames, like this:

<a href="PicturesOfMe.html">Pictures of Me</a>
<a href="MyKids.html">Pictures of My Kids</a>
These URL addresses are relative URLs. That is, the URLs are specified relative to the file in which they are contained--JoesHomePage.html.

In your Java programs, you can create a URL object from a relative URL specification. For example, suppose you know two URLs at the Gamelan site:

http://www.gamelan.com/pages/Gamelan.game.html
http://www.gamelan.com/pages/Gamelan.net.html
You can create URL objects for these pages relative to their common base URL: http://www.gamelan.com/pages/ like this:
URL gamelan = new URL("http://www.gamelan.com/pages/");
URL gamelanGames = new URL(gamelan, "Gamelan.game.html");
URL gamelanNetwork = new URL(gamelan, "Gamelan.net.html");
This code snippet uses the URL constructor that lets you create a URL object from another URL object (the base) and a relative URL specification. The general form of this constructor is:
URL(URL baseURL, String relativeURL)
The first argument is a URL object that specifies the base of the new URL. The second argument is a String that specifies the rest of the resource name relative to the base. If baseURL is null, then this constructor treats relativeURL like an absolute URL specification. Conversely, if relativeURL is an absolute URL specification, then the constructor ignores baseURL.

This constructor is also useful for creating URL objects for named anchors (also called references) within a file. For example, suppose the Gamelan.network.html file has a named anchor called BOTTOM at the bottom of the file. You can use the relative URL constructor to create a URL object for it like this:

URL gamelanNetworkBottom = new URL(gamelanNetwork, "#BOTTOM");

Other URL Constructors

The URL class provides two additional constructors for creating a URL object. These constructors are useful when you are working with URLs, such as HTTP URLs, that have host name, filename, port number, and reference components in the resource name portion of the URL. These two constructors are useful when you do not have a String containing the complete URL specification, but you do know various components of the URL.

For example, suppose you design a network browsing panel similar to a file browsing panel that allows users to choose the protocol, host name, port number, and filename. You can construct a URL from the panel's components. The first constructor creates a URL object from a protocol, host name, and filename. The following code snippet creates a URL to the Gamelan.net.html file at the Gamelan site:

new URL("http", "www.gamelan.com", "/pages/Gamelan.net.html");
This is equivalent to
new URL("http://www.gamelan.com/pages/Gamelan.net.html");
The first argument is the protocol, the second is the host name, and the last is the pathname of the file. Note that the filename contains a forward slash at the beginning. This indicates that the filename is specified from the root of the host.

The final URL constructor adds the port number to the list of arguments used in the previous constructor:

URL gamelan = new URL("http", "www.gamelan.com", 80,
                       "pages/Gamelan.network.html");
This creates a URL object for the following URL:
http://www.gamelan.com:80/pages/Gamelan.network.html
If you construct a URL object using one of these constructors, you can get a String containing the complete URL address by using the URL object's toString method or the equivalent toExternalForm method.

URL addresses with Special characters

Some URL addresses contain special characters, for example the space character. Like this:
http://foo.com/hello world/
To make theses characters legal they need to encoded before passing them to the URL constructor.
URL url = new URL("http://foo.com/hello%20world");
Encoding the special character(s) in this example is easy as there is only one character that needs encoding, but for URL addresses that have several of these characters or if you are unsure when writing your code what URL addresses you will need to access, you can use the multi-argument constructors of the java.net.URI class to automatically take care of the encoding for you.
URI uri = new URI("http", "foo.com", "/hello world/", "");
And then convert the URI to a URL.
URL url = uri.toURL();

MalformedURLException

Each of the four URL constructors throws a MalformedURLException if the arguments to the constructor refer to a null or unknown protocol. Typically, you want to catch and handle this exception by embedding your URL constructor statements in a try/catch pair, like this:
try {
    URL myURL = new URL(. . .)
} catch (MalformedURLException e) {
    . . .
    // exception handler code here
    . . .
}
See Exceptions for information about handling exceptions.

Note: URLs are "write-once" objects. Once you've created a URL object, you cannot change any of its attributes (protocol, host name, filename, or port number).
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: What Is a URL?
Next page: Parsing a URL


Parsing a URL (The Java™ Tutorials > Custom Networking > Working with URLs)

Trail: Custom Networking
Lesson: Working with URLs
Working with URLs
What Is a URL?
Creating a URL
Parsing a URL
Reading Directly from a URL
Connecting to a URL
Reading from and Writing to a URLConnection
Home Page > Custom Networking > Working with URLs
« Previous • Trail • Next »
Parsing a URL
The URL class provides several methods that let you query URL objects. You can get the protocol, authority, host name, port number, path, query, filename, and reference from a URL using these accessor methods:
getProtocol
Returns the protocol identifier component of the URL.
getAuthority
Returns the authority component of the URL.
getHost
Returns the host name component of the URL.
getPort
Returns the port number component of the URL. The getPort method returns an integer that is the port number. If the port is not set, getPort returns -1.
getPath
Returns the path component of this URL.
getQuery
Returns the query component of this URL.
getFile
Returns the filename component of the URL. The getFile method returns the same as getPath, plus the concatenation of the value of getQuery, if any.
getRef
Returns the reference component of the URL.

Note:  Remember that not all URL addresses contain these components. The URL class provides these methods because HTTP URLs do contain these components and are perhaps the most commonly used URLs. The URL class is somewhat HTTP-centric.

You can use these getXXX methods to get information about the URL regardless of the constructor that you used to create the URL object.

The URL class, along with these accessor methods, frees you from ever having to parse URLs again! Given any string specification of a URL, just create a new URL object and call any of the accessor methods for the information you need. This small example program creates a URL from a string specification and then uses the URL object's accessor methods to parse the URL:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.net.*;
import java.io.*;

public class ParseURL {
    public static void main(String[] args) throws Exception {
        URL aURL = new URL("http://java.sun.com:80/docs/books/tutorial"
                           + "/index.html?name=networking#DOWNLOADING");
        System.out.println("protocol = " + aURL.getProtocol());
    System.out.println("authority = " + aURL.getAuthority());
        System.out.println("host = " + aURL.getHost());
        System.out.println("port = " + aURL.getPort());
        System.out.println("path = " + aURL.getPath());
        System.out.println("query = " + aURL.getQuery());
        System.out.println("filename = " + aURL.getFile());
        System.out.println("ref = " + aURL.getRef());
    }
}
Here's the output displayed by the program:
protocol = http
authority = java.sun.com:80
host = java.sun.com
port = 80
path = /docs/books/tutorial/index.html
query = name=networking
filename = /docs/books/tutorial/index.html?name=networking
ref = DOWNLOADING
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creating a URL
Next page: Reading Directly from a URL


Reading Directly from a URL (The Java™ Tutorials > Custom Networking > Working with URLs)

Trail: Custom Networking
Lesson: Working with URLs
Working with URLs
What Is a URL?
Creating a URL
Parsing a URL
Reading Directly from a URL
Connecting to a URL
Reading from and Writing to a URLConnection
Home Page > Custom Networking > Working with URLs
« Previous • Trail • Next »
Reading Directly from a URL
After you've successfully created a URL, you can call the URL's openStream() method to get a stream from which you can read the contents of the URL. The openStream() method returns a java.io.InputStreamobject, so reading from a URL is as easy as reading from an input stream.

The following small Java program uses openStream() to get an input stream on the URL http://www.yahoo.com/. It then opens a BufferedReader on the input stream and reads from the BufferedReader thereby reading from the URL. Everything read is copied to the standard output stream:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.net.*;
import java.io.*;

public class URLReader {
    public static void main(String[] args) throws Exception {
    URL yahoo = new URL("http://www.yahoo.com/");
    BufferedReader in = new BufferedReader(
                new InputStreamReader(
                yahoo.openStream()));

    String inputLine;

    while ((inputLine = in.readLine()) != null)
        System.out.println(inputLine);

    in.close();
    }
}
When you run the program, you should see, scrolling by in your command window, the HTML commands and textual content from the HTML file located at http://www.yahoo.com/. Alternatively, the program might hang or you might see an exception stack trace. If either of the latter two events occurs, you may have to set the proxy host so that the program can find the Yahoo server.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Parsing a URL
Next page: Connecting to a URL


Connecting to a URL (The Java™ Tutorials > Custom Networking > Working with URLs)

Trail: Custom Networking
Lesson: Working with URLs
Working with URLs
What Is a URL?
Creating a URL
Parsing a URL
Reading Directly from a URL
Connecting to a URL
Reading from and Writing to a URLConnection
Home Page > Custom Networking > Working with URLs
« Previous • Trail • Next »
Connecting to a URL
After you've successfully created a URL object, you can call the URL object's openConnection method to get a URLConnection object, or one of its protocol specific subclasses, e.g. java.net.HttpURLConnection

You can use this URLConnection object to setup parameters and general request properties that you may need before connecting. Connection to the remote object represented by the URL is only initiated when the URLConnection.connect method is called. When you do this you are initializing a communication link between your Java program and the URL over the network. For example, you can open a connection to the Yahoo site with the following code:

try {
    URL yahoo = new URL("http://www.yahoo.com/");
    URLConnection yahooConnection = yahoo.openConnection();
    yahooConnection.connect();

} catch (MalformedURLException e) {     // new URL() failed
    . . .
} catch (IOException e) {               // openConnection() failed
    . . .
}
A new URLConnection object is created every time by calling the openConnection method of the protocol handler for this URL.

You are not always required to explicitly call the connect method to initiate the connection. Operations that depend on being connected, like getInputStream, getOutputStream, etc, will implicitly perform the connection, if necessary.

Now that you've successfully connected to your URL, you can use the URLConnection object to perform actions such as reading from or writing to the connection. The next section shows you how.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Reading Directly from a URL
Next page: Reading from and Writing to a URLConnection


Reading from and Writing to a URLConnection (The Java™ Tutorials > Custom Networking > Working with URLs)

Trail: Custom Networking
Lesson: Working with URLs
Working with URLs
What Is a URL?
Creating a URL
Parsing a URL
Reading Directly from a URL
Connecting to a URL
Reading from and Writing to a URLConnection
Home Page > Custom Networking > Working with URLs
« Previous • Trail • Next »
Reading from and Writing to a URLConnection
The URLConnection class contains many methods that let you communicate with the URL over the network. URLConnection is an HTTP-centric class; that is, many of its methods are useful only when you are working with HTTP URLs. However, most URL protocols allow you to read from and write to the connection. This section describes both functions.

Reading from a URLConnection

The following program performs the same function as the URLReader program shown in Reading Directly from a URL.

However, rather than getting an input stream directly from the URL, this program explicitly retrieves a URLConnection object and gets an input stream from the connection. The connection is opened implicitly by calling getInputStream. Then, like URLReader, this program creates a BufferedReader on the input stream and reads from it. The bold statements highlight the differences between this example and the previous

import java.net.*;
import java.io.*;

public class URLConnectionReader {
    public static void main(String[] args) throws Exception {
        URL yahoo = new URL("http://www.yahoo.com/");
        URLConnection yc = yahoo.openConnection();
        BufferedReader in = new BufferedReader(
                                new InputStreamReader(
                                yc.getInputStream()));
        String inputLine;

        while ((inputLine = in.readLine()) != null)
            System.out.println(inputLine);
        in.close();
    }
}
The output from this program is identical to the output from the program that opens a stream directly from the URL. You can use either way to read from a URL. However, reading from a URLConnection instead of reading directly from a URL might be more useful. This is because you can use the URLConnection object for other tasks (like writing to the URL) at the same time.

Again, if the program hangs or you see an error message, you may have to set the proxy host so that the program can find the Yahoo server.

Writing to a URLConnection

Many HTML pages contain forms-- text fields and other GUI objects that let you enter data to send to the server. After you type in the required information and initiate the query by clicking a button, your Web browser writes the data to the URL over the network. At the other end the server receives the data, processes it, and then sends you a response, usually in the form of a new HTML page.

Many of these HTML forms use the HTTP POST METHOD to send data to the server. Thus writing to a URL is often called posting to a URL. The server recognizes the POST request and reads the data sent from the client.

For a Java program to interact with a server-side process it simply must be able to write to a URL, thus providing data to the server. It can do this by following these steps:

  1. Create a URL.
  2. Retrieve the URLConnection object.
  3. Set output capability on the URLConnection.
  4. Open a connection to the resource.
  5. Get an output stream from the connection.
  6. Write to the output stream.
  7. Close the output stream.

Here is a small servlet named ReverseServlet ( or if you prefer a cgi-bin script ). You can use this servlet to test the following example program.

The servlet running in a container reads from its InputStream, reverses the string, and writes it to its OutputStream. The servlet requires input of the form string=string_to_reverse, where string_to_reverse is the string whose characters you want displayed in reverse order.

Here's an example program that runs the ReverseServlet over the network through a URLConnection:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.*;
import java.net.*;

public class Reverse {
    public static void main(String[] args) throws Exception {

    if (args.length != 2) {
        System.err.println("Usage:  java Reverse " +
                               "http://<location of your servlet/script>" +
                               " string_to_reverse");
        System.exit(1);
    }

    String stringToReverse = URLEncoder.encode(args[1], "UTF-8");

    URL url = new URL(args[0]);
    URLConnection connection = url.openConnection();
    connection.setDoOutput(true);

    OutputStreamWriter out = new OutputStreamWriter(
                              connection.getOutputStream());
    out.write("string=" + stringToReverse);
    out.close();

    BufferedReader in = new BufferedReader(
                new InputStreamReader(
                connection.getInputStream()));

    String decodedString;

    while ((decodedString = in.readLine()) != null) {
        System.out.println(decodedString);
    }
    in.close();
    }
}
Let's examine the program and see how it works. First, the program processes its command-line arguments:
if (args.length != 2) {
    System.err.println("Usage:  java Reverse " +
                        "http://<location of your servlet/script>" +
                    " string_to_reverse");
    System.exit(1);
}

String stringToReverse = URLEncoder.encode(args[1], "UTF-8");
These statements ensure that the user provides two and only two command-line arguments to the program. The command-line arguments are the location of the ReverseServlet and the string that will be reversed. It may contain spaces or other non-alphanumeric characters. These characters must be encoded because the string is processed on its way to the server. The URLEncoder class methods encode the characters.

Next, the program creates the URL object, and sets the connection so that it can write to it:

URL url = new URL(args[0]);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
The program then creates an output stream on the connection and opens an OutputStreamWriter on it:
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
If the URL does not support output, getOutputStream method throws an UnknownServiceException. If the URL does support output, then this method returns an output stream that is connected to the input stream of the URL on the server side--the client's output is the server's input.

Next, the program writes the required information to the output stream and closes the stream:

out.write("string=" + stringToReverse);
out.close();
This code writes to the output stream using the write method. So you can see that writing data to a URL is as easy as writing data to a stream. The data written to the output stream on the client side is the input for the servlet on the server side. The Reverse program constructs the input in the form required by the script by prepending string= to the encoded string to be reversed.

The serlvet reads the information you write, performs a reverse operation on the string value, and then sends this back to you. You now need to read the string the server has sent back. The Reverse program does it like this:

BufferReaderder in = new BufferedReader(
                     new InputStreamReader(
                     connection.getInputStream()));

String decodedString;

while ((decodedString = in.readLine()) != null) {
    System.out.println(decodedString);
}
in.close();
If your ReverseServlet is located at http://foobar.com/servlet/ReverseServlet, then when you run the Reverse program using
http://foobar.com/servlet/ReverseServlet "Reverse Me"
as the argument (including the double quote marks), you should see this output:
Reverse Me
 reversed is:
eM esreveR
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Connecting to a URL
Next page: All About Sockets


Lesson: All About Sockets (The Java™ Tutorials > Custom Networking)

All About Sockets
What Is a Socket?
Reading from and Writing to a Socket
Writing the Server Side of a Socket
Trail: Custom Networking
Home Page > Custom Networking
« Previous • Trail • Next »
Lesson: All About Sockets
URLs and URLConnections provide a relatively high-level mechanism for accessing resources on the Internet. Sometimes your programs require lower-level network communication, for example, when you want to write a client-server application.

In client-server applications, the server provides some service, such as processing database queries or sending out current stock prices. The client uses the service provided by the server, either displaying database query results to the user or making stock purchase recommendations to an investor. The communication that occurs between the client and the server must be reliable. That is, no data can be dropped and it must arrive on the client side in the same order in which the server sent it.

TCP provides a reliable, point-to-point communication channel that client-server applications on the Internet use to communicate with each other. To communicate over TCP, a client program and a server program establish a connection to one another. Each program binds a socket to its end of the connection. To communicate, the client and the server each reads from and writes to the socket bound to the connection.

What Is a Socket?

A socket is one end-point of a two-way communication link between two programs running on the network. Socket classes are used to represent the connection between a client program and a server program. The java.net package provides two classes--Socket and ServerSocket--that implement the client side of the connection and the server side of the connection, respectively.

Reading from and Writing to a Socket

This page contains a small example that illustrates how a client program can read from and write to a socket.

Writing a Client/Server Pair

The previous page showed an example of how to write a client program that interacts with an existing server via a Socket object. This page shows you how to write a program that implements the other side of the connection--a server program.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: What Is a Socket?


What Is a Socket? (The Java™ Tutorials > Custom Networking > All About Sockets)

Trail: Custom Networking
Lesson: All About Sockets
All About Sockets
What Is a Socket?
Reading from and Writing to a Socket
Writing the Server Side of a Socket
Home Page > Custom Networking > All About Sockets
« Previous • Trail • Next »
What Is a Socket?
Normally, a server runs on a specific computer and has a socket that is bound to a specific port number. The server just waits, listening to the socket for a client to make a connection request.

On the client-side: The client knows the hostname of the machine on which the server is running and the port number on which the server is listening. To make a connection request, the client tries to rendezvous with the server on the server's machine and port. The client also needs to identify itself to the server so it binds to a local port number that it will use during this connection. This is usually assigned by the system.

If everything goes well, the server accepts the connection. Upon acceptance, the server gets a new socket bound to the same local port and also has its remote endpoint set to the address and port of the client. It needs a new socket so that it can continue to listen to the original socket for connection requests while tending to the needs of the connected client.

On the client side, if the connection is accepted, a socket is successfully created and the client can use the socket to communicate with the server.

The client and server can now communicate by writing to or reading from their sockets.

Definition: A socket is one endpoint of a two-way communication link between two programs running on the network. A socket is bound to a port number so that the TCP layer can identify the application that data is destined to be sent.

An endpoint is a combination of an IP address and a port number. Every TCP connection can be uniquely identified by its two endpoints. That way you can have multiple connections between your host and the server.

The java.net package in the Java platform provides a class, Socket, that implements one side of a two-way connection between your Java program and another program on the network. The Socket class sits on top of a platform-dependent implementation, hiding the details of any particular system from your Java program. By using the java.net.Socket class instead of relying on native code, your Java programs can communicate over the network in a platform-independent fashion.

Additionally, java.net includes the ServerSocket class, which implements a socket that servers can use to listen for and accept connections to clients. This lesson shows you how to use the Socket and ServerSocket classes.

If you are trying to connect to the Web, the URL class and related classes (URLConnection, URLEncoder) are probably more appropriate than the socket classes. In fact, URLs are a relatively high-level connection to the Web and use sockets as part of the underlying implementation. See Working with URLs for information about connecting to the Web via URLs.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: All About Sockets
Next page: Reading from and Writing to a Socket


Reading from and Writing to a Socket (The Java™ Tutorials > Custom Networking > All About Sockets)

Trail: Custom Networking
Lesson: All About Sockets
All About Sockets
What Is a Socket?
Reading from and Writing to a Socket
Writing the Server Side of a Socket
Home Page > Custom Networking > All About Sockets
« Previous • Trail • Next »
Reading from and Writing to a Socket
Let's look at a simple example that illustrates how a program can establish a connection to a server program using the Socket class and then, how the client can send data to and receive data from the server through the socket.

The example program implements a client, EchoClient, that connects to the Echo server. The Echo server simply receives data from its client and echoes it back. The Echo server is a well-known service that clients can rendezvous with on port 7.

EchoClient creates a socket thereby getting a connection to the Echo server. It reads input from the user on the standard input stream, and then forwards that text to the Echo server by writing the text to the socket. The server echoes the input back through the socket to the client. The client program reads and displays the data passed back to it from the server:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.*;
import java.net.*;

public class EchoClient {
    public static void main(String[] args) throws IOException {

        Socket echoSocket = null;
        PrintWriter out = null;
        BufferedReader in = null;

        try {
            echoSocket = new Socket("taranis", 7);
            out = new PrintWriter(echoSocket.getOutputStream(), true);
            in = new BufferedReader(new InputStreamReader(
                                        echoSocket.getInputStream()));
        } catch (UnknownHostException e) {
            System.err.println("Don't know about host: taranis.");
            System.exit(1);
        } catch (IOException e) {
            System.err.println("Couldn't get I/O for "
                               + "the connection to: taranis.");
            System.exit(1);
        }

    BufferedReader stdIn = new BufferedReader(
                                   new InputStreamReader(System.in));
    String userInput;

    while ((userInput = stdIn.readLine()) != null) {
        out.println(userInput);
        System.out.println("echo: " + in.readLine());
    }

    out.close();
    in.close();
    stdIn.close();
    echoSocket.close();
    }
}
Note that EchoClient both writes to and reads from its socket, thereby sending data to and receiving data from the Echo server.

Let's walk through the program and investigate the interesting parts. The three statements in the try block of the main method are critical. These lines establish the socket connection between the client and the server and open a PrintWriter and a BufferedReader on the socket:

echoSocket = new Socket("taranis", 7);
out = new PrintWriter(echoSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
                             echoSocket.getInputStream()));
The first statement in this sequence creates a new Socket object and names it echoSocket. The Socket constructor used here requires the name of the machine and the port number to which you want to connect. The example program uses the host name taranis. This is the name of a hypothetical machine on our local network. When you type in and run this program on your machine, change the host name to the name of a machine on your network. Make sure that the name you use is the fully qualified IP name of the machine to which you want to connect. The second argument is the port number. Port number 7 is the port on which the Echo server listens.

The second statement gets the socket's output stream and opens a PrintWriter on it. Similarly, the third statement gets the socket's input stream and opens a BufferedReader on it. The example uses readers and writers so that it can write Unicode characters over the socket.

To send data through the socket to the server, EchoClient simply needs to write to the PrintWriter. To get the server's response, EchoClient reads from the BufferedReader. The rest of the program achieves this. If you are not yet familiar with the Java platform's I/O classes, you may wish to read Basic I/O.

The next interesting part of the program is the while loop. The loop reads a line at a time from the standard input stream and immediately sends it to the server by writing it to the PrintWriter connected to the socket:

String userInput;

while ((userInput = stdIn.readLine()) != null) {
    out.println(userInput);
    System.out.println("echo: " + in.readLine());
}
The last statement in the while loop reads a line of information from the BufferedReader connected to the socket. The readLine method waits until the server echoes the information back to EchoClient. When readline returns, EchoClient prints the information to the standard output.

The while loop continues until the user types an end-of-input character. That is, EchoClient reads input from the user, sends it to the Echo server, gets a response from the server, and displays it, until it reaches the end-of-input. The while loop then terminates and the program continues, executing the next four lines of code:

out.close();
in.close();
stdIn.close();
echoSocket.close();
These lines of code fall into the category of housekeeping. A well-behaved program always cleans up after itself, and this program is well-behaved. These statements close the readers and writers connected to the socket and to the standard input stream, and close the socket connection to the server. The order here is important. You should close any streams connected to a socket before you close the socket itself.

This client program is straightforward and simple because the Echo server implements a simple protocol. The client sends text to the server, and the server echoes it back. When your client programs are talking to a more complicated server such as an HTTP server, your client program will also be more complicated. However, the basics are much the same as they are in this program:

  1. Open a socket.
  2. Open an input stream and output stream to the socket.
  3. Read from and write to the stream according to the server's protocol.
  4. Close the streams.
  5. Close the socket.
Only step 3 differs from client to client, depending on the server. The other steps remain largely the same.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: What Is a Socket?
Next page: Writing the Server Side of a Socket


Writing the Server Side of a Socket (The Java™ Tutorials > Custom Networking > All About Sockets)

Trail: Custom Networking
Lesson: All About Sockets
All About Sockets
What Is a Socket?
Reading from and Writing to a Socket
Writing the Server Side of a Socket
Home Page > Custom Networking > All About Sockets
« Previous • Trail • Next »
Writing the Server Side of a Socket
This section shows you how to write a server and the client that goes with it. The server in the client/server pair serves up Knock Knock jokes. Knock Knock jokes are favored by children and are usually vehicles for bad puns. They go like this:

Server: "Knock knock!"
Client: "Who's there?"
Server: "Dexter."
Client: "Dexter who?"
Server: "Dexter halls with boughs of holly."
Client: "Groan."

The example consists of two independently running Java programs: the client program and the server program. The client program is implemented by a single class, KnockKnockClient, and is very similar to the EchoClient example from the previous section. The server program is implemented by two classes: KnockKnockServer and KnockKnockProtocol, KnockKnockServer contains the main method for the server program and performs the work of listening to the port, establishing connections, and reading from and writing to the socket. KnockKnockProtocol serves up the jokes. It keeps track of the current joke, the current state (sent knock knock, sent clue, and so on), and returns the various text pieces of the joke depending on the current state. This object implements the protocol-the language that the client and server have agreed to use to communicate.

The following section looks in detail at each class in both the client and the server and then shows you how to run them.

The Knock Knock Server

This section walks through the code that implements the Knock Knock server program. Here is the complete source for the KnockKnockServer class.

The server program begins by creating a new ServerSocket object to listen on a specific port (see the statement in bold in the following code segment). When writing a server, choose a port that is not already dedicated to some other service. KnockKnockServer listens on port 4444 because 4 happens to be my favorite number and port 4444 is not being used for anything else in my environment:

try {
    serverSocket = new ServerSocket(4444);
} catch (IOException e) {
    System.out.println("Could not listen on port: 4444");
    System.exit(-1);
}
ServerSocket is a java.net class that provides a system-independent implementation of the server side of a client/server socket connection. The constructor for ServerSocket throws an exception if it can't listen on the specified port (for example, the port is already being used). In this case, the KnockKnockServer has no choice but to exit.

If the server successfully binds to its port, then the ServerSocket object is successfully created and the server continues to the next step--accepting a connection from a client (shown in bold):

Socket clientSocket = null;
try {
    clientSocket = serverSocket.accept();
} catch (IOException e) {
    System.out.println("Accept failed: 4444");
    System.exit(-1);
}
The accept method waits until a client starts up and requests a connection on the host and port of this server (in this example, the server is running on the hypothetical machine taranis on port 4444). When a connection is requested and successfully established, the accept method returns a new Socket object which is bound to the same local port and has it's remote address and remote port set to that of the client. The server can communicate with the client over this new Socket and continue to listen for client connection requests on the original ServerSocket This particular version of the program doesn't listen for more client connection requests. However, a modified version of the program is provided in Supporting Multiple Clients.

After the server successfully establishes a connection with a client, it communicates with the client using this code:

PrintWriter out = new PrintWriter(
                      clientSocket.getOutputStream(), true);
BufferedReader in = new BufferedReader(
                        new InputStreamReader(
                            clientSocket.getInputStream()));
String inputLine, outputLine;

// initiate conversation with client
KnockKnockProtocol kkp = new KnockKnockProtocol();
outputLine = kkp.processInput(null);
out.println(outputLine);

while ((inputLine = in.readLine()) != null) {
    outputLine = kkp.processInput(inputLine);
    out.println(outputLine);
    if outputLine.equals("Bye."))
        break;
}
This code:
  1. Gets the socket's input and output stream and opens readers and writers on them.
  2. Initiates communication with the client by writing to the socket (shown in bold).
  3. Communicates with the client by reading from and writing to the socket (the while loop).
Step 1 is already familiar. Step 2 is shown in bold and is worth a few comments. The bold statements in the code segment above initiate the conversation with the client. The code creates a KnockKnockProtocol object-the object that keeps track of the current joke, the current state within the joke, and so on.

After the KnockKnockProtocol is created, the code calls KnockKnockProtocol's processInput method to get the first message that the server sends to the client. For this example, the first thing that the server says is "Knock! Knock!" Next, the server writes the information to the PrintWriter connected to the client socket, thereby sending the message to the client.

Step 3 is encoded in the while loop. As long as the client and server still have something to say to each other, the server reads from and writes to the socket, sending messages back and forth between the client and the server.

The server initiated the conversation with a "Knock! Knock!" so afterwards the server must wait for the client to say "Who's there?" As a result, the while loop iterates on a read from the input stream. The readLine method waits until the client responds by writing something to its output stream (the server's input stream). When the client responds, the server passes the client's response to the KnockKnockProtocol object and asks the KnockKnockProtocol object for a suitable reply. The server immediately sends the reply to the client via the output stream connected to the socket, using a call to println. If the server's response generated from the KnockKnockServer object is "Bye." this indicates that the client doesn't want any more jokes and the loop quits.

The KnockKnockServer class is a well-behaved server, so the last several lines of this section of KnockKnockServer clean up by closing all of the input and output streams, the client socket, and the server socket:

out.close();
in.close();
clientSocket.close();
serverSocket.close();

The Knock Knock Protocol

The KnockKnockProtocol class implements the protocol that the client and server use to communicate. This class keeps track of where the client and the server are in their conversation and serves up the server's response to the client's statements. The KnockKnockServer object contains the text of all the jokes and makes sure that the client gives the proper response to the server's statements. It wouldn't do to have the client say "Dexter who?" when the server says "Knock! Knock!"

All client/server pairs must have some protocol by which they speak to each other; otherwise, the data that passes back and forth would be meaningless. The protocol that your own clients and servers use depends entirely on the communication required by them to accomplish the task.

The Knock Knock Client

The KnockKnockClient class implements the client program that speaks to the KnockKnockServer. KnockKnockClient is based on the EchoClient program in the previous section, Reading from and Writing to a Socket and should be somewhat familiar to you. But we'll go over the program anyway and look at what's happening in the client in the context of what's going on in the server.

When you start the client program, the server should already be running and listening to the port, waiting for a client to request a connection. So, the first thing the client program does is to open a socket that is connected to the server running on the hostname and port specified:

kkSocket = new Socket("taranis", 4444);
out = new PrintWriter(kkSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(
                            kkSocket.getInputStream()));
When creating its socket, KnockKnockClient uses the host name taranis, the name of a hypothetical machine on our network. When you type in and run this program, change the host name to the name of a machine on your network. This is the machine on which you will run the KnockKnockServer.

The KnockKnockClient program also specifies the port number 4444 when creating its socket. This is a remote port number--the number of a port on the server machine--and is the port to which KnockKnockServer is listening. The client's socket is bound to any available local port--a port on the client machine. Remember that the server gets a new socket as well. That socket is bound to local port number 4444 on its machine. The server's socket and the client's socket are connected.

Next comes the while loop that implements the communication between the client and the server. The server speaks first, so the client must listen first. The client does this by reading from the input stream attached to the socket. If the server does speak, it says "Bye." and the client exits the loop. Otherwise, the client displays the text to the standard output and then reads the response from the user, who types into the standard input. After the user types a carriage return, the client sends the text to the server through the output stream attached to the socket.

while ((fromServer = in.readLine()) != null) {
    System.out.println("Server: " + fromServer);
    if (fromServer.equals("Bye."))
        break;
    fromUser = stdIn.readLine();
    if (fromUser != null) {
        System.out.println("Client: " + fromUser);
        out.println(fromUser);
    }
}
The communication ends when the server asks if the client wishes to hear another joke, the client says no, and the server says "Bye."

In the interest of good housekeeping, the client closes its input and output streams and the socket:

out.close();
in.close();
stdIn.close();
kkSocket.close();

Running the Programs

You must start the server program first. To do this, run the server program using the Java interpreter, just as you would any other Java application. Remember to run the server on the machine that the client program specifies when it creates the socket.

Next, run the client program. Note that you can run the client on any machine on your network; it does not have to run on the same machine as the server.

If you are too quick, you might start the client before the server has a chance to initialize itself and begin listening on the port. If this happens, you will see a stack trace from the client. If this happens, just restart the client.

If you forget to change the host name in the source code for the KnockKnockClient program, you will see the following error message:

Don't know about host: taranis
To fix this, modify the KnockKnockClient program and provide a valid host name for your network. Recompile the client program and try again.

If you try to start a second client while the first client is connected to the server, the second client just hangs. The next section, Supporting Multiple Clients, talks about supporting multiple clients.

When you successfully get a connection between the client and server, you will see the following text displayed on your screen:

Server: Knock! Knock!
Now, you must respond with:
Who's there?
The client echoes what you type and sends the text to the server. The server responds with the first line of one of the many Knock Knock jokes in its repertoire. Now your screen should contain this (the text you typed is in bold):
Server: Knock! Knock!
Who's there?
Client: Who's there?
Server: Turnip
Now, you respond with:
Turnip who?"
Again, the client echoes what you type and sends the text to the server. The server responds with the punch line. Now your screen should contain this:
Server: Knock! Knock!
Who's there?
Client: Who's there?
Server: Turnip
Turnip who?
Client: Turnip who?
Server: Turnip the heat, it's cold in here! Want another? (y/n)
If you want to hear another joke, type y; if not, type n. If you type y, the server begins again with "Knock! Knock!" If you type n, the server says "Bye." thus causing both the client and the server to exit.

If at any point you make a typing mistake, the KnockKnockServer object catches it and the server responds with a message similar to this:

Server: You're supposed to say "Who's there?"!
The server then starts the joke over again:
Server: Try again. Knock! Knock!
Note that the KnockKnockProtocol object is particular about spelling and punctuation but not about capitalization.

Supporting Multiple Clients
To keep the KnockKnockServer example simple, we designed it to listen for and handle a single connection request. However, multiple client requests can come into the same port and, consequently, into the same ServerSocket. Client connection requests are queued at the port, so the server must accept the connections sequentially. However, the server can service them simultaneously through the use of threads - one thread per each client connection.

The basic flow of logic in such a server is this:

while (true) {
    accept a connection ;
    create a thread to deal with the client ;
end while
The thread reads from and writes to the client connection as necessary.

Try This: Modify the KnockKnockServer so that it can service multiple clients at the same time. Two classes compose our solution: KKMultiServer and KKMultiServerThread. KKMultiServer loops forever, listening for client connection requests on a ServerSocket. When a request comes in, KKMultiServer accepts the connection, creates a new KKMultiServerThread object to process it, hands it the socket returned from accept, and starts the thread. Then the server goes back to listening for connection requests. The KKMultiServerThread object communicates to the client by reading from and writing to the socket. Run the new Knock Knock server and then run several clients in succession.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Reading from and Writing to a Socket
Next page: All About Datagrams


Lesson: All About Datagrams (The Java™ Tutorials > Custom Networking)

All About Datagrams
What Is a Datagram?
Writing a Datagram Client and Server
Broadcasting to Multiple Recipients
Trail: Custom Networking
Home Page > Custom Networking
« Previous • Trail • Next »
Lesson: All About Datagrams
Some applications that you write to communicate over the network will not require the reliable, point-to-point channel provided by TCP. Rather, your applications might benefit from a mode of communication that delivers independent packages of information whose arrival and order of arrival are not guaranteed.

The UDP protocol provides a mode of network communication whereby applications send packets of data, called datagrams, to one another. A datagram is an independent, self-contained message sent over the network whose arrival, arrival time, and content are not guaranteed. The DatagramPacket and DatagramSocket classes in the java.net package implement system-independent datagram communication using UDP.

What Is a Datagram?

A datagram is an independent, self-contained message sent over the network whose arrival, arrival time, and content are not guaranteed.

Writing a Datagram Client and Server

This section walks you through an example that contains two Java programs that use datagrams to communicate. The server side is a quote server that listens to its DatagramSocket and sends a quotation to a client whenever the client requests it. The client side is a simple program that simply makes a request of the server.

Broadcasting to Multiple Recipients

This section modifies the quote server so that instead of sending a quotation to a single client upon request, the quote server broadcasts a quote every minute to as many clients as are listening. The client program must be modified accordingly.
Note: Many firewalls and routers are configured not to allow UDP packets. If you have trouble connecting to a service outside your firewall, or if clients have trouble connecting to your service, ask your system administrator if UDP is permitted.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: What Is a Datagram?


What Is a Datagram? (The Java™ Tutorials > Custom Networking > All About Datagrams)

Trail: Custom Networking
Lesson: All About Datagrams
All About Datagrams
What Is a Datagram?
Writing a Datagram Client and Server
Broadcasting to Multiple Recipients
Home Page > Custom Networking > All About Datagrams
« Previous • Trail • Next »
What Is a Datagram?
Clients and servers that communicate via a reliable channel, such as a TCP socket, have a dedicated point-to-point channel between themselves, or at least the illusion of one. To communicate, they establish a connection, transmit the data, and then close the connection. All data sent over the channel is received in the same order in which it was sent. This is guaranteed by the channel.

In contrast, applications that communicate via datagrams send and receive completely independent packets of information. These clients and servers do not have and do not need a dedicated point-to-point channel. The delivery of datagrams to their destinations is not guaranteed. Nor is the order of their arrival.

Definition: A datagram is an independent, self-contained message sent over the network whose arrival, arrival time, and content are not guaranteed.

The java.net package contains three classes to help you write Java programs that use datagrams to send and receive packets over the network: DatagramSocket, DatagramPacket, and MulticastSocketAn application can send and receive DatagramPackets through a DatagramSocket. In addition, DatagramPackets can be broadcast to multiple recipients all listening to a MulticastSocket.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: All About Datagrams
Next page: Writing a Datagram Client and Server


Writing a Datagram Client and Server (The Java™ Tutorials > Custom Networking > All About Datagrams)

Trail: Custom Networking
Lesson: All About Datagrams
All About Datagrams
What Is a Datagram?
Writing a Datagram Client and Server
Broadcasting to Multiple Recipients
Home Page > Custom Networking > All About Datagrams
« Previous • Trail • Next »
Writing a Datagram Client and Server
The example featured in this section consists of two applications: a client and a server. The server continuously receives datagram packets over a datagram socket. Each datagram packet received by the server indicates a client request for a quotation. When the server receives a datagram, it replies by sending a datagram packet that contains a one-line "quote of the moment" back to the client.

The client application in this example is fairly simple. It sends a single datagram packet to the server indicating that the client would like to receive a quote of the moment. The client then waits for the server to send a datagram packet in response.

Two classes implement the server application: QuoteServer and QuoteServerThread. A single class implements the client application: QuoteClient.

Let's investigate these classes, starting with the class that contains the main method for the server application. Working with a Server-Side Application contains an applet version of the QuoteClient class.

The QuoteServer Class
The QuoteServer class, shown here in its entirety, contains a single method: the main method for the quote server application. The main method simply creates a new QuoteServerThread object and starts it:
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.*;

public class QuoteServer {
    public static void main(String[] args) throws IOException {
        new QuoteServerThread().start();
    }
}
The QuoteServerThread class implements the main logic of the quote server.

The QuoteServerThread Class

When created, the QuoteServerThread creates a DatagramSocket on port 4445 (arbitrarily chosen). This is the DatagramSocket through which the server communicates with all of its clients.
public QuoteServerThread() throws IOException {
    this("QuoteServer");
}
public QuoteServerThread(String name) throws IOException {
    super(name);
    socket = new DatagramSocket(4445);

    try {
        in = new BufferedReader(
                  new FileReader("one-liners.txt"));
    } catch (FileNotFoundException e)
        System.err.println("Couldn't open quote file. " +
                          "Serving time instead.");
    }
}
Remember that certain ports are dedicated to well-known services and you cannot use them. If you specify a port that is in use, the creation of the DatagramSocket will fail.

The constructor also opens a BufferedReader on a file named one-liners.txt which contains a list of quotes. Each quote in the file is on a line by itself.

Now for the interesting part of the QuoteServerThread: its run method. The run method overrides run in the Thread class and provides the implementation for the thread. For information about threads, see Defining and Starting a Thread.

The run method contains a while loop that continues as long as there are more quotes in the file. During each iteration of the loop, the thread waits for a DatagramPacket to arrive over the DatagramSocket. The packet indicates a request from a client. In response to the client's request, the QuoteServerThread gets a quote from the file, puts it in a DatagramPacket and sends it over the DatagramSocket to the client that asked for it.

Let's look first at the section that receives the requests from clients:

byte[] buf = new byte[256];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
The first statement creates an array of bytes which is then used to create a DatagramPacket. The DatagramPacket will be used to receive a datagram from the socket because of the constructor used to create it. This constructor requires only two arguments: a byte array that contains client-specific data and the length of the byte array. When constructing a DatagramPacket to send over the DatagramSocket, you also must supply the Internet address and port number of the packet's destination. You'll see this later when we discuss how the server responds to a client request.

The last statement in the previous code snippet receives a datagram from the socket (the information received from the client gets copied into the packet). The receive method waits forever until a packet is received. If no packet is received, the server makes no further progress and just waits.

Now assume that, the server has received a request from a client for a quote. Now the server must respond. This section of code in the run method constructs the response:

String dString = null;
if (in == null)
    dString = new Date().toString();
else
    dString = getNextQuote();
buf = dString.getBytes();
If the quote file did not get opened for some reason, then in equals null. If this is the case, the quote server serves up the time of day instead. Otherwise, the quote server gets the next quote from the already opened file. Finally, the code converts the string to an array of bytes.

Now, the run method sends the response to the client over the DatagramSocket with this code:

InetAddress address = packet.getAddress();
int port = packet.getPort();
packet = new DatagramPacket(buf, buf.length, address, port);
socket.send(packet);
The first two statements in this code segment get the Internet address and the port number, respectively, from the datagram packet received from the client. The Internet address and port number indicate where the datagram packet came from. This is where the server must send its response. In this example, the byte array of the datagram packet contains no relevant information. The arrival of the packet itself indicates a request from a client that can be found at the Internet address and port number indicated in the datagram packet.

The third statement creates a new DatagramPacket object intended for sending a datagram message over the datagram socket. You can tell that the new DatagramPacket is intended to send data over the socket because of the constructor used to create it. This constructor requires four arguments. The first two arguments are the same required by the constructor used to create receiving datagrams: a byte array containing the message from the sender to the receiver and the length of this array. The next two arguments are different: an Internet address and a port number. These two arguments are the complete address of the destination of the datagram packet and must be supplied by the sender of the datagram. The last line of code sends the DatagramPacket on its way.

When the server has read all the quotes from the quote file, the while loop terminates and the run method cleans up:

socket.close();

The QuoteClient Class

The QuoteClient class implements a client application for the QuoteServer. This application sends a request to the QuoteServer, waits for the response, and, when the response is received, displays it to the standard output. Let's look at the code in detail.

The QuoteClient class contains one method, the main method for the client application. The top of the main method declares several local variables for its use:

int port;
InetAddress address;
DatagramSocket socket = null;
DatagramPacket packet;
byte[] sendBuf = new byte[256];
First, the main method processes the command-line arguments used to invoke the QuoteClient application:
if (args.length != 1) {
     System.out.println("Usage: java QuoteClient <hostname>");
     return;
}
The QuoteClient application requires one command-line arguments: the name of the machine on which the QuoteServer is running.

Next, the main method creates a DatagramSocket:

DatagramSocket socket = new DatagramSocket();
The client uses a constructor that does not require a port number. This constructor just binds the DatagramSocket to any available local port. It doesn't matter what port the client is bound to because the DatagramPackets contain the addressing information. The server gets the port number from the DatagramPackets and send its response to that port.

Next, the QuoteClient program sends a request to the server:

byte[] buf = new byte[256];
InetAddress address = InetAddress.getByName(args[0]);
DatagramPacket packet = new DatagramPacket(buf, buf.length,
                                           address, 4445);
socket.send(packet);
The code segment gets the Internet address for the host named on the command line (presumably the name of the machine on which the server is running). This InetAddress and the port number 4445 (the port number that the server used to create its DatagramSocket) are then used to create DatagramPacket destined for that Internet address and port number. Therefore the DatagramPacket will be delivered to the quote server.

Note that the code creates a DatagramPacket with an empty byte array. The byte array is empty because this datagram packet is simply a request to the server for information. All the server needs to know to send a response--the address and port number to which reply--is automatically part of the packet.

Next, the client gets a response from the server and displays it:

packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
String received = new String(packet.getData(), 0, packet.getLength());
System.out.println("Quote of the Moment: " + received);
To get a response from the server, the client creates a "receive" packet and uses the DatagramSocket receive method to receive the reply from the server. The receive method waits until a datagram packet destined for the client comes through the socket. Note that if the server's reply is somehow lost, the client will wait forever because of the no-guarantee policy of the datagram model. Normally, a client sets a timer so that it doesn't wait forever for a reply; if no reply arrives, the timer goes off and the client retransmits.

When the client receives a reply from the server, the client uses the getData method to retrieve that data from the packet. The client then converts the data to a string and displays it.

Running the Server and Client

After you've successfully compiled the server and the client programs, you run them. You have to run the server program first. Just use the Java interpreter and specify the QuoteServer class name.

Once the server has started, you can run the client program. Remember to run the client program with one command-line argument: the name of the host on which the QuoteServer is running.

After the client sends a request and receives a response from the server, you should see output similar to this:

Quote of the Moment:
Good programming is 99% sweat and 1% coffee.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: What Is a Datagram?
Next page: Broadcasting to Multiple Recipients


Broadcasting to Multiple Recipients (The Java™ Tutorials > Custom Networking > All About Datagrams)

Trail: Custom Networking
Lesson: All About Datagrams
All About Datagrams
What Is a Datagram?
Writing a Datagram Client and Server
Broadcasting to Multiple Recipients
Home Page > Custom Networking > All About Datagrams
« Previous • Trail • Next »
Broadcasting to Multiple Recipients
In addition to DatagramSocket, which lets programs send packets to one another, java.net includes a class called MulticastSocket. This kind of socket is used on the client-side to listen for packets that the server broadcasts to multiple clients.

Let's rewrite the quote server so that it broadcasts DatagramPackets to multiple recipients. Instead of sending quotes to a specific client that makes a request, the new server now needs to broadcast quotes at a regular interval. The client needs to be modified so that it passively listens for quotes and does so on a MulticastSocket.

This example is comprised of three classes which are modifications of the three classes from the previous example: MulticastServer, MulticastServerThread, and MulticastClient. This discussion highlights the interesting parts of these classes.

Here is the new version of the server's main program. The differences between this code and the previous version, QuoteServer, are shown in bold:

import java.io.*;
public class MulticastServer {
    public static void main(String[] args) throws IOException {
        new MulticastServerThread().start();
    }
}
Basically, the server got a new name and creates a MulticastServerThread instead of a QuoteServerThread. Now let's look at the MulticastServerThread which contains the heart of the server. Here's its class declaration:
public class MulticastServerThread extends QuoteServerThread {
    ...
}
We've made this class a subclass of QuoteServerThread so that it can use the constructor, and inherit some member variable and the getNextQuote method. Recall that QuoteServerThread creates a DatagramSocket bound to port 4445 and opens the quote file. The DatagramSocket's port number doesn't actually matter in this example because the client never send anything to the server.

The only method explicitly implemented in MulticastServerThread is its run method. The differences between this run method and the one in QuoteServerThread are shown in bold:

public void run() {
    while (moreQuotes) {
        try {
            byte[] buf new byte[256];
            // don't wait for request...just send a quote

            String dString = null;
            if (in == null)
                dString = new Date().toString();
            else
                dString = getNextQuote();
            buf = dString.getBytes();

            InetAddress group = InetAddress.getByName(
                                            "230.0.0.1");
            DatagramPacket packet;
            packet = new DatagramPacket(buf, buf.length,
                                        group, 4446);
            socket.send(packet);

            try {
                sleep((long)Math.random() * FIVE_SECONDS);
            } catch (InterruptedException e) { }
        } catch (IOException e) {
            e.printStackTrace();
            moreQuotes = false;
        }
    }
    socket.close();
}
The interesting change is how the DatagramPacket is constructed, in particular, the InetAddress and port used to construct the DatagramPacket. Recall that the previous example retrieved the InetAddress and port number from the packet sent to the server from the client. This was because the server needed to reply directly to the client. Now, the server needs to address multiple clients. So this time both the InetAddress and the port number are hard-coded.

The hard-coded port number is 4446 (the client must have a MulticastSocket bound to this port). The hard-coded InetAddress of the DatagramPacket is "230.0.0.1" and is a group identifier (rather than the Internet address of the machine on which a single client is running). This particular address was arbitrarily chosen from the reserved for this purpose.

Created in this way, the DatagramPacket is destined for all clients listening to port number 4446 who are member of the "230.0.0.1" group.

To listen to port number 4446, the new client program just created its MulticastSocket with that port number. To become a member of the "230.0.0.1" group, the client calls the MulticastSocket's joinGroup method with the InetAddress that identifies the group. Now, the client is set up to receive DatagramPackets destined for the port and group specified. Here's the relevant code from the new client program (which was also rewritten to passively receive quotes rather than actively request them). The bold statements are the ones that interact with the MulticastSocket:

MulticastSocket socket = new MulticastSocket(4446);
InetAddress group = InetAddress.getByName("230.0.0.1");
socket.joinGroup(group);

DatagramPacket packet;
for (int i = 0; i < 5; i++) {
    byte[] buf = new byte[256];
    packet = new DatagramPacket(buf, buf.length);
    socket.receive(packet);

    String received = new String(packet.getData());
    System.out.println("Quote of the Moment: " + received);
}
socket.leaveGroup(group);
socket.close();
Notice that the server uses a DatagramSocket to broadcast packet received by the client over a MulticastSocket. Alternatively, it could have used a MulticastSocket. The socket used by the server to send the DatagramPacket is not important. What's important when broadcasting packets is the addressing information contained in the DatagramPacket, and the socket used by the client to listen for it

Try this: Run the MulticastServer and several clients. Watch how the clients all get the same quotes.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Writing a Datagram Client and Server
Next page: Programmatic Access to Network Parameters


Lesson: Programmatic Access to Network Parameters (The Java™ Tutorials > Custom Networking)

Programmatic Access to Network Parameters
What Is a Network Interface?
Retrieving Network Interfaces
Listing Network Interface Addresses
Network Interface Parameters
Trail: Custom Networking
Home Page > Custom Networking
« Previous • Trail • Next »
Lesson: Programmatic Access to Network Parameters
Systems often run with multiple active network connections, such as wired Ethernet, 802.11 b/g (wireless), and bluetooth. Some applications might need to access this information to perform the particular network activity on a specific connection.

The java.net.NetworkInterface class provides access to this information.

This lesson guides you through some of the more common uses of this class and provides examples that list all the network interfaces on a machine as well as their IP addresses and status.

What Is a Network Interface?

This page describes a network interface and explains why you might want to use it.

Retrieving Network Interfaces

This page contains an example that illustrates how a client program can retrieve all the network interfaces on a machine.

Listing Network Interface Addresses

This page shows you how to list the IP addresses assigned to all the network interfaces on a machine.

Network Interface Parameters

This page shows you how to determine whether a network interface is running or if the network interface is a loopback interface, a point-to-point interface, or a virtual interface. You can also learn how to determine if the interface supports multicasting.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: What Is a Network Interface?


What Is a Network Interface? (The Java™ Tutorials > Custom Networking > Programmatic Access to Network Parameters)

Trail: Custom Networking
Lesson: Programmatic Access to Network Parameters
Programmatic Access to Network Parameters
What Is a Network Interface?
Retrieving Network Interfaces
Listing Network Interface Addresses
Network Interface Parameters
Home Page > Custom Networking > Programmatic Access to Network Parameters
« Previous • Trail • Next »
What Is a Network Interface?
A network interface is the point of interconnection between a computer and a private or public network. A network interface is generally a network interface card (NIC), but does not have to have a physical form. Instead, the network interface can be implemented in software. For example, the loopback interface (127.0.0.1 for IPv4 and ::1 for IPv6) is not a physical device but a piece of software simulating a network interface. The loopback interface is commonly used in test environments.

The java.net.NetworkInterface class represents both types of interfaces.

NetworkInterface is useful for a multihomed system, which is a system with multiple NICs. Using NetworkInterface, you can specify which NIC to use for a particular network activity.

For example, assume you have a machine with two configured NICs, and you want to send data to a server. You create a socket like this:

  Socket soc = new java.net.Socket();
  soc.connect(new InetSocketAddress(address, port));
To send the data, the system determines which interface will be used. However, if you have a preference or otherwise need to specify which NIC to use, you can query the system for the appropriate interfaces and find an address on the interface you want to use. When you create the socket and bind it to that address, the system will use the associated interface. For example:
  NetworkInterface nif = NetworkInterface.getByName("bge0");
  Enumeration nifAddresses = nif.getInetAddresses();

  Socket soc = new java.net.Socket();
  soc.bind(nifAddresses.nextElement());
  soc.connect(new InetSocketAddress(address, port));

You can also use NetworkInterface to identify the local interface on which a multicast group is to be joined. For example:

  NetworkInterface nif = NetworkInterface.getByName("bge0");

  MulticastSocket() ms = new MulticastSocket();
  ms.joinGroup(new InetSocketAddress(hostname, port) , nif);

NetworkInterface can be used with Java APIs in many other ways beyond the two uses described here.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Programmatic Access to Network Parameters
Next page: Retrieving Network Interfaces


Retrieving Network Interfaces (The Java™ Tutorials > Custom Networking > Programmatic Access to Network Parameters)

Trail: Custom Networking
Lesson: Programmatic Access to Network Parameters
Programmatic Access to Network Parameters
What Is a Network Interface?
Retrieving Network Interfaces
Listing Network Interface Addresses
Network Interface Parameters
Home Page > Custom Networking > Programmatic Access to Network Parameters
« Previous • Trail • Next »
Retrieving Network Interfaces
The NetworkInterface class has no public constructor. Therefore, you cannot just create a new instance of this class with the new operator. Instead, the following static methods are available so that you can retrieve the interface details from the system: getByInetAddress(), getByName(), and getNetworkInterfaces(). The first two methods are used when you already know the IP address or the name of the particular interface. The third method, getNetworkInterfaces() returns the complete list of interfaces on the machine.

Network interfaces can be hierarchically organized. The NetworkInterface class includes two methods, getParent() and getSubInterfaces(), that are pertinent to a network interface hierarchy. The getParent() method returns the parent NetworkInterface of an interface. If a network interface is a subinterface, getParent() returns a non-null value. The getSubInterfaces() method returns all the subinterfaces of a network interface.

The following example program lists the name of all the network interfaces and subinterfaces (if any exist) on a machine.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.*;
import java.net.*;
import java.util.*;
import static java.lang.System.out;

public class ListNIFs
{
    public static void main(String args[]) throws SocketException {
        Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();

        for (NetworkInterface netIf : Collections.list(nets)) {
            out.printf("Display name: %s\n", netIf.getDisplayName());
            out.printf("Name: %s\n", netIf.getName());
            displaySubInterfaces(netIf);
            out.printf("\n");
        }
    }

    static void displaySubInterfaces(NetworkInterface netIf) throws SocketException {
        Enumeration<NetworkInterface> subIfs = netIf.getSubInterfaces();

        for (NetworkInterface subIf : Collections.list(subIfs)) {
            out.printf("\tSub Interface Display name: %s\n", subIf.getDisplayName());
            out.printf("\tSub Interface Name: %s\n", subIf.getName());
        }
     }
}
The following is sample output from the example program:
Display name: bge0
Name: bge0
    Sub Interface Display name: bge0:3
    Sub Interface Name: bge0:3
    Sub Interface Display name: bge0:2
    Sub Interface Name: bge0:2
    Sub Interface Display name: bge0:1
    Sub Interface Name: bge0:1

Display name: lo0
Name: lo0
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: What Is a Network Interface?
Next page: Listing Network Interface Addresses


Listing Network Interface Addresses (The Java™ Tutorials > Custom Networking > Programmatic Access to Network Parameters)

Trail: Custom Networking
Lesson: Programmatic Access to Network Parameters
Programmatic Access to Network Parameters
What Is a Network Interface?
Retrieving Network Interfaces
Listing Network Interface Addresses
Network Interface Parameters
Home Page > Custom Networking > Programmatic Access to Network Parameters
« Previous • Trail • Next »
Listing Network Interface Addresses
One of the most useful pieces of information you can get from a network interface is the list of IP addresses that are assigned to it. You can obtain this information from a NetworkInterface instance by using one of two methods. The first method, getInetAddresses(), returns an Enumeration of InetAddress. The other method, getInterfaceAddresses(), returns a list of java.net.InterfaceAddress instances. This method is used when you need more information about an interface address beyond its IP address. For example, you might need additional information about the subnet mask and broadcast address when the address is an IPv4 address, and a network prefix length in the case of an IPv6 address.

The following example program lists all the network interfaces and their addresses on a machine:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.*;
import java.net.*;
import java.util.*;
import static java.lang.System.out;

public class ListNets
{
    public static void main(String args[]) throws SocketException {
        Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
        for (NetworkInterface netint : Collections.list(nets))
            displayInterfaceInformation(netint);
    }

    static void displayInterfaceInformation(NetworkInterface netint) throws SocketException {
        out.printf("Display name: %s\n", netint.getDisplayName());
        out.printf("Name: %s\n", netint.getName());
        Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();
        for (InetAddress inetAddress : Collections.list(inetAddresses)) {
            out.printf("InetAddress: %s\n", inetAddress);
        }
        out.printf("\n");
     }
}
The following is sample output from the example program:
Display name: bge0
Name: bge0
InetAddress: /fe80:0:0:0:203:baff:fef2:e99d%2
InetAddress: /121.153.225.59

Display name: lo0
Name: lo0
InetAddress: /0:0:0:0:0:0:0:1%1
InetAddress: /127.0.0.1
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Retrieving Network Interfaces
Next page: Network Interface Parameters


Network Interface Parameters (The Java™ Tutorials > Custom Networking > Programmatic Access to Network Parameters)

Trail: Custom Networking
Lesson: Programmatic Access to Network Parameters
Programmatic Access to Network Parameters
What Is a Network Interface?
Retrieving Network Interfaces
Listing Network Interface Addresses
Network Interface Parameters
Home Page > Custom Networking > Programmatic Access to Network Parameters
« Previous • Trail • Next »
Network Interface Parameters
You can access network parameters about a network interface beyond the name and IP addresses assigned to it

You can discover if a network interface is “up” (that is, running) with the isUP() method. The following methods indicate the network interface type:

  • isLoopback() indicates if the network interface is a loopback interface.
  • isPointToPoint() indicates if the interface is a point-to-point interface.
  • isVirtual() indicates if the interface is a virtual interface.

The supportsMulticast() method indicates whether the network interface supports multicasting. The getHardwareAddress() method returns the network interface's physical hardware address, usually called MAC address, when it is available. The getMTU() method returns the Maximum Transmission Unit (MTU), which is the largest packet size.

The following example expands on the example in Listing Network Interface Addresses by adding the additional network parameters described on this page:

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.io.*;
import java.net.*;
import java.util.*;
import static java.lang.System.out;

public class ListNetsEx
{
    public static void main(String args[]) throws SocketException {
        Enumeration<NetworkInterface> nets = NetworkInterface.getNetworkInterfaces();
        for (NetworkInterface netint : Collections.list(nets))
            displayInterfaceInformation(netint);
    }

    static void displayInterfaceInformation(NetworkInterface netint) throws SocketException {
        out.printf("Display name: %s\n", netint.getDisplayName());
        out.printf("Name: %s\n", netint.getName());
        Enumeration<InetAddress> inetAddresses = netint.getInetAddresses();

        for (InetAddress inetAddress : Collections.list(inetAddresses)) {
            out.printf("InetAddress: %s\n", inetAddress);
        }

        out.printf("Up? %s\n", netint.isUp());
        out.printf("Loopback? %s\n", netint.isLoopback());
        out.printf("PointToPoint? %s\n", netint.isPointToPoint());
        out.printf("Supports multicast? %s\n", netint.supportsMulticast());
        out.printf("Virtual? %s\n", netint.isVirtual());
        out.printf("Hardware address: %s\n",
                    Arrays.toString(netint.getHardwareAddress()));
        out.printf("MTU: %s\n", netint.getMTU());

        out.printf("\n");

     }
}
The following is sample output from the example program:
Display name: bge0
Name: bge0
InetAddress: /fe80:0:0:0:203:baff:fef2:e99d%2
InetAddress: /129.156.225.59
Up? true
Loopback? false
PointToPoint? false
Supports multicast? false
Virtual? false
Hardware address: [0, 3, 4, 5, 6, 7]
MTU: 1500

Display name: lo0
Name: lo0
InetAddress: /0:0:0:0:0:0:0:1%1
InetAddress: /127.0.0.1
Up? true
Loopback? true
PointToPoint? false
Supports multicast? false
Virtual? false
Hardware address: null
MTU: 8232
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Listing Network Interface Addresses
Next page: Working With Cookies


Lesson: Working With Cookies (The Java™ Tutorials > Custom Networking)

Working With Cookies
HTTP State Management With Cookies
CookieHandler Callback Mechanism
Default CookieManager
Custom CookieManager
Trail: Custom Networking
Home Page > Custom Networking
« Previous • Trail • Next »
Lesson: Working With Cookies
Though you are probably already familiar with cookies, you might not know how to take advantage of them in your Java application. This lesson guides you through the concept of cookies and explains how to set a cookie handler so that your HTTP URL connections will use it.

Java SE provides one main class for this functionality, java.net.CookieHandler, and the following supporting classes and interfaces: java.net.CookieManager, java.net.CookiePolicy, java.net.CookieStore, and java.net.HttpCookie.

HTTP State Management With Cookies

This page describes cookies and explains how they are used to provide sessions.

CookieHandler Callback Mechanism

This page explains how a cookie handler is called when you access a web site and how to set a cookie handler.

Default CookieManager

Java SE provides a default cookie handler implementation that is sufficient in most cases and highly customizable.

Custom CookieManager

Here are some examples of how to customize the cookie policy and write your own cookie store.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: HTTP State Management With Cookies


HTTP State Management With Cookies (The Java™ Tutorials > Custom Networking > Working With Cookies)

Trail: Custom Networking
Lesson: Working With Cookies
Working With Cookies
HTTP State Management With Cookies
CookieHandler Callback Mechanism
Default CookieManager
Custom CookieManager
Home Page > Custom Networking > Working With Cookies
« Previous • Trail • Next »
HTTP State Management With Cookies
The HTTP state management mechanism specifies a way to create a stateful session with HTTP requests and responses.

Generally, HTTP request/response pairs are independent of each other. However, the state management mechanism enables clients and servers that can exchange state information to put these pairs in a larger context, which is called a session. The state information used to create and maintain the session is called a cookie.

A cookie is a piece of data that can be stored in a browser's cache. If you visit a web site and then revisit it, the cookie data can be used to identify you as a return visitor. Cookies enable state information, such as an online shopping cart, to be remembered. A cookie can be short term, holding data for a single web session, that is, until you close the browser, or a cookie can be longer term, holding data for a week or a year.

For more information about HTTP state management, see RFC 2965: HTTP State Management Mechanism.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Working With Cookies
Next page: CookieHandler Callback Mechanism


CookieHandler Callback Mechanism (The Java™ Tutorials > Custom Networking > Working With Cookies)

Trail: Custom Networking
Lesson: Working With Cookies
Working With Cookies
HTTP State Management With Cookies
CookieHandler Callback Mechanism
Default CookieManager
Custom CookieManager
Home Page > Custom Networking > Working With Cookies
« Previous • Trail • Next »
CookieHandler Callback Mechanism
HTTP state management is implemented in Java SE through the java.net.CookieHandler class. A CookieHandler object provides a callback mechanism to provide an HTTP state management policy implementation in the HTTP protocol handler. That is, URLs that use HTTP as the protocol, new URL("http://java.sun.com") for example, will use the HTTP protocol handler. This protocol handler calls back to the CookieHander object, if set, to handle the state management.

The CookieHandler class is an abstract class that has two pairs of related methods. The first pair, getDefault() and setDefault(cookieHandler), are static methods that enable you to discover the current handler that is installed and to install your own handler.

No default handler is installed, and installing a handler is done on a system-wide basis. For applications running within a secure environment, that is, they have a security manager installed, you must have special permission to get and set the handler. For more information, see java.net.CookieHandler.getDefault.

The second pair of related methods, put(uri, responseHeaders) and get(uri, requestHeaders), enable you to set and get all the applicable cookies to and from a cookie cache for the specified URI in the response/request headers, respectively. These methods are abstract, and a concrete implementation of a CookieHandler must provide the implementation.

Java Web Start and Java Plug-in have a default CookieHandler installed. However, if you are running a stand-alone application and want to enable HTTP state management, you must set a system-wide handler. The next two pages in this lesson show you how to do so.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: HTTP State Management With Cookies
Next page: Default CookieManager


Default CookieManager (The Java™ Tutorials > Custom Networking > Working With Cookies)

Trail: Custom Networking
Lesson: Working With Cookies
Working With Cookies
HTTP State Management With Cookies
CookieHandler Callback Mechanism
Default CookieManager
Custom CookieManager
Home Page > Custom Networking > Working With Cookies
« Previous • Trail • Next »
Default CookieManager
java.net.CookieManager provides a concrete implementation of a CookieHandler and for most users is sufficient for handling HTTP state management. CookieManager separates the storage of cookies from the policy surrounding, accepting, and rejecting them. A CookieManager is initialized with a java.net.CookieStore and a java.net.CookiePolicy. CookieStore manages the storage of the cookies. CookiePolicy makes policy decisions on cookie acceptance and rejection.

The following code shows how to create and set a system-wide CookieManager:

  java.net.CookieManager cm = new java.net.CookieManager();
  java.net.CookieHandler.setDefault(cm);
The first line calls the default CookieManager constructor to create the instance. The second line calls the static setDefault method of CookieHander to set the system-wide handler.

The default CookieManager constructor creates a new CookieManager instance with a default cookie store and accept policy. CookieStore is the place where any accepted HTTP cookie is stored. If not specified when created, a CookieManager instance will use an internal in-memory implementation. This implementation is not persistent and only lives for the lifetime of the Java Virtual Machine. Users requiring a persistent store must implement their own store.

The default cookie policy used by CookieManager is CookiePolicy.ACCEPT_ORIGINAL_SERVER, which only accepts cookies from the original server. So, the Set-Cookie response from the server must have a “domain” attribute set, and it must match the domain of the host in the URL. For more information, see java.net.HttpCookie.domainMatches. Users requiring a different policy must implement the CookiePolicy interface and pass it to the CookieManager constructor or set it to an already constructed CookieManager instance by using the setCookiePolicy(cookiePolicy) method.

When retrieving cookies from the cookie store, CookieManager also enforces the path-match rule from section 3.3.4 of RFC 2965. So, a cookie must also have its “path” attribute set so that the path-match rule can be applied before the cookie is retrieved from the cookie store.

In summary, CookieManager provides the framework for handling cookies and provides a good default implementation for CookieStore. CookieManager is highly customizable by enabling you to set your own CookieStore, CookiePolicy, or both.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: CookieHandler Callback Mechanism
Next page: Custom CookieManager


Custom CookieManager (The Java™ Tutorials > Custom Networking > Working With Cookies)

Trail: Custom Networking
Lesson: Working With Cookies
Working With Cookies
HTTP State Management With Cookies
CookieHandler Callback Mechanism
Default CookieManager
Custom CookieManager
Home Page > Custom Networking > Working With Cookies
« Previous • Trail • Next »
Custom CookieManager
Two aspects of the CookieManager class can be customized, the CookiePolicy and the CookieStore.

CookiePolicy

For convenience, CookiePolicy defines the following pre-defined policies for accepting cookies:
  • CookiePolicy.ACCEPT_ORIGINAL_SERVER only accepts cookies from the original server.
  • CookiePolicy.ACCEPT_ALL accepts all cookies.
  • CookiePolicy.ACCEPT_NONE accepts no cookies. You can also define your own cookie policy by implementing the shouldAccept method of CookiePolicy. You can then use this CookiePolicy by passing it to the multi-argument CookieManager constructor or by calling the setCookiePolicy(cookiePolicy) method to change an already existing cookie manager.

    The following is an example of a cookie policy that rejects cookies from domains that are on a blacklist, before applying the CookiePolicy.ACCEPT_ORIGINAL_SERVER policy:

    /*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.net.*;

public class BlacklistCookiePolicy implements CookiePolicy
{
    String[] blacklist;

    public BlacklistCookiePolicy(String[] list) {
        blacklist = list;
    }

    public boolean shouldAccept(URI uri, HttpCookie cookie)  {
        String host;
        try {
            host =  InetAddress.getByName(uri.getHost()).getCanonicalHostName();
        } catch (UnknownHostException e) {
            host = uri.getHost();
        }

        for (int i=0; i<blacklist.length; i++) {
        if (HttpCookie.domainMatches(blacklist[i], host)) {
                return false;
            }
        }

        return CookiePolicy.ACCEPT_ORIGINAL_SERVER.shouldAccept(uri, cookie);
    }
}
    When you create a BlacklistCookiePolicy instance, you pass it an array of strings representing the domains that you do not want to accept cookies from. Then, you set this BlacklistCookiePolicy instance as the cookie policy for your CookieManager. For example:
    String[] list = new String[] { ".bar.com" };
CookieManager cm = new CookieManager(null, new BlacklistCookiePolicy(list));
CookieHandler.setDefault(cm);
    The sample code will not accept cookies from hosts such as the following:
    foo.bar.com
goo.bar.com
    However, this sample code will accept cookies from hosts such as the following:
    y.com
bar.com
x.foo.bar.com

CookieStore

A CookieStore is an interface that represents a storage area for cookies. CookieManager adds the cookies to the CookieStore for every HTTP response and retrieves cookies from the CookieStore for every HTTP request.

You can implement this interface to provide your own CookieStore and pass it to the CookieManager during creation. You cannot set the CookieStore after the CookieManager instance has been created. However, you can get a reference to the cookie store by calling CookieManager.getCookieStore(). Doing so can be useful as it enables you to leverage the default in-memory CookieStore implementation that is provided by Java SE and complement its functionality.

For example, you might want to create a persistent cookie store that would save cookies so that they can be used even if the Java Virtual Machine is restarted. Your implementation would work similar to the following:

  1. Any cookies that were previously saved are read in.
  2. During runtime, cookies are stored and retrieved from memory.
  3. Cookies are written out to persistent storage before exiting.
The following is an incomplete example of this cookie store. This example shows you how to leverage the Java SE default in-memory cookie store and how you might extend its functionality.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.net.*;
import java.util.*;

public class PersistentCookieStore
   implements CookieStore, Runnable
{
    CookieStore store;

    public PersistentCookieStore() {
        // get the default in memory cookie store
        store = new CookieManager().getCookieStore();

        // todo: read in cookies from persistant storage
        // and add them store

        // add a shutdown hook to write out the in memory cookies
        Runtime.getRuntime().addShutdownHook(new Thread(this));
    }

    public void run() {
        // todo: write cookies in store to persistent storage
    }

    public void	add(URI uri, HttpCookie cookie) {
        store.add(uri, cookie);
    }

    public List<HttpCookie> get(URI uri) {
        return store.get(uri);
    }

    public List<HttpCookie> getCookies() {
        return store.getCookies();
    }

    public List<URI> getURIs() {
        return store.getURIs();
    }

    public boolean remove(URI uri, HttpCookie cookie) {
        return store.remove(uri, cookie);
    }

    public boolean removeAll()  {
        return store.removeAll();
    }
}
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Default CookieManager
Next page: End of Trail


Trail: Bonus (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Bonus
Generics, introduced in J2SE 5.0, is the long-awaited enhancement to the type system. It allows a type or method to operate on objects of various types while providing compile-time type safety. It adds compile-time type safety to the Collections Framework and eliminates the drudgery of casting.

Full-Screen Exclusive Mode API teaches you about a powerful feature of J2SETM version 1.4 that allows the programmer to suspend the windowing system so that drawing can be done directly to the screen. Programmers writing games or other graphic-intensive applications should read this lesson.

Preparation for Java Programmer Language Certification provides information on training resources and lists the portions of the tutorial that cover potential exam topics.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Generics


Lesson: Generics (The Java™ Tutorials > Bonus)

Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Trail: Bonus
Home Page > Bonus
« Previous • Trail • Next »
Lesson: Generics

by Gilad Bracha

Note: This lesson covers a language feature introduced in the latest release of the JavaTM 2 Platform Standard Edition version 5.0. Visit the J2SE 5.0 download page.
Introduced in J2SE 5.0, this long-awaited enhancement to the type system allows a type or method to operate on objects of various types while providing compile-time type safety. It adds compile-time type safety to the Collections Framework and eliminates the drudgery of casting.
Introduction

Defining Simple Generics

Generics and Subtyping

Wildcards

Generic Methods

Interoperating with Legacy Code

The Fine Print

Class Literals as Runtime-Type Tokens

More Fun with Wildcards

Converting Legacy Code to Use Generics

Acknowledgements

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: Introduction


Introduction (The Java™ Tutorials > Bonus > Generics)

Trail: Bonus
Lesson: Generics
Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Home Page > Bonus > Generics
« Previous • Trail • Next »
Introduction
JDK 5.0 introduces several new extensions to the Java programming language. One of these is the introduction of generics.

This trail is an introduction to generics. You may be familiar with similar constructs from other languages, most notably C++ templates. If so, you'll see that there are both similarities and important differences. If you are unfamiliar with look-a-alike constructs from elsewhere, all the better; you can start fresh, without having to unlearn any misconceptions.

Generics allow you to abstract over types. The most common examples are container types, such as those in the Collections hierarchy.

Here is a typical usage of that sort:

List myIntList = new LinkedList(); // 1
myIntList.add(new Integer(0)); // 2
Integer x = (Integer) myIntList.iterator().next();  // 3
The cast on line 3 is slightly annoying. Typically, the programmer knows what kind of data has been placed into a particular list. However, the cast is essential. The compiler can only guarantee that an Object will be returned by the iterator. To ensure the assignment to a variable of type Integer is type safe, the cast is required.

Of course, the cast not only introduces clutter. It also introduces the possibility of a run time error, since the programmer may be mistaken.

What if programmers could actually express their intent, and mark a list as being restricted to contain a particular data type? This is the core idea behind generics. Here is a version of the program fragment given above using generics:

List<Integer> myIntList = new LinkedList<Integer>(); // 1'
myIntList.add(new Integer(0)); // 2'
Integer x = myIntList.iterator().next(); // 3'
Notice the type declaration for the variable myIntList. It specifies that this is not just an arbitrary List, but a List of Integer, written List<Integer>. We say that List is a generic interface that takes a type parameter--in this case, Integer. We also specify a type parameter when creating the list object.

Note, too, that the cast on line 3' is gone.

Now, you might think that all we've accomplished is to move the clutter around. Instead of a cast to Integer on line 3, we have Integer as a type parameter on line 1'. However, there is a very big difference here. The compiler can now check the type correctness of the program at compile-time. When we say that myIntList is declared with type List<Integer>, this tells us something about the variable myIntList, which holds true wherever and whenever it is used, and the compiler will guarantee it. In contrast, the cast tells us something the programmer thinks is true at a single point in the code.

The net effect, especially in large programs, is improved readability and robustness.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Generics
Next page: Defining Simple Generics


Defining Simple Generics (The Java™ Tutorials > Bonus > Generics)

Trail: Bonus
Lesson: Generics
Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Home Page > Bonus > Generics
« Previous • Trail • Next »
Defining Simple Generics
Here is a small excerpt from the definitions of the interfaces List and Iterator in package java.util:
public interface List <E>{
    void add(E x);
    Iterator<E> iterator();
}

public interface Iterator<E>{
    E next();
    boolean hasNext();
}
This code should all be familiar, except for the stuff in angle brackets. Those are the declarations of the formal type parameters of the interfaces List and Iterator.

Type parameters can be used throughout the generic declaration, pretty much where you would use ordinary types (though there are some important restrictions; see the section The Fine Print.

In the introduction, we saw invocations of the generic type declaration List, such as List<Integer>. In the invocation (usually called a parameterized type), all occurrences of the formal type parameter (E in this case) are replaced by the actual type argument (in this case, Integer).

You might imagine that List<Integer> stands for a version of List where E has been uniformly replaced by Integer:

public interface IntegerList {
    void add(Integer x);
    Iterator<Integer> iterator();
}
This intuition can be helpful, but it's also misleading.

It is helpful, because the parameterized type List<Integer> does indeed have methods that look just like this expansion.

It is misleading, because the declaration of a generic is never actually expanded in this way. There aren't multiple copies of the code--not in source, not in binary, not on disk and not in memory. If you are a C++ programmer, you'll understand that this is very different than a C++ template.

A generic type declaration is compiled once and for all, and turned into a single class file, just like an ordinary class or interface declaration.

Type parameters are analogous to the ordinary parameters used in methods or constructors. Much like a method has formal value parameters that describe the kinds of values it operates on, a generic declaration has formal type parameters. When a method is invoked, actual arguments are substituted for the formal parameters, and the method body is evaluated. When a generic declaration is invoked, the actual type arguments are substituted for the formal type parameters.

A note on naming conventions. We recommend that you use pithy (single character if possible) yet evocative names for formal type parameters. It's best to avoid lower case characters in those names, making it easy to distinguish formal type parameters from ordinary classes and interfaces. Many container types use E, for element, as in the examples above. We'll see some additional conventions in later examples.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Introduction
Next page: Generics and Subtyping


Generics and Subtyping (The Java™ Tutorials > Bonus > Generics)

Trail: Bonus
Lesson: Generics
Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Home Page > Bonus > Generics
« Previous • Trail • Next »
Generics and Subtyping
Let's test your understanding of generics. Is the following code snippet legal?
List<String> ls = new ArrayList<String>(); // 1
List<Object> lo = ls; // 2
Line 1 is certainly legal. The trickier part of the question is line 2. This boils down to the question: is a List of String a List of Object. Most people instinctively answer, "Sure!"

Well, take a look at the next few lines:

lo.add(new Object()); // 3
String s = ls.get(0); // 4: Attempts to assign an Object to a String!
Here we've aliased ls and lo. Accessing ls, a list of String, through the alias lo, we can insert arbitrary objects into it. As a result ls does not hold just Strings anymore, and when we try and get something out of it, we get a rude surprise.

The Java compiler will prevent this from happening of course. Line 2 will cause a compile time error.

In general, if Foo is a subtype (subclass or subinterface) of Bar, and G is some generic type declaration, it is not the case that G<Foo> is a subtype of G<Bar>. This is probably the hardest thing you need to learn about generics, because it goes against our deeply held intuitions.

We should not assume that collections don't change. Our instinct may lead us to think of these things as immutable.

For example, if the department of motor vehicles supplies a list of drivers to the census bureau, this seems reasonable. We think that a List<Driver> is a List<Person>, assuming that Driver is a subtype of Person. In fact, what is being passed is a copy of the registry of drivers. Otherwise, the census bureau could add new people who are not drivers into the list, corrupting the DMV's records.

To cope with this sort of situation, it's useful to consider more flexible generic types. The rules we've seen so far are quite restrictive.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Defining Simple Generics
Next page: Wildcards


Wildcards (The Java™ Tutorials > Bonus > Generics)

Trail: Bonus
Lesson: Generics
Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Home Page > Bonus > Generics
« Previous • Trail • Next »
Wildcards
Consider the problem of writing a routine that prints out all the elements in a collection. Here's how you might write it in an older version of the language (i.e., a pre-5.0 release):
void printCollection(Collection c) {
    Iterator i = c.iterator();
    for (k = 0; k < c.size(); k++) {
        System.out.println(i.next());
    }
}
And here is a naive attempt at writing it using generics (and the new for loop syntax):
void printCollection(Collection<Object> c) {
    for (Object e : c) {
        System.out.println(e);
    }
}
The problem is that this new version is much less useful than the old one. Whereas the old code could be called with any kind of collection as a parameter, the new code only takes Collection<Object>, which, as we've just demonstrated, is not a supertype of all kinds of collections!

So what is the supertype of all kinds of collections? It's written Collection<?> (pronounced "collection of unknown"), that is, a collection whose element type matches anything. It's called a wildcard type for obvious reasons. We can write:

void printCollection(Collection<?> c) {
    for (Object e : c) {
        System.out.println(e);
    }
}
and now, we can call it with any type of collection. Notice that inside printCollection(), we can still read elements from c and give them type Object. This is always safe, since whatever the actual type of the collection, it does contain objects. It isn't safe to add arbitrary objects to it however:
Collection<?> c = new ArrayList<String>();
c.add(new Object()); // Compile time error
Since we don't know what the element type of c stands for, we cannot add objects to it. The add() method takes arguments of type E, the element type of the collection. When the actual type parameter is ?, it stands for some unknown type. Any parameter we pass to add would have to be a subtype of this unknown type. Since we don't know what type that is, we cannot pass anything in. The sole exception is null, which is a member of every type.

On the other hand, given a List<?>, we can call get() and make use of the result. The result type is an unknown type, but we always know that it is an object. It is therefore safe to assign the result of get() to a variable of type Object or pass it as a parameter where the type Object is expected.

Bounded Wildcards

Consider a simple drawing application that can draw shapes such as rectangles and circles. To represent these shapes within the program, you could define a class hierarchy such as this:
public abstract class Shape {
    public abstract void draw(Canvas c);
}

public class Circle extends Shape {
    private int x, y, radius;
    public void draw(Canvas c) {
        ...
    }
}

public class Rectangle extends Shape {
    private int x, y, width, height;
    public void draw(Canvas c) {
        ...
    }
}
These classes can be drawn on a canvas:
public class Canvas {
    public void draw(Shape s) {
        s.draw(this);
   }
}
Any drawing will typically contain a number of shapes. Assuming that they are represented as a list, it would be convenient to have a method in Canvas that draws them all:
public void drawAll(List<Shape> shapes) {
    for (Shape s: shapes) {
        s.draw(this);
   }
}
Now, the type rules say that drawAll() can only be called on lists of exactly Shape: it cannot, for instance, be called on a List<Circle>. That is unfortunate, since all the method does is read shapes from the list, so it could just as well be called on a List<Circle>. What we really want is for the method to accept a list of any kind of shape:
public void drawAll(List<? extends Shape> shapes) {
    ...
}
There is a small but very important difference here: we have replaced the type List<Shape> with List<? extends Shape>. Now drawAll() will accept lists of any subclass of Shape, so we can now call it on a List<Circle> if we want.

List<? extends Shape> is an example of a bounded wildcard. The ? stands for an unknown type, just like the wildcards we saw earlier. However, in this case, we know that this unknown type is in fact a subtype of Shape. (Note: It could be Shape itself, or some subclass; it need not literally extend Shape.) We say that Shape is the upper bound of the wildcard.

There is, as usual, a price to be paid for the flexibility of using wildcards. That price is that it is now illegal to write into shapes in the body of the method. For instance, this is not allowed:

public void addRectangle(List<? extends Shape> shapes) {
    shapes.add(0, new Rectangle()); // Compile-time error!
}
You should be able to figure out why the code above is disallowed. The type of the second parameter to shapes.add() is ? extends Shape-- an unknown subtype of Shape. Since we don't know what type it is, we don't know if it is a supertype of Rectangle; it might or might not be such a supertype, so it isn't safe to pass a Rectangle there.

Bounded wildcards are just what one needs to handle the example of the DMV passing its data to the census bureau. Our example assumes that the data is represented by mapping from names (represented as strings) to people (represented by reference types such as Person or its subtypes, such as Driver). Map<K,V> is an example of a generic type that takes two type arguments, representing the keys and values of the map.

Again, note the naming convention for formal type parameters--K for keys and V for values.

public class Census {
    public static void addRegistry(Map<String, ? extends Person> registry) {
}
...

Map<String, Driver> allDrivers = ... ;
Census.addRegistry(allDrivers);
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Generics and Subtyping
Next page: Generic Methods


Generic Methods (The Java™ Tutorials > Bonus > Generics)

Trail: Bonus
Lesson: Generics
Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Home Page > Bonus > Generics
« Previous • Trail • Next »
Generic Methods
Consider writing a method that takes an array of objects and a collection and puts all objects in the array into the collection. Here's a first attempt:
static void fromArrayToCollection(Object[] a, Collection<?> c) {
    for (Object o : a) {
        c.add(o); // Compile time error
    }
}
By now, you will have learned to avoid the beginner's mistake of trying to use Collection<Object> as the type of the collection parameter. You may or may not have recognized that using Collection<?> isn't going to work either. Recall that you cannot just shove objects into a collection of unknown type.

The way to do deal with these problems is to use generic methods. Just like type declarations, method declarations can be generic--that is, parameterized by one or more type parameters.

static <T> void fromArrayToCollection(T[] a, Collection<T> c) {
    for (T o : a) {
        c.add(o); // Correct
    }
}
We can call this method with any kind of collection whose element type is a supertype of the element type of the array.
Object[] oa = new Object[100];
Collection<Object> co = new ArrayList<Object>();
fromArrayToCollection(oa, co); // T inferred to be Object

String[] sa = new String[100];
Collection<String> cs = new ArrayList<String>();
fromArrayToCollection(sa, cs); // T inferred to be String
fromArrayToCollection(sa, co); // T inferred to be Object

Integer[] ia = new Integer[100];
Float[] fa = new Float[100];
Number[] na = new Number[100];
Collection<Number> cn = new ArrayList<Number>();
fromArrayToCollection(ia, cn); // T inferred to be Number
fromArrayToCollection(fa, cn); // T inferred to be Number
fromArrayToCollection(na, cn); // T inferred to be Number
fromArrayToCollection(na, co); // T inferred to be Object

fromArrayToCollection(na, cs); // compile-time error
Notice that we don't have to pass an actual type argument to a generic method. The compiler infers the type argument for us, based on the types of the actual arguments. It will generally infer the most specific type argument that will make the call type-correct.

One question that arises is: when should I use generic methods, and when should I use wildcard types? To understand the answer, let's examine a few methods from the Collection libraries.

interface Collection<E> {
    public boolean containsAll(Collection<?> c);
    public boolean addAll(Collection<? extends E> c);
}
We could have used generic methods here instead:
interface Collection<E> {
    public <T> boolean containsAll(Collection<T> c);
    public <T extends E> boolean addAll(Collection<T> c);
    // Hey, type variables can have bounds too!
}
However, in both containsAll and addAll, the type parameter T is used only once. The return type doesn't depend on the type parameter, nor does any other argument to the method (in this case, there simply is only one argument). This tells us that the type argument is being used for polymorphism; its only effect is to allow a variety of actual argument types to be used at different invocation sites. If that is the case, one should use wildcards. Wildcards are designed to support flexible subtyping, which is what we're trying to express here.

Generic methods allow type parameters to be used to express dependencies among the types of one or more arguments to a method and/or its return type. If there isn't such a dependency, a generic method should not be used.

It is possible to use both generic methods and wildcards in tandem. Here is the method Collections.copy():

class Collections {
    public static <T> void copy(List<T> dest, List<? extends T> src) {
    ...
}
Note the dependency between the types of the two parameters. Any object copied from the source list, src, must be assignable to the element type T of the destination list, dst. So the element type of src can be any subtype of T--we don't care which. The signature of copy expresses the dependency using a type parameter, but uses a wildcard for the element type of the second parameter.

We could have written the signature for this method another way, without using wildcards at all:

class Collections {
    public static <T, S extends T>
           void copy(List<T> dest, List<S> src) {
    ...
}
This is fine, but while the first type parameter is used both in the type of dst and in the bound of the second type parameter, S, S itself is only used once, in the type of src--nothing else depends on it. This is a sign that we can replace S with a wildcard. Using wildcards is clearer and more concise than declaring explicit type parameters, and should therefore be preferred whenever possible.

Wildcards also have the advantage that they can be used outside of method signatures, as the types of fields, local variables and arrays. Here is an example.

Returning to our shape drawing problem, suppose we want to keep a history of drawing requests. We can maintain the history in a static variable inside class Shape, and have drawAll() store its incoming argument into the history field.

static List<List<? extends Shape>> history =
            new ArrayList<List<? extends Shape>>();
public void drawAll(List<? extends Shape> shapes) {
    history.addLast(shapes);
    for (Shape s: shapes) {
        s.draw(this);
    }
}
Finally, again let's take note of the naming convention used for the type parameters. We use T for type, whenever there isn't anything more specific about the type to distinguish it. This is often the case in generic methods. If there are multiple type parameters, we might use letters that neighbor T in the alphabet, such as S. If a generic method appears inside a generic class, it's a good idea to avoid using the same names for the type parameters of the method and class, to avoid confusion. The same applies to nested generic classes.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Wildcards
Next page: Interoperating with Legacy Code


Interoperating with Legacy Code (The Java™ Tutorials > Bonus > Generics)

Trail: Bonus
Lesson: Generics
Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Home Page > Bonus > Generics
« Previous • Trail • Next »
Interoperating with Legacy Code
Until now, all our examples have assumed an idealized world, where everyone is using the latest version of the Java programming language, which supports generics.

Alas, in reality this isn't the case. Millions of lines of code have been written in earlier versions of the language, and they won't all be converted overnight.

Later, in the Converting Legacy Code to Use Genericssection, we will tackle the problem of converting your old code to use generics. In this section, we'll focus on a simpler problem: how can legacy code and generic code interoperate? This question has two parts: using legacy code from within generic code and using generic code within legacy code.

Using Legacy Code in Generic Code

How can you use old code, while still enjoying the benefits of generics in your own code?

As an example, assume you want to use the package com.Fooblibar.widgets. The folks at Fooblibar.com* market a system for inventory control, highlights of which are shown below:

package com.Fooblibar.widgets;

public interface Part { ...}

public class Inventory {
/**
 * Adds a new Assembly to the inventory database.
 * The assembly is given the name name, and consists of a set
 * parts specified by parts. All elements of the collection parts
 * must support the Part interface.
**/
    public static void addAssembly(String name, Collection parts) {...}
    public static Assembly getAssembly(String name) {...}
}

public interface Assembly {
    Collection getParts(); // Returns a collection of Parts
}
Now, you'd like to add new code that uses the API above. It would be nice to ensure that you always called addAssembly() with the proper arguments - that is, that the collection you pass in is indeed a Collection of Part. Of course, generics are tailor made for this:
package com.mycompany.inventory;

import com.Fooblibar.widgets.*;

public class Blade implements Part {
    ...
}

public class Guillotine implements Part {
}

public class Main {
    public static void main(String[] args) {
        Collection<Part> c = new ArrayList<Part>();
        c.add(new Guillotine()) ;
        c.add(new Blade());
        Inventory.addAssembly("thingee", c);
        Collection<Part> k = Inventory.getAssembly("thingee").getParts();
    }
}
When we call addAssembly, it expects the second parameter to be of type Collection. The actual argument is of type Collection<Part>. This works, but why? After all, most collections don't contain Part objects, and so in general, the compiler has no way of knowing what kind of collection the type Collection refers to.

In proper generic code, Collection would always be accompanied by a type parameter. When a generic type like Collection is used without a type parameter, it's called a raw type.

Most people's first instinct is that Collection really means Collection<Object>. However, as we saw earlier, it isn't safe to pass a Collection<Part> in a place where a Collection<Object> is required. It's more accurate to say that the type Collection denotes a collection of some unknown type, just like Collection<?>.

But wait, that can't be right either! Consider the call to getParts(), which returns a Collection. This is then assigned to k, which is a Collection<Part>. If the result of the call is a Collection<?>, the assignment would be an error.

In reality, the assignment is legal, but it generates an unchecked warning. The warning is needed, because the fact is that the compiler can't guarantee its correctness. We have no way of checking the legacy code in getAssembly() to ensure that indeed the collection being returned is a collection of Parts. The type used in the code is Collection, and one could legally insert all kinds of objects into such a collection.

So, shouldn't this be an error? Theoretically speaking, yes; but practically speaking, if generic code is going to call legacy code, this has to be allowed. It's up to you, the programmer, to satisfy yourself that in this case, the assignment is safe because the contract of getAssembly() says it returns a collection of Parts, even though the type signature doesn't show this.

So raw types are very much like wildcard types, but they are not typechecked as stringently. This is a deliberate design decision, to allow generics to interoperate with pre-existing legacy code.

Calling legacy code from generic code is inherently dangerous; once you mix generic code with non-generic legacy code, all the safety guarantees that the generic type system usually provides are void. However, you are still better off than you were without using generics at all. At least you know the code on your end is consistent.

At the moment there's a lot more non-generic code out there then there is generic code, and there will inevitably be situations where they have to mix.

If you find that you must intermix legacy and generic code, pay close attention to the unchecked warnings. Think carefully how you can justify the safety of the code that gives rise to the warning.

What happens if you still made a mistake, and the code that caused a warning is indeed not type safe? Let's take a look at such a situation. In the process, we'll get some insight into the workings of the compiler.

Erasure and Translation

public String loophole(Integer x) {
    List<String> ys = new LinkedList<String>();
    List xs = ys;
    xs.add(x); // Compile-time unchecked warning
    return ys.iterator().next();
}
Here, we've aliased a list of strings and a plain old list. We insert an Integer into the list, and attempt to extract a String. This is clearly wrong. If we ignore the warning and try to execute this code, it will fail exactly at the point where we try to use the wrong type. At run time, this code behaves like:
public String loophole(Integer x) {
    List ys = new LinkedList;
    List xs = ys;
    xs.add(x);
    return(String) ys.iterator().next(); // run time error
}
When we extract an element from the list, and attempt to treat it as a string by casting it to String, we will get a ClassCastException. The exact same thing happens with the generic version of loophole().

The reason for this is, that generics are implemented by the Java compiler as a front-end conversion called erasure. You can (almost) think of it as a source-to-source translation, whereby the generic version of loophole() is converted to the non-generic version.

As a result, the type safety and integrity of the Java virtual machine are never at risk, even in the presence of unchecked warnings.

Basically, erasure gets rid of (or erases) all generic type information. All the type information betweeen angle brackets is thrown out, so, for example, a parameterized type like List<String> is converted into List. All remaining uses of type variables are replaced by the upper bound of the type variable (usually Object). And, whenever the resulting code isn't type-correct, a cast to the appropriate type is inserted, as in the last line of loophole.

The full details of erasure are beyond the scope of this tutorial, but the simple description we just gave isn't far from the truth. It's good to know a bit about this, especially if you want to do more sophisticated things like converting existing APIs to use generics (see the Converting Legacy Code to Use Genericssection), or just want to understand why things are the way they are.

Using Generic Code in Legacy Code

Now let's consider the inverse case. Imagine that Fooblibar.com chose to convert their API to use generics, but that some of their clients haven't yet. So now the code looks like:
package com.Fooblibar.widgets;

public interface Part {
    ...
}

public class Inventory {
/**
 * Adds a new Assembly to the inventory database.
 * The assembly is given the name name, and consists of a set
 * parts specified by parts. All elements of the collection parts
 * must support the Part interface.
**/
    public static void addAssembly(String name, Collection<Part> parts) {...}
    public static Assembly getAssembly(String name) {...}
}

public interface Assembly {
    Collection<Part> getParts(); // Returns a collection of Parts
}
and the client code looks like:
package com.mycompany.inventory;

import com.Fooblibar.widgets.*;

public class Blade implements Part {
...
}

public class Guillotine implements Part {
}

public class Main {
    public static void main(String[] args) {
        Collection c = new ArrayList();
        c.add(new Guillotine()) ;
        c.add(new Blade());
        Inventory.addAssembly("thingee", c); // 1: unchecked warning}
        Collection k = Inventory.getAssembly("thingee").getParts();
    }
}
The client code was written before generics were introduced, but it uses the package com.Fooblibar.widgets and the collection library, both of which are using generic types. All the uses of generic type declarations in the client code are raw types.

Line 1 generates an unchecked warning, because a raw Collection is being passed in where a Collection of Parts is expected, and the compiler cannot ensure that the raw Collection really is a Collection of Parts.

As an alternative, you can compile the client code using the source 1.4 flag, ensuring that no warnings are generated. However, in that case you won't be able to use any of the new language features introduced in JDK 5.0.

Note that "Fooblibar.com" is a purely fictional company used for illustration purposes only. Any relation to any real company or institution, or any persons living or dead, is purely coincidental.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Generic Methods
Next page: The Fine Print


The Fine Print (The Java™ Tutorials > Bonus > Generics)

Trail: Bonus
Lesson: Generics
Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Home Page > Bonus > Generics
« Previous • Trail • Next »
The Fine Print

A Generic Class is Shared by All Its Invocations

What does the following code fragment print?
List <String> l1 = new ArrayList<String>();
List<Integer> l2 = new ArrayList<Integer>();
System.out.println(l1.getClass() == l2.getClass());
You might be tempted to say false, but you'd be wrong. It prints true, because all instances of a generic class have the same run-time class, regardless of their actual type parameters.

Indeed, what makes a class generic is the fact that it has the same behavior for all of its possible type parameters; the same class can be viewed as having many different types.

As consequence, the static variables and methods of a class are also shared among all the instances. That is why it is illegal to refer to the type parameters of a type declaration in a static method or initializer, or in the declaration or initializer of a static variable.

Casts and InstanceOf

Another implication of the fact that a generic class is shared among all its instances, is that it usually makes no sense to ask an instance if it is an instance of a particular invocation of a generic type:
Collection cs = new ArrayList<String>();
if (cs instanceof Collection<String>) { ...} // Illegal.
similarly, a cast such as
Collection<String> cstr = (Collection<String>) cs; // Unchecked warning,
gives an unchecked warning, since this isn't something the runtime system is going to check for you.

The same is true of type variables

<T> T badCast(T t, Object o) {return (T) o; // Unchecked warning.
    }
Type variables don't exist at run time. This means that they entail no performance overhead in either time nor space, which is nice. Unfortunately, it also means that you can't reliably use them in casts.

Arrays

The component type of an array object may not be a type variable or a parameterized type, unless it is an (unbounded) wildcard type.You can declare array types whose element type is a type variable or a parameterized type, but not array objects.

This is annoying, to be sure. This restriction is necessary to avoid situations like:

List<String>[] lsa = new List<String>[10]; // Not really allowed.
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[1] = li; // Unsound, but passes run time store check
String s = lsa[1].get(0); // Run-time error: ClassCastException.
If arrays of parameterized type were allowed, the example above would compile without any unchecked warnings, and yet fail at run-time. We've had type-safety as a primary design goal of generics. In particular, the language is designed to guarantee that if your entire application has been compiled without unchecked warnings using javac -source 1.5, it is type safe.

However, you can still use wildcard arrays. Here are two variations on the code above. The first forgoes the use of both array objects and array types whose element type is parameterized. As a result, we have to cast explicitly to get a String out of the array.

List<?>[] lsa = new List<?>[10]; // OK, array of unbounded wildcard type.
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[1] = li; // Correct.
String s = (String) lsa[1].get(0); // Run time error, but cast is explicit.
In the next variation, we refrain from creating an array object whose element type is parameterized, but still use an array type with a parameterized element type. This is legal, but generates an unchecked warning. Indeed, the code is unsafe, and eventually an error occurs.
List<String>[] lsa = new List<?>[10]; // Unchecked warning. This is unsafe!
Object o = lsa;
Object[] oa = (Object[]) o;
List<Integer> li = new ArrayList<Integer>();
li.add(new Integer(3));
oa[1] = li; // Correct.
String s = lsa[1].get(0); // Run time error, but we were warned.
Similarly, attempting to create an array object whose element type is a type variable causes a compile-time error:
<T> T[] makeArray(T t) {
    return new T[100]; // Error.
}
Since type variables don't exist at run time, there is no way to determine what the actual array type would be.

The way to work around these kinds of limitations is to use class literals as run time type tokens, as described in the next section, Class Literals as Runtime-Type Tokens.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Interoperating with Legacy Code
Next page: Class Literals as Runtime-Type Tokens


Class Literals as Runtime-Type Tokens (The Java™ Tutorials > Bonus > Generics)

Trail: Bonus
Lesson: Generics
Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Home Page > Bonus > Generics
« Previous • Trail • Next »
Class Literals as Runtime-Type Tokens
One of the changes in JDK 5.0 is that the class java.lang.Class is generic. It's an interesting example of using genericity for something other than a container class.

Now that Class has a type parameter T, you might well ask, what does T stand for? It stands for the type that the Class object is representing.

For example, the type of String.class is Class<String>, and the type of Serializable.class is Class<Serializable>. This can be used to improve the type safety of your reflection code.

In particular, since the newInstance() method in Class now returns a T, you can get more precise types when creating objects reflectively.

For example, suppose you need to write a utility method that performs a database query, given as a string of SQL, and returns a collection of objects in the database that match that query.

One way is to pass in a factory object explicitly, writing code like:

interface Factory<T> { T make();}

public <T> Collection<T> select(Factory<T> factory, String statement) {
    Collection<T> result = new ArrayList<T>();
    /* Run sql query using jdbc */
    for (/* Iterate over jdbc results. */) {
        T item = factory.make();
        /* Use reflection and set all of item's fields from sql results. */
        result.add(item);
    }
    return result;
}
You can call this either as
select(new Factory<EmpInfo>(){ public EmpInfo make() {
                               return new EmpInfo();
                               }}
      , "selection string");
or you can declare a class EmpInfoFactory to support the Factory interface
class EmpInfoFactory implements Factory<EmpInfo> {
    ...
    public EmpInfo make() { return new EmpInfo();}
}
and call it
select(getMyEmpInfoFactory(), "selection string");
The downside of this solution is that it requires either:
  • the use of verbose anonymous factory classes at the call site, or
  • declaring a factory class for every type used and passing a factory instance at the call site, which is somewhat unnatural.
It is natural to use the class literal as a factory object, which can then be used by reflection. Today (without generics) the code might be written:
Collection emps = sqlUtility.select(EmpInfo.class, "select * from emps");
...
public static Collection select(Class c, String sqlStatement) {
    Collection result = new ArrayList();
    /* Run sql query using jdbc. */
    for (/* Iterate over jdbc results. */ ) {
        Object item = c.newInstance();
        /* Use reflection and set all of item's fields from sql results. */
        result.add(item);
    }
    return result;
}
However, this would not give us a collection of the precise type we desire. Now that Class is generic, we can instead write the following:
Collection<EmpInfo> emps =
                      sqlUtility.select(EmpInfo.class, "select * from emps");
...
public static <T> Collection<T> select(Class<T> c, String sqlStatement) {
    Collection<T> result = new ArrayList<T>();
    /* Run sql query using jdbc. */
    for (/* Iterate over jdbc results. */ ) {
        T item = c.newInstance();
        /* Use reflection and set all of item's fields from sql results. */
        result.add(item);
    }
    return result;
}
The above code gives us the precise type of collection in a type safe way.

This technique of using class literals as run time type tokens is a very useful trick to know. It's an idiom that's used extensively in the new APIs for manipulating annotations, for example.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: The Fine Print
Next page: More Fun with Wildcards


More Fun with Wildcards (The Java™ Tutorials > Bonus > Generics)

Trail: Bonus
Lesson: Generics
Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Home Page > Bonus > Generics
« Previous • Trail • Next »
More Fun with Wildcards
In this section, we'll consider some of the more advanced uses of wildcards. We've seen several examples where bounded wildcards were useful when reading from a data structure. Now consider the inverse, a write-only data structure. The interface Sink is a simple example of this sort.
interface Sink<T> {
    flush(T t);
}
We can imagine using it as demonstrated by the code below. The method writeAll() is designed to flush all elements of the collection coll to the sink snk, and return the last element flushed.
public static <T> T writeAll(Collection<T> coll, Sink<T> snk) {
    T last;
    for (T t : coll) {
        last = t;
        snk.flush(last);
    }
    return last;
}
...
Sink<Object> s;
Collection<String> cs;
String str = writeAll(cs, s); // Illegal call.
As written, the call to writeAll() is illegal, as no valid type argument can be inferred; neither String nor Object are appropriate types for T, because the Collection element and the Sink element must be of the same type.

We can fix this error by modifying the signature of writeAll() as shown below, using a wildcard.

public static <T> T writeAll(Collection<? extends T>, Sink<T>) {...}
...
String str = writeAll(cs, s); // Call is OK, but wrong return type.
The call is now legal, but the assignment is erroneous, since the return type inferred is Object because T matches the element type of s, which is Object.

The solution is to use a form of bounded wildcard we haven't seen yet: wildcards with a lower bound. The syntax ? super T denotes an unknown type that is a supertype of T (or T itself; remember that the supertype relation is reflexive). It is the dual of the bounded wildcards we've been using, where we use ? extends T to denote an unknown type that is a subtype of T.

public static <T> T writeAll(Collection<T> coll, Sink<? super T> snk) {
    ...
}
String str = writeAll(cs, s); // Yes!
Using this syntax, the call is legal, and the inferred type is String, as desired.

Now let's turn to a more realistic example. A java.util.TreeSet<E> represents a tree of elements of type E that are ordered. One way to construct a TreeSet is to pass a Comparator object to the constructor. That comparator will be used to sort the elements of the TreeSet according to a desired ordering.

TreeSet(Comparator<E> c)
The Comparator interface is essentially:
interface Comparator<T> {
    int compare(T fst, T snd);
}
Suppose we want to create a TreeSet<String> and pass in a suitable comparator, We need to pass it a Comparator that can compare Strings. This can be done by a Comparator<String>, but a Comparator<Object> will do just as well. However, we won't be able to invoke the constructor given above on a Comparator<Object>. We can use a lower bounded wildcard to get the flexibility we want:
TreeSet(Comparator<? super E> c)
This code allows any applicable comparator to be used.

As a final example of using lower bounded wildcards, lets look at the method Collections.max(), which returns the maximal element in a collection passed to it as an argument. Now, in order for max() to work, all elements of the collection being passed in must implement Comparable. Furthermore, they must all be comparable to each other.

A first attempt at generifying this method signature yields:

public static <T extends Comparable<T>>
        T max(Collection<T> coll)
That is, the method takes a collection of some type T that is comparable to itself, and returns an element of that type. However, this code turns out to be too restrictive. To see why, consider a type that is comparable to arbitrary objects:
class Foo implements Comparable<Object> {
    ...
}
Collection<Foo> cf = ... ;
Collections.max(cf); // Should work.
Every element of cf is comparable to every other element in cf, since every such element is a Foo, which is comparable to any object, and in particular to another Foo. However, using the signature above, we find that the call is rejected. The inferred type must be Foo, but Foo does not implement Comparable<Foo>.

It isn't necessary that T be comparable to exactly itself. All that's required is that T be comparable to one of its supertypes. This give us:

public static <T extends Comparable<? super T>>
        T max(Collection<T> coll)
Note that the actual signature of Collections.max() is more involved. We return to it in the next section, Converting Legacy Code to Use Generics. This reasoning applies to almost any usage of Comparable that is intended to work for arbitrary types: You always want to use Comparable<? super T>.

In general, if you have an API that only uses a type parameter T as an argument, its uses should take advantage of lower bounded wildcards (? super T). Conversely, if the API only returns T, you'll give your clients more flexibility by using upper bounded wildcards (? extends T).

Wildcard Capture

It should be pretty clear by now that given:
Set<?> unknownSet = new HashSet<String>();
...
/** Add an element  t to a Set s. */
public static <T> void addToSet(Set<T> s, T t) {
    ...
}
The call below is illegal.
addToSet(unknownSet, "abc"); // Illegal.
It makes no difference that the actual set being passed is a set of strings; what matters is that the expression being passed as an argument is a set of an unknown type, which cannot be guaranteed to be a set of strings, or of any type in particular.

Now, consider the following code:

class Collections {
    ...
    <T> public static Set<T> unmodifiableSet(Set<T> set) {
        ...
    }
}
...
Set<?> s = Collections.unmodifiableSet(unknownSet); // This works! Why?
It seems this should not be allowed; yet, looking at this specific call, it is perfectly safe to permit it. After all, unmodifiableSet() does work for any kind of Set, regardless of its element type.

Because this situation arises relatively frequently, there is a special rule that allows such code under very specific circumstances in which the code can be proven to be safe. This rule, known as wildcard capture, allows the compiler to infer the unknown type of a wildcard as a type argument to a generic method.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Class Literals as Runtime-Type Tokens
Next page: Converting Legacy Code to Use Generics


Converting Legacy Code to Use Generics (The Java™ Tutorials > Bonus > Generics)

Trail: Bonus
Lesson: Generics
Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Home Page > Bonus > Generics
« Previous • Trail • Next »
Converting Legacy Code to Use Generics
Earlier, we showed how new and legacy code can interoperate. Now, it's time to look at the harder problem of "generifying" old code.

If you decide to convert old code to use generics, you need to think carefully about how you modify the API.

You need to make certain that the generic API is not unduly restrictive; it must continue to support the original contract of the API. Consider again some examples from java.util.Collection. The pre-generic API looks like:

interface Collection {
    public boolean containsAll(Collection c);
    public boolean addAll(Collection c);
}
A naive attempt to generify it would be the following:
interface Collection<E> {

    public boolean containsAll(Collection<E> c);
    public boolean addAll(Collection<E> c);
}
While this is certainly type safe, it doesn't live up to the API's original contract. The containsAll() method works with any kind of incoming collection. It will only succeed if the incoming collection really contains only instances of E, but:
  • The static type of the incoming collection might differ, perhaps because the caller doesn't know the precise type of the collection being passed in, or perhaps because it is a Collection<S>,where S is a subtype of E.
  • It's perfectly legitimate to call containsAll() with a collection of a different type. The routine should work, returning false.
In the case of addAll(), we should be able to add any collection that consists of instances of a subtype of E. We saw how to handle this situation correctly in section Generic Methods.

You also need to ensure that the revised API retains binary compatibility with old clients. This implies that the erasure of the API must be the same as the original, ungenerified API. In most cases, this falls out naturally, but there are some subtle cases. We'll examine one of the subtlest cases we've encountered, the method Collections.max(). As we saw in section More Fun with Wildcards, a plausible signature for max() is:

public static <T extends Comparable<? super T>>
        T max(Collection<T> coll)
This is fine, except that the erasure of this signature is:
public static Comparable max(Collection coll)
which is different than the original signature of max():
public static Object max(Collection coll)
One could certainly have specified this signature for max(), but it was not done, and all the old binary class files that call Collections.max() depend on a signature that returns Object.

We can force the erasure to be different, by explicitly specifying a superclass in the bound for the formal type parameter T.

public static <T extends Object & Comparable<? super T>>
        T max(Collection<T> coll)
This is an example of giving multiple bounds for a type parameter, using the syntax T1 & T2 ... & Tn. A type variable with multiple bounds is known to be a subtype of all of the types listed in the bound. When a multiple bound is used, the first type mentioned in the bound is used as the erasure of the type variable.

Finally, we should recall that max only reads from its input collection, and so is applicable to collections of any subtype of T.

This brings us to the actual signature used in the JDK:

public static <T extends Object & Comparable<? super T>>
        T max(Collection<? extends T> coll)
It's very rare that anything so involved comes up in practice, but expert library designers should be prepared to think very carefully when converting existing APIs.

Another issue to watch out for is covariant returns, that is, refining the return type of a method in a subclass. You should not take advantage of this feature in an old API. To see why, let's look at an example.

Assume your original API was of the form:

public class Foo {
    public Foo create() {
        ...
    } // Factory. Should create an instance of whatever class it is declared in.
}

public class Bar extends Foo {
    public Foo create() {
        ...
    } // Actually creates a Bar.
}
Taking advantage of covariant returns, you modify it to:
public class Foo {
    public Foo create() {
        ...
    } // Factory. Should create an instance of whatever class it is declared in.
}

public class Bar extends Foo {
    public Bar create() {
        ...
    } // Actually creates a Bar.
}
Now, assume a third party client of your code wrote the following:
public class Baz extends Bar {
    public Foo create() {
        ...
    } // Actually creates a Baz.
}
The Java virtual machine does not directly support overriding of methods with different return types. This feature is supported by the compiler. Consequently, unless the class Baz is recompiled, it will not properly override the create() method of Bar. Furthermore, Baz will have to be modified, since the code will be rejected as written--the return type of create() in Baz is not a subtype of the return type of create() in Bar.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: More Fun with Wildcards
Next page: Acknowledgements


Acknowledgements (The Java™ Tutorials > Bonus > Generics)

Trail: Bonus
Lesson: Generics
Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Home Page > Bonus > Generics
« Previous • Trail • Next »
Acknowledgements
Erik Ernst, Christian Plesner Hansen, Jeff Norton, Mads Torgersen, Peter von der Ahe and Philip Wadler contributed material to this trail .

Thanks to David Biesack, Bruce Chapman, David Flanagan, Neal Gafter, Orjan Petersson, Scott Seligman, Yoshiki Shibata and Kresten Krab Thorup for valuable feedback on earlier versions of this trail. Apologies to anyone I've forgotten.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Converting Legacy Code to Use Generics
Next page: Full-Screen Exclusive Mode API


Lesson: Full-Screen Exclusive Mode API (The Java™ Tutorials > Bonus)

Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode
Display Mode
Passive vs. Active Rendering
Double Buffering and Page Flipping
BufferStrategy and BufferCapabilities
Examples
Trail: Bonus
Home Page > Bonus
« Previous • Trail • Next »
Lesson: Full-Screen Exclusive Mode API

by Michael Martak

Do you want to use high-performance graphics in the Java development environment? Have you always wanted to program a game, but your images wouldn't move fast enough? Has your slide show program not worked properly because you had no control over the user's display resolution? If you've been asking any of these questions, then the full-screen exclusive mode API, introduced in release 1.4, may be what you're looking for.
Full-Screen Exclusive Mode
Full-screen exclusive mode is a powerful new feature that enables you to suspend the windowing system so that drawing can be done directly to the screen.

Display Mode
This section describes how to choose and set the display mode. It also discusses why you'd want to set the display mode in the first place.

Passive vs. Active Rendering
This section discusses the merits of passive and active rendering. For example, painting while on the main event loop using the paint method is passive, whereas rendering in your own thread is active. Active rendering tips are also listed.

Double Buffering and Page Flipping
This section explains double buffering and introduces page-flipping, a double buffering technique available in full-screen exclusive mode.

BufferStrategy and BufferCapabilities
This section covers java.awt.image.BufferStrategy, a class that allows you to draw to surfaces and components without having to know the number of buffers used or the technique used to display them. This section also reviews java.awt.BufferCapabilities, a class that can help you determine the capabilities of your graphics device.

Examples
This page lists several full-screen exclusive mode examples.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Full-Screen Exclusive Mode


Full-Screen Exclusive Mode (The Java™ Tutorials > Bonus > Full-Screen Exclusive Mode API)

Trail: Bonus
Lesson: Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode
Display Mode
Passive vs. Active Rendering
Double Buffering and Page Flipping
BufferStrategy and BufferCapabilities
Examples
Home Page > Bonus > Full-Screen Exclusive Mode API
« Previous • Trail • Next »
Full-Screen Exclusive Mode
Programmers who use Microsoft's DirectX API may already be familiar with full-screen exclusive mode. Other programmers may be somewhat new to the concept. In either case, full-screen exclusive mode is a powerful feature of J2SETM version 1.4 that allows the programmer to suspend the windowing system so that drawing can be done directly to the screen.

This is a slight paradigm shift from the usual kind of GUI program in many ways. In traditional Java GUI programs, the AWT is responsible for propagating paint events from the operating system, through the event dispatch thread, and by calling AWT's Component.paint method when appropriate. In full-screen exclusive applications, painting is usually done actively by the program itself. Additionally, a traditional GUI application is limited to the bit depth and size of the screen chosen by the user. In a full-screen exclusive application, the program can control the bit depth and size (display mode) of the screen. Finally, many more advanced techniques, such as page flipping (discussed below) and stereo buffering (utilizing systems which use a separate set of frames for each eye) require, on some platforms, that an application first be in full-screen exclusive mode.

Hardware-Accelerated Image Basics

To understand the full-screen exclusive mode API, you need to understand some basic principles of hardware-accelerated images. The VolatileImage interface encapsulates a surface which may or may not take advantage of hardware acceleration. Such surfaces may lose their hardware acceleration or their memory at the behest of the operating system (hence, the name 'volatile'). See the VolatileImage Tutorial (coming soon) for more information on volatile images.

Full-screen exclusive mode is handled through a java.awt.GraphicsDevice object. For a list of all available screen graphics devices (in single or multi-monitor systems), you can call the method getScreenDevices on the local java.awt.GraphicsEnvironment; for the default (primary) screen (the only screen on a single-monitor system), you can call the method getDefaultScreenDevice.

Once you have the graphics device, you can call one of the following methods:

public boolean isFullScreenSupported()
This method returns whether or not full-screen exclusive mode is available. On systems where full-screen exclusive mode is not available, it is probably better to run an application in windowed mode with a fixed size rather than setting a full-screen window.

public void setFullScreenWindow(Window w)
Given a window, this method enters full-screen exclusive mode using that window. If full-screen exclusive mode is not available, the window is positioned at (0,0) and resized to fit the screen. Use this method with a null parameter to exit full-screen exclusive mode.

Programming Tips

Here are some tips about programming using full-screen exclusive mode:

  • Check for isFullScreenSupported before entering full-screen exclusive mode. If it isn't supported, performance may be degraded.
  • Entering and exiting full-screen mode is more robust when using a try...finally clause. This is not only good coding practice, but it also prevents your program from staying in full-screen exclusive mode longer than it should:
    • GraphicsDevice myDevice;
Window myWindow;

try {
    myDevice.setFullScreenWindow(myWindow);
    ...
} finally {
    myDevice.setFullScreenWindow(null);
}
  • Most full-screen exclusive applications are better suited to use undecorated windows. Turn off decorations in a frame or dialog using the setUndecorated method.
  • Full-screen exclusive applications should not be resizable, since resizing a full-screen application can cause unpredictable (or possibly dangerous) behavior.
  • For security reasons, the user must grant fullScreenExclusive permission when using full-screen exclusive mode in an applet.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Full-Screen Exclusive Mode API
Next page: Display Mode


Display Mode (The Java™ Tutorials > Bonus > Full-Screen Exclusive Mode API)

Trail: Bonus
Lesson: Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode
Display Mode
Passive vs. Active Rendering
Double Buffering and Page Flipping
BufferStrategy and BufferCapabilities
Examples
Home Page > Bonus > Full-Screen Exclusive Mode API
« Previous • Trail • Next »
Display Mode
Once an application is in full-screen exclusive mode, it may be able to take advantage of actively setting the display mode. A display mode (java.awt.DisplayMode) is composed of the size (width and height of the monitor, in pixels), bit depth (number of bits per pixel), and refresh rate (how frequently the monitor updates itself). Some operating systems allow you to use multiple bit depths at the same time, in which case the special value BIT_DEPTH_MULTI is used for the value of bit depth. Also, some operating systems may not have any control over the refresh rate (or you may not care about the refresh rate setting). In this case, the special value REFRESH_RATE_UNKNOWN is used for the refresh rate value.

How to Set the Display Mode

To get the current display mode, simply call the getDisplayMode method on your graphics device. To obtain a list of all possible display modes, call the getDisplayModes method. Both getDisplayMode and getDisplayModes can be called at any time, regardless of whether or not you are in full-screen exclusive mode.

Before attempting to change the display mode, you should first call the isDisplayChangeSupported method. If this method returns false, the operating system does not support changing the display mode.

Changing the display mode can only be done when in full-screen exclusive mode. To change the display mode, call the setDisplayMode method with the desired display mode. A runtime exception will be thrown if the display mode is not available, if display mode changes are not supported, or if you are not running in full-screen exclusive mode.

Reasons for Changing the Display Mode

The main reason for setting the display mode is performance. An application can run much more quickly if the images it chooses to display share the same bit depth as the screen. Also, if you can count on the display to be a particular size, it makes drawing to that display much simpler, since you do not have to scale things down or up depending on how the user has set the display.

Programming Tips

Here are some tips for choosing and setting the display mode:

  • Check the value returned by the isDisplayChangeSupported method before attempting to change the display mode on a graphics device.
  • Make sure you are in full-screen exclusive mode before attempting to change the display mode.
  • As with using full-screen mode, setting the display mode is more robust when in a try...finally clause:
    • GraphicsDevice myDevice;
Window myWindow;
DisplayMode newDisplayMode;

DisplayMode oldDisplayMode = myDevice.getDisplayMode();
try {
    myDevice.setFullScreenWindow(myWindow);
    myDevice.setDisplayMode(newDisplayMode);
    ...
} finally {
    myDevice.setDisplayMode(oldDisplayMode);
    myDevice.setFullScreenWindow(null);
}
  • When choosing a display mode for your application, you may want to keep a list of preferred display modes, then choose the best one from the list of available display modes.
  • As a fallback, if the display mode you desire is not available, you may want to simply run in windowed mode at a fixed size.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Full-Screen Exclusive Mode
Next page: Passive vs. Active Rendering


Passive vs. Active Rendering (The Java™ Tutorials > Bonus > Full-Screen Exclusive Mode API)

Trail: Bonus
Lesson: Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode
Display Mode
Passive vs. Active Rendering
Double Buffering and Page Flipping
BufferStrategy and BufferCapabilities
Examples
Home Page > Bonus > Full-Screen Exclusive Mode API
« Previous • Trail • Next »
Passive vs. Active Rendering
As mentioned before, most full-screen applications usually function better if they are at the helm during drawing. In traditional windowed GUI applications, the question of when to paint is usually handled by the operating system. When operating in a windowed environment, this makes perfect sense. A windowed application does not know when the user is going to move, resize, expose, or cover an application by another window until it actually happens. In a Java GUI application, the operating system delivers a paint event to the AWT, which figures out what needs to be painted, creates a java.awt.Graphics object with the appropriate clipping region, then calls the paint method with that Graphics object:
// Traditional GUI Application paint method:
// This can be called at any time, usually from the event dispatch thread
public void paint(Graphics g) {
    // Use g to draw my Component
}
This is sometimes referred to as passive rendering. As you can imagine, such a system incurs a lot of overhead, much to the annoyance of many performance-sensitive AWT and Swing programmers.

When in full-screen exclusive mode, you don't have to worry anymore about the window being resized, moved, exposed, or occluded (unless you've ignored my suggestion to turn off resizing). Instead, the application window is drawn directly to the screen (active rendering). This simplifies painting quite a bit, since you don't ever need to worry about paint events. In fact, paint events delivered by the operating system may even be delivered at inappropriate or unpredictable times when in full-screen exclusive mode.

Instead of relying on the paint method in full-screen exclusive mode, drawing code is usually more appropriately done in a rendering loop:

public void myRenderingLoop() {
    while (!done) {
        Graphics myGraphics = getPaintGraphics();
        // Draw as appropriate using myGraphics
        myGraphics.dispose();
    }
}
Such a rendering loop can done from any thread, either its own helper thread or as part of the main application thread.

Programming Tips

Some tips about using active rendering:

  • Don't put drawing code in the paint routine. You may never know when that routine may get called! Instead, use another method name, such as render(Graphics g), which can be called from the paint method when operating in windowed mode, or alternately called with its own graphics from the rendering loop.
  • Use the setIgnoreRepaint method on your application window and components to turn off all paint events dispatched from the operating system completely, since these may be called during inappropriate times, or worse, end up calling paint, which can lead to race conditions between the AWT event thread and your rendering loop.
  • Separate your drawing code from your rendering loop, so that you can operate fully under both full-screen exclusive and windowed modes.
  • Optimize your rendering so that you aren't drawing everything on the screen at all times (unless you are using page-flipping or double-buffering, both discussed below).
  • Do not rely on the update or repaint methods for delivering paint events.
  • Do not use heavyweight components, since these will still incur the overhead of involving the AWT and the platform's windowing system.
  • If you use lightweight components, such as Swing components, you may have to fiddle with them a bit so that they draw using your Graphics, and not directly as a result of calling the paint method. Feel free to call Swing methods such as paintComponents, paintComponent, paintBorder, and paintChildren directly from your rendering loop.
  • Feel free to use passive rendering if you just want a simple full-screen Swing or AWT application, but remember that paint events may be somewhat unreliable or unnecessary while in full-screen exclusive mode. Additionally, if you use passive rendering, you will not be able to use more advanced techniques such as page-flipping. Finally, be very careful to avoid deadlocks if you decide to use both active and passive rendering simultaneously--this approach is not recommended.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Display Mode
Next page: Double Buffering and Page Flipping


Double Buffering and Page Flipping (The Java™ Tutorials > Bonus > Full-Screen Exclusive Mode API)

Trail: Bonus
Lesson: Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode
Display Mode
Passive vs. Active Rendering
Double Buffering and Page Flipping
BufferStrategy and BufferCapabilities
Examples
Home Page > Bonus > Full-Screen Exclusive Mode API
« Previous • Trail • Next »
Double Buffering and Page Flipping
Suppose you had to draw an entire picture on the screen, pixel by pixel or line by line. If you were to draw such a thing directly to the screen (using, say, Graphics.drawLine), you would probably notice with much disappointment that it takes a bit of time. You will probably even notice visible artifacts of how your picture is drawn. Rather than watching things being drawn in this fashion and at this pace, most programmers use a technique called double-buffering.

The traditional notion of double-buffering in Java applications is fairly straightforward: create an offscreen image, draw to that image using the image's graphics object, then, in one step, call drawImage using the target window's graphics object and the offscreen image. You may have already noticed that Swing uses this technique in many of its components, usually enabled by default, using the setDoubleBuffered method.

The screen surface is commonly referred to as the primary surface, and the offscreen image used for double-buffering is commonly referred to as the back buffer. The act of copying the contents from one surface to another is frequently referred to as a block line transfer, or blitting (blt is typically pronounced "blit" and shouldn't be confused with a BLT sandwich).

The primary surface is usually manipulated through the graphics object of any showing component; when in full-screen mode, any operation using the graphics of the full-screen window is a direct manipulation of screen memory. For this reason, you can take advantage of other capabilities in full-screen exclusive mode that may otherwise be unavailable due to the overhead of the windowing system. One such technique that is only available in full-screen exclusive mode is a form of double-buffering called page-flipping.

Page Flipping

Many graphics cards have the notion of a video pointer, which is simply an address in video memory. This pointer tells the graphics card where to look for the contents of the video to be displayed during the next refresh cycle. In some graphics cards and on some operating systems, this pointer can even be manipulated programmatically. Suppose you created a back buffer (in video memory) of the exact width, height, and bit depth of the screen, then drew to that buffer the same way as you would using double-buffering. Now imagine what would happen if, instead of blitting your image to the screen as in double-buffering, you simply changed the video pointer to your back buffer. During the next refresh, the graphics card would now use your image to display. This switch is called page-flipping, and the performance gain over blt-based double-buffering is that only a single pointer needs to be moved in memory as opposed to copying the entire contents from one buffer to another.

When a page flip occurs, the pointer to the old back buffer now points to the primary surface and the pointer to the old primary surface now points to the back buffer memory. This sets you up automatically for the next draw operation.

Sometimes it is advantageous to set up multiple back buffers in a flip chain. This is particularly useful when the amount of time spent drawing is greater than the monitor's refresh rate. A flip chain is simply two or more back buffers (sometimes called intermediary buffers) plus the primary surface (this is sometimes called triple-buffering, quadruple-buffering, etc.). In a flip chain, the next available back buffer becomes the primary surface, etc., all the way down to the rearmost back buffer that is used for drawing.

Benefits of Double-Buffering and Page-Flipping

If your performance metric is simply the speed at which double-buffering or page-flipping occurs versus direct rendering, you may be disappointed. You may find that your numbers for direct rendering far exceed those for double-buffering and that those numbers far exceed those for page-flipping. Each of these techniques is for used for improving perceived performance, which is much more important in graphical applications than numerical performance.

Double-buffering is used primarily to eliminate visible draws which can make an application look amateurish, sluggish, or appear to flicker. Page-flipping is used primarily to also eliminate tearing, a splitting effect that occurs when drawing to the screen happens faster than the monitor's refresh rate. Smoother drawing means better perceived performance and a much better user experience.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Passive vs. Active Rendering
Next page: BufferStrategy and BufferCapabilities


Trail: Bonus
Lesson: Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode
Display Mode
Passive vs. Active Rendering
Double Buffering and Page Flipping
BufferStrategy and BufferCapabilities
Examples
Home Page > Bonus > Full-Screen Exclusive Mode API
« Previous • Trail • Next »
BufferStrategy and BufferCapabilities

BufferStrategy

In Java 2 Standard Edition, you don't have to worry about video pointers or video memory in order to take full advantage of either double-buffering or page-flipping. The new class java.awt.image.BufferStrategy has been added for the convenience of dealing with drawing to surfaces and components in a general way, regardless of the number of buffers used or the technique used to display them.

A buffer strategy gives you two all-purpose methods for drawing: getDrawGraphics and show. When you want to start drawing, get a draw graphics and use it. When you are finished drawing and want to present your information to the screen, call show. These two methods are designed to fit rather gracefully into a rendering loop:

BufferStrategy myStrategy;

while (!done) {
    Graphics g = myStrategy.getDrawGraphics();
    render(g);
    g.dispose();
    myStrategy.show();
}
Buffer strategies have also been set up to help you monitor VolatileImage issues. When in full-screen exclusive mode, VolatileImage issues are especially important because the windowing system can sometimes take back the video memory it has given you. One important example is when the user presses the ALT+TAB key combination in Windows--suddenly your full-screen program is running in the background and your video memory is lost. You can call the contentsLost method to find out if this has happened. Similarly, when the windowing system returns your memory to you, you can find out using the contentsRestored method.

BufferCapabilities

As mentioned before, different operating systems, or even different graphics cards on the same operating system, have different techniques available at their disposal. These capabilities are exposed for you so that you can pick the best technique for your application.

The class java.awt.BufferCapabilities encapsulates these capabilities. Every buffer strategy is controlled by its buffer capabilities, so picking the right ones for your application is very crucial. To find out what capabilities are available, call the getBufferCapabilities method from the GraphicsConfiguration objects available on your graphics device.

The capabilities available in Java 2 Standard Edition version 1.4 are:

isPageFlipping
This capability returns whether or not hardware page-flipping is available on this graphics configuration.

isFullScreenRequired
This capability returns whether or not full-screen exclusive mode is required before hardware page-flipping should be attempted.

isMultiBufferAvailable
This capability returns whether or not multiple buffering (two or more back buffers plus the primary surface) in hardware is available.

getFlipContents
This capability returns a hint of the technique used to do hardware page-flipping. This is important because the contents of the back buffer after a show are different depending on the technique used. The value returned can be null (if isPageFlipping returns false) or one of the following values. Any value can be specified for a buffer strategy so long as the isPageFlipping method returns true, though performance will vary depending on the available capabilities.

FlipContents.COPIED
This value means that the contents of the back buffer are copied to the primary surface. A "flip" is probably performed as a hardware blt, which means that hardware double-buffering is probably done using blitting instead of true page-flipping. This should (in theory) be faster, or at least as fast, as blitting from a VolatileImage to the primary surface, though your mileage may vary. The contents of the back buffer are the same as the primary surface after a flip.

FlipContents.BACKGROUND
This value means that the contents of the back buffer have been cleared with the background color. Either a true page-flip or a blt has occurred.

FlipContents.PRIOR
This value means that the contents of the back buffer are now the contents of the old primary surface, and vice versa. Generally this value indicates that true page-flipping occurs, though this is not guaranteed and, once again, your mileage on this operation may vary.

FlipContents.UNKNOWN
This value means that the contents of the back buffer are undefined after a flip. You may have to experiment to find which technique works best for you (or you may not care), and you will definitely have to set up the contents of the back buffer yourself each time you draw.
To create a buffer strategy for a component, call the createBufferStrategy method, supplying the number of buffers desired (this number includes the primary surface). If any particular buffering technique is desired, supply an appropriate BufferCapabilities object. Note that when you use this version of the method, you must catch an AWTException in the event that your choice is not available. Also note that these methods are only available on Canvas and Window.

Once a particular buffer strategy has been created for a component, you can manipulate it using the getBufferStrategy method. Note that this method is also only available for canvases and windows.

Programming Tips

Some tips about using buffer capabilities and buffer strategies:
  • Getting, using, and disposing a graphics object are more robust in a try...finally clause:
    • BufferStrategy myStrategy;

while (!done) {
    Graphics g;
    try {
        g = myStrategy.getDrawGraphics();
        render(g);
    } finally {
        g.dispose();
    }
    myStrategy.show();
}
  • Check the available capabilities before using a buffer strategy.
  • For best results, create your buffer strategy on a full-screen exclusive window. Make sure you check the isFullScreenRequired and isPageFlipping capabilities before using page-flipping.
  • Don't make any assumptions about performance. Tweak your code as necessary, but remember that different operating systems and graphics cards have different capabilities. Profile your application!
  • You may want to subclass your component to override the createBufferStrategy method. Use an algorithm for choosing a strategy that is best suited to your application. The FlipBufferStrategy and BltBufferStrategy inner classes are protected and can be subclassed.
  • Don't forget that you may lose your drawing surfaces! Be sure to check contentsLost and contentsRestored before drawing. All buffers that have been lost have to be redrawn when they are restored.
  • If you use a buffer strategy for double-buffering in a Swing application, you probably want to turn off double-buffering for your Swing components, since they will already be double-buffered. Video memory is somewhat valuable and should only be used whenever absolutely necessary.
  • It may be end up being wasteful to use more than one back buffer. Multi-buffering is only useful when the drawing time exceeds the time spent to do a show. Profile your application!

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Double Buffering and Page Flipping
Next page: Examples


Examples (The Java™ Tutorials > Bonus > Full-Screen Exclusive Mode API)

Trail: Bonus
Lesson: Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode
Display Mode
Passive vs. Active Rendering
Double Buffering and Page Flipping
BufferStrategy and BufferCapabilities
Examples
Home Page > Bonus > Full-Screen Exclusive Mode API
« Previous • Trail • Next »
Examples
Note: You can only run these examples if you're using Java 2 Standard Edition version 1.4 or higher.
CapabilitiesTest demonstrates the different buffering capabilities available for the machine on which it is run.

DisplayModeTest shows a Swing application that uses passive rendering. If full-screen exclusive mode is available, it will enter full-screen exclusive mode. If display mode changes are allowed, it allows you to switch between display modes.

MultiBufferTest enters full-screen mode and uses multi-buffering through an active render loop.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: BufferStrategy and BufferCapabilities
Next page: Preparation for Java Programmer Language Certification


Lesson: Preparation for Java Programmer Language Certification (The Java™ Tutorials > Bonus)

Trail: Bonus
Home Page > Bonus
« Previous • Trail • Next »
Lesson: Preparation for Java Programmer Language Certification
Sun Microsystems provides certification examinations for Solaris administrators and different types of Java programmers. Sun also offers training classes and practice exams for each type of certification.

Much of the material in this tutorial is pertinent to preparation for the examination to become a "Sun Certified Programmer for the Java Platform."

Some useful links are:

http://www.sun.com/training/certification
An overview of all of the various certifications offered and their associated learning tools.

http://www.sun.com/training/certification/java/index.html
Information specific to the certifications available for Java technologies.

http://www.sun.com/training/certification/objectives
A table of links to the "Testing Objectives" for each Java certification exam—lists of what will be covered on the exams.

If you open the last link and select the Testing Objectives for the Sun Certified Programmer for the Java Platform, you will find a list of objectives that includes bulleted items in seven areas:

  1. Declarations, Initialization, and Scoping
  2. Flow Control
  3. API Contents
  4. Concurrency
  5. OO Concepts
  6. Collections/Generics
  7. Fundamentals
In the text below, each of the bulleted items in each of the seven areas of the Testing Objectives for the Sun Certified Programmer for the Java Platform is quoted, followed by links to sections in this tutorial that include relevant material.
Disclaimer: This tutorial is not intended as a primer for the certification exam—it does not cover every subject to the depth that will be on the exam. The links below are presented so that you can use this tutorial as one of many sources for exam preparation.

Section 1: Declarations, Initialization and Scoping

Item 1:

"Develop code that declares classes (including abstract and all forms of nested classes), interfaces, and enums, and includes the appropriate use of package and import statements (including static imports).

  • Declaring Classes
  • Abstract Methods and Classes
  • Nested Classes
  • Interfaces
  • Enum Types
  • Creating and Using Packages
  • Using Package Members (import statements, static imports)

Item 2:

"Develop code that declares an interface. Develop code that implements or extends one or more interfaces. Develop code that declares an abstract class. Develop code that extends an abstract class."

  • Defining an Interface
  • Implementing an Interface
  • Abstract Methods and Classes

Item 3:

"Develop code that declares, initializes, and uses primitives, arrays, enums, and objects as static, instance, and local variables. Also, use legal identifiers for variable names."

  • Primitive Data Types
  • Arrays
  • Enum Types
  • Understanding Instance and Class Members
  • Variables
  • Declaring Member Variables

Item 4:

"Develop code that declares both static and non-static methods, and - if appropriate - use method names that adhere to the JavaBeans naming standards. Also develop code that declares and uses a variable-length argument list."

  • Understanding Instance and Class Members
  • Passing Information to a Method or Constructor

Item 5:

"Given a code example, determine if a method is correctly overriding or overloading another method, and identify legal return values (including covariant returns), for the method."

  • Overriding and Hiding Methods
  • Defining Methods (overloading)
  • Returning a Value From a Method

Item 6:

"Given a set of classes and superclasses, develop constructors for one or more of the classes. Given a class declaration, determine if a default constructor will be created, and if so, determine the behavior of that constructor. Given a nested or non-nested class listing, write code to instantiate the class."

  • Providing Constructors for Your Classes
  • Using the Keyword super
  • Creating Objects
  • Nested Classes

Section 2: Flow Control

Item 1:

"Develop code that implements an if or switch statement; and identify legal argument types for these statements."

  • The if-then and if-then-else Statements
  • The switch statement

Item 2:

"Develop code that implements all forms of loops and iterators, including the use of for, the enhanced for loop (for-each), do, while, labels, break, and continue; and explain the values taken by loop counter variables during and after loop execution."

  • The for Statement
  • The while and do-while Statements
  • Branching Statements

Item 3:

"Develop code that makes use of assertions, and distinguish appropriate from inappropriate use of assertions."

  • Questions and Exercises:Classes (assertion example)

Item 4:

"Develop code that makes use of exceptions and exception handling clauses (try, catch, finally), and declares methods and overriding methods that throw exceptions."

  • Catching and Handling Exceptions
  • The try Block
  • The catch Blocks
  • The finally Block
  • Putting It All Together

Item 5:

"Recognize the effect of an exception arising at a specified point in a code fragment. Note that the exception may be a runtime exception, a checked exception, or an error."

  • The Catch or Specify Requirement
  • Specifying the Exceptions Thrown by a Method

Item 6:

"Recognize situations that will result in any of the following being thrown: ArrayIndexOutOfBoundsException, ClassCastException, IllegalArgumentException, IllegalStateException, NullPointerException, NumberFormatException, AssertionError, ExceptionInInitializerError, StackOverflowError or NoClassDefFoundError. Understand which of these are thrown by the virtual machine and recognize situations in which others should be thrown programatically."

  • Putting It All Together (ArrayIndexOutOfBoundsException)
  • How to Throw Exceptions (NullPointerException)
  • Command-Line Arguments (NumberFormatException)
  • Object Ordering (ClassCastException, IllegalStateException)
  • The Queue Interface (IllegalStateException)
  • The List Interface (IllegalStateException)

Section 3: API Contents

Item 1:

"Develop code that uses the primitive wrapper classes (such as Boolean, Character, Double, Integer, etc.), and/or autoboxing & unboxing. Discuss the differences between the String, StringBuilder, and StringBuffer classes."

  • The Number Classes
  • Characters
  • Strings
  • The StringBuilder Class

Item 2:

"Given a scenario involving navigating file systems, reading from files, or writing to files, develop the correct solution using the following classes (sometimes in combination), from java.io: BufferedReader, BufferedWriter, File, FileReader, FileWriter and PrintWriter."

  • Character Streams (FileReader, FileWriter)
  • Buffered Streams (BufferedReader, BufferedWriter)
  • Formatting (PrintWriter)
  • File Objects (File)

Item 3:

"Develop code that serializes and/or de-serializes objects using the following APIs from java.io: DataInputStream, DataOutputStream, FileInputStream, FileOutputStream, ObjectInputStream, ObjectOutputStream and Serializable."

  • Data Streams
  • Object Streams

Item 4:

"Use standard J2SE APIs in the java.text package to correctly format or parse dates, numbers, and currency values for a specific locale; and, given a scenario, determine the appropriate methods to use if you want to use the default locale or a specific locale. Describe the purpose and use of the java.util.Locale class."

Item 5:

"Write code that uses standard J2SE APIs in the java.util and java.util.regex packages to format or parse strings or streams. For strings, write code that uses the Pattern and Matcher classes and the String.split method. Recognize and use regular expression patterns for matching (limited to: . (dot), * (star), + (plus), ?, \d, \s, \w, [], ()). The use of *, +, and ? will be limited to greedy quantifiers, and the parenthesis operator will only be used as a grouping mechanism, not for capturing content during matching. For streams, write code using the Formatter and Scanner classes and the PrintWriter.format/printf methods. Recognize and use formatting parameters (limited to: %b, %c, %d, %f, %s) in format strings."

  • Manipulating Characters in a String (String split method)
  • Methods of the Pattern Class
  • Methods of the Matcher Class
  • Scanning
  • Formatting
  • Formatting (PrintWriter, formatting parameters)
  • Formatting Numeric Print Output (formatting parameters)

Section 4: Concurrency

Item 1:

"Write code to define, instantiate, and start new threads using both java.lang.Thread and java.lang.Runnable."

  • Defining and Starting a Thread
  • The SimpleThreads Example

Item 2:

"Recognize the states in which a thread can exist, and identify ways in which a thread can transition from one state to another."

Item 3:

"Given a scenario, write code that makes appropriate use of object locking to protect static or instance variables from concurrent access problems."

  • Thread Interference
  • Memory Consistency Errors
  • Synchronized Methods
  • Intrinsic Locks and Synchronization
  • Atomic Access

Item 4:

"Given a scenario, write code that makes appropriate use of wait, notify, or notifyAll."

  • Guarded Blocks

Section 5: OO Concepts

Item 1:

"Develop code that implements tight encapsulation, loose coupling, and high cohesion in classes, and describe the benefits."

Item 2:

"Given a scenario, develop code that demonstrates the use of polymorphism. Further, determine when casting will be necessary and recognize compiler vs. runtime errors related to object reference casting."

  • Inheritance

Item 3:

"Explain the effect of modifiers on inheritance with respect to constructors, instance or static variables, and instance or static methods."

  • Inheritance
  • Overriding and Hiding Methods
  • Using the Keyword super

Item 4:

"Given a scenario, develop code that declares and/or invokes overridden or overloaded methods and code that declares and/or invokes superclass, overridden, or overloaded constructors."

  • Overriding and Hiding Methods
  • Defining Methods
  • Using the Keyword super

Item 5:

"Develop code that implements "is-a" and/or "has-a" relationships."

Section 6: Collections / Generics

Item 1:

"Given a design scenario, determine which collection classes and/or interfaces should be used to properly implement that design, including the use of the Comparable interface."

  • Object Ordering

Item 2:

"Distinguish between correct and incorrect overrides of corresponding hashCode and equals methods, and explain the difference between == and the equals method."

  • Object as a Superclass

Item 3:

"Write code that uses the generic versions of the Collections API, in particular, the Set, List, and Map interfaces and implementation classes. Recognize the limitations of the non-generic Collections API and how to refactor code to use the generic versions."

  • Generic Types

Item 4:

"Develop code that makes proper use of type parameters in class/interface declarations, instance variables, method arguments, and return types; and write generic methods or methods that make use of wildcard types and understand the similarities and differences between these two approaches."

  • Declaring Classes
  • Defining an Interface
  • Passing Information to a Method or Constructor
  • Returning a Value from a Method
  • Generic Types
  • Generic Methods and Constructors
  • Wildcards

Item 5:

"Use capabilities in the java.util package to write code to manipulate a list by sorting, performing a binary search, or converting the list to an array. Use capabilities in the java.util package to write code to manipulate an array by sorting, performing a binary search, or converting the array to a list. Use the java.util.Comparator and java.lang.Comparable interfaces to affect the sorting of lists and arrays. Furthermore, recognize the effect of the "natural ordering" of primitive wrapper classes and java.lang.String on sorting."

  • Algorithms

Section 7: Fundamentals

Item 1:

"Given a code example and a scenario, write code that uses the appropriate access modifiers, package declarations, and import statements to interact with (through access or inheritance) the code in the example."

  • Controlling Access to Members of a Class
  • Using Package Members

Item 2:

"Given an example of a class and a command-line, determine the expected runtime behavior."

  • Command-Line Arguments
  • Command-Line I/O Objects

Item 3:

"Determine the effect upon object references and primitive values when they are passed into methods that perform assignments or other modifying operations on the parameters."

  • Passing information to a Method or Constructor

Item 4:

"Given a code example, recognize the point at which an object becomes eligible for garbage collection, and determine what is and is not guaranteed by the garbage collection system. Recognize the behaviors of System.gc and finalization."

  • Using Objects

Item 5:

"Given the fully-qualified name of a class that is deployed inside and/or outside a JAR file, construct the appropriate directory structure for that class. Given a code example and a classpath, determine whether the classpath will allow the code to compile successfully."

  • Managing Source and Class Files

Item 6:

"Write code that correctly applies the appropriate operators including assignment operators (limited to: =, +=, -=), arithmetic operators (limited to: +, -, *, /, %, ++, --), relational operators (limited to: <, <=",">, >=, ==, !=), the instanceof operator, logical operators (limited to: &, |, ^, !, &&, ||), and the conditional operator ( ? : ), to produce a desired result. Write code that determines the equality of two objects or two primitives.

  • Assignment, Arithmetic, and Unary Operators
  • Equality, Relational, and Conditional Operators
  • Object as a Superclass
  • Comparing Strings and Portions of Strings
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: End of Trail


Trail: Java Naming and Directory Interface(TM). (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Java Naming and Directory Interface(TM).
This trail describes JNDITM (Java Naming and Directory Interface) an API to access the directory and naming services. Here you learn about the basic naming and directory services and how to use JNDI to write simple applications to use these services. The most popular directory service LDAP is used to demostrate the use of JNDI to access the directory services.

Naming and Directory Concepts Start here to get an overview of naming and directory concepts.

JNDI Overview Gives you an overview of JNDI, its architecture and packaging.

Software Setup Describes instructions and steps involved in setting an environment that is required to run the examples described in this trail as well as any other JNDI application.

Naming and Directory Operations Describes various naming and directory operations and demonstrates them through plenty of examples that access naming/directory services using JNDI.

Advanced Topics for LDAP users A specialized lesson for the LDAP users. It talks about modeling JNDI as an LDAP API, how to perform LDAP authentication, SSL and managing connections in production environments.

Accessing Objects in the Directory Shows you how to integrate your application with the directory, so that you can store and retrieve Java objects to and from the directory.

New features in JDK 5.0 and JDK 6 Introduces to the new features in the JNDI and the LDAP Service Provider that are available in JDK 5.0 and JDK 6.

Note: This tutorial trail is based on the JNDI tutorial at http://java.sun.com/jndi/tutorial/

Why there are two tutorials on JNDI?- I am confused about which one to use?

This tutorial trail is a shorter version of the longer JNDI tutorial and it's been recently updated to include JDK 5.0 and JDK 6 features. The following topics are not covered in this trail, They are covered only in the JNDI Tutorial.
  • Event Notification
  • Building Service Providers
  • Topics on Names
  • Dealing with LDAP Schema
  • Handling LDAP Referrals and aliases
  • LDAP Controls and Extensions
  • GSS-API/Kerberos v5 Authentication

In future, we have plans to merge both tutorial pointers and provide a single source of updated information for our developers.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: Naming and Directory Concepts


Lesson: Naming and Directory Concepts (The Java™ Tutorials > Java Naming and Directory Interface(TM).)

Naming and Directory Concepts
Directory Concepts
Trail: Java Naming and Directory Interface(TM).
Home Page > Java Naming and Directory Interface(TM).
« Previous • Trail • Next »
Lesson: Naming and Directory Concepts

Naming Concepts

A fundamental facility in any computing system is the naming service--the means by which names are associated with objects and objects are found based on their names. When using almost any computer program or system, you are always naming one object or another. For example, when you use an electronic mail system, you must provide the name of the recipient. To access a file in the computer, you must supply its name. A naming service allows you to look up an object given its name.

A naming service's primary function is to map people friendly names to objects, such as addresses, identifiers, or objects typically used by computer programs.

For example, the Internet Domain Name System (DNS) maps machine names to IP Addresses:

www.sun.com ==> 192.9.48.5.

A file system maps a filename to a file reference that a program can use to access the contents of the file.

c:\bin\autoexec.bat ==> File Reference

These two examples also illustrate the wide range of scale at which naming services exist--from naming an object on the Internet to naming a file on the local file system.

Names

To look up an object in a naming system, you supply it the name of the object. The naming system determines the syntax that the name must follow. This syntax is sometimes called the naming system's naming convention. A name is made up components. A name's representation consist of a component separator marking the components of the name.

Naming System | Component Seperator | Names
UNIXTM file system "/" /usr/hello
DNS "." sales.Wiz.COM
LDAP | "," and "=" | cn=Rosanna Lee, o=Sun, c=US

The UNIXTM file system's naming convention is that a file is named from its path relative to the root of the file system, with each component in the path separated from left to right using the forward slash character ("/"). The UNIX pathname, /usr/hello, for example, names a file hello in the file directory usr, which is located in the root of the file system.

DNS naming convention calls for components in the DNS name to be ordered from right to left and delimited by the dot character ("."). Thus the DNS name sales.Wiz.COM names a DNS entry with the name sales, relative to the DNS entry Wiz.COM. The DNS entry Wiz.COM, in turn, names an entry with the name Wiz in the COM entry.

The Lightweight Directory Access Protocol (LDAP) naming convention orders components from right to left, delimited by the comma character (","). Thus the LDAP name cn=Rosanna Lee, o=Sun, c=US names an LDAP entry cn=Rosanna Lee, relative to the entry o=Sun, which in turn, is relative to c=us. LDAP has the further rule that each component of the name must be a name/value pair with the name and value separated by an equals character ("=").

Bindings

The association of a name with an object is called a binding. A file name is bound to a file.

The DNS contains bindings that map machine names to IP addresses. An LDAP name is bound to an LDAP entry.

References and Addresses

Depending on the naming service, some objects cannot be stored directly by the naming service; that is, a copy of the object cannot be placed inside the naming service. Instead, they must be stored by reference; that is, a pointer or reference to the object is placed inside the naming service. A reference represents information about how to access an object. Typically, it is a compact representation that can be used to communicate with the object, while the object itself might contain more state information. Using the reference, you can contact the object and obtain more information about the object.

For example, an airplane object might contain a list of the airplane's passengers and crew, its flight plan, and fuel and instrument status, and its flight number and departure time. By contrast, an airplane object reference might contain only its flight number and departure time. The reference is a much more compact representation of information about the airplane object and can be used to obtain additional information. A file object, for example, is accessed using a file reference. A printer object, for example, might contain the state of the printer, such as its current queue and the amount of paper in the paper tray. A printer object reference, on the other hand, might contain only information on how to reach the printer, such as its print server name and printing protocol.

Although in general a reference can contain any arbitrary information, it is useful to refer to its contents as addresses (or communication end points): specific information about how to access the object.

For simplicity, this tutorial uses "object" to refer to both objects and object references when a distinction between the two is not required.

Context

A context is a set of name-to-object bindings. Every context has an associated naming convention. A context always provides a lookup (resolution) operation that returns the object, it typically also provides operations such as those for binding names, unbinding names, and listing bound names. A name in one context object can be bound to another context object (called a subcontext) that has the same naming convention.

A file directory, such as /usr, in the UNIX file system represents a context. A file directory named relative to another file directory represents a subcontext (UNIX users refer to this as a subdirectory). That is, in a file directory /usr/bin, the directory bin is a subcontext of usr. A DNS domain, such as COM, represents a context. A DNS domain named relative to another DNS domain represents a subcontext. For the DNS domain Sun.COM, the DNS domain Sun is a subcontext of COM.

Finally, an LDAP entry, such as c=us, represents a context. An LDAP entry named relative to another LDAP entry represents a subcontext. For the LDAP entry o=sun,c=us, the entry o=sun is a subcontext of c=us.

Naming Systems and Namespaces

A naming system is a connected set of contexts of the same type (they have the same naming convention) and provides a common set of operations.

A system that implements the DNS is a naming system. A system that communicates using the LDAP is a naming system.

A naming system provides a naming service to its customers for performing naming-related operations. A naming service is accessed through its own interface. The DNS offers a naming service that maps machine names to IP addresses. LDAP offers a naming service that maps LDAP names to LDAP entries. A file system offers a naming service that maps filenames to files and directories.

A namespace is the set of all possible names in a naming system. The UNIX file system has a namespace consisting of all of the names of files and directories in that file system. The DNS namespace contains names of DNS domains and entries. The LDAP namespace contains names of LDAP entries.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Table of Contents
Next page: Directory Concepts


Directory Concepts (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Concepts)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Concepts
Naming and Directory Concepts
Directory Concepts
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Concepts
« Previous • Trail • Next »
Directory Concepts
Many naming services are extended with a directory service. A directory service associates names with objects and also associates such objects with attributes.

directory service = naming service + objects containing attributes

You not only can look up an object by its name but also get the object's attributes or search for the object based on its attributes.

An example is the telephone company's directory service. It maps a subscriber's name to his address and phone number. A computer's directory service is very much like a telephone company's directory service in that both can be used to store information such as telephone numbers and addresses. The computer's directory service is much more powerful, however, because it is available online and can be used to store a variety of information that can be utilized by users, programs, and even the computer itself and other computers.

A directory object represents an object in a computing environment. A directory object can be used, for example, to represent a printer, a person, a computer, or a network. A directory object contains attributes that describe the object that it represents.

Attributes

A directory object can have attributes. For example, a printer might be represented by a directory object that has as attributes its speed, resolution, and color. A user might be represented by a directory object that has as attributes the user's e-mail address, various telephone numbers, postal mail address, and computer account information.

An attribute has an attribute identifier and a set of attribute values. An attribute identifier is a token that identifies an attribute independent of its values. For example, two different computer accounts might have a "mail" attribute; "mail" is the attribute identifier. An attribute value is the contents of the attribute. The email address, for example, might have:

     Attribute Identifier : Attribute Value
             mail   john.smith@somewhere.com

Directories and Directory Services

A directory is a connected set of directory objects. A directory service is a service that provides operations for creating, adding, removing, and modifying the attributes associated with objects in a directory. The service is accessed through its own interface.

Many examples of directory services are possible.

Network Information Service (NIS)
NIS is a directory service available on the Unix operating system for storing system-related information, such as that relating to machines, networks, printers, and users.
Sun Java Directory Server
The Sun Java Directory Server is a general-purpose directory service based on the Internet standard LDAP
Novell Directory Service (NDS)
NDS is a directory service from Novell that provides information about many networking services, such as the file and print services.

Search Service

You can look up a directory object by supplying its name to the directory service. Alternatively, many directories, such as those based on the LDAP, support the notion of searches. When you search, you can supply not a name but a query consisting of a logical expression in which you specify the attributes that the object or objects must have. The query is called a search filter. This style of searching is sometimes called reverse lookup or content-based searching. The directory service searches for and returns the objects that satisfy the search filter.

For example, you can query the directory service to find:

  • all users that have the attribute "age" greater than 40 years.
  • all machines whose IP address starts with "192.113.50".

Combining Naming and Directory Services

Directories often arrange their objects in a hierarchy. For example, the LDAP arranges all directory objects in a tree, called a directory information tree (DIT). Within the DIT, an organization object, for example, might contain group objects that might in turn contain person objects. When directory objects are arranged in this way, they play the role of naming contexts in addition to that of containers of attributes.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Naming and Directory Concepts
Next page: Overview of JNDI


Lesson: Overview of JNDI (The Java™ Tutorials > Java Naming and Directory Interface(TM).)

Overview of JNDI
Naming Package
Directory and LDAP Packages
Event and Service Provider Packages
Trail: Java Naming and Directory Interface(TM).
Home Page > Java Naming and Directory Interface(TM).
« Previous • Trail • Next »
Lesson: Overview of JNDI
The Java Naming and Directory InterfaceTM (JNDI) is an application programming interface (API) that provides naming and directory functionality to applications written using the JavaTM programming language. It is defined to be independent of any specific directory service implementation. Thus a variety of directories -new, emerging, and already deployed can be accessed in a common way.

Architecture

The JNDI architecture consists of an API and a service provider interface (SPI). Java applications use the JNDI API to access a variety of naming and directory services. The SPI enables a variety of naming and directory services to be plugged in transparently, thereby allowing the Java application using the JNDI API to access their services. See the following figure.

Packaging

JNDI is included in the Java SE Platform. To use the JNDI, you must have the JNDI classes and one or more service providers. The JDK includes service providers for the following naming/directory services:
  • Lightweight Directory Access Protocol (LDAP)
  • Common Object Request Broker Architecture (CORBA) Common Object Services (COS) name service
  • Java Remote Method Invocation (RMI) Registry
  • Domain Name Service (DNS)

Other service providers can be downloaded from the JNDI Web site or obtained from other vendors.

The JNDI is divided into five packages:

  • javax.naming
  • javax.naming.directory
  • javax.naming.ldap
  • javax.naming.event
  • javax.naming.spi
The next part of the lesson has a brief description of the JNDI packages.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Naming Package


Naming Package (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Overview of JNDI)

Trail: Java Naming and Directory Interface(TM).
Lesson: Overview of JNDI
Overview of JNDI
Naming Package
Directory and LDAP Packages
Event and Service Provider Packages
Home Page > Java Naming and Directory Interface(TM). > Overview of JNDI
« Previous • Trail • Next »
Naming Package
The javax.naming package contains classes and interfaces for accessing naming services.

Context

The javax.naming package defines a Context interface, which is the core interface for looking up, binding/unbinding, renaming objects and creating and destroying subcontexts.

Lookup
The most commonly used operation is lookup(). You supply lookup() the name of the object you want to look up, and it returns the object bound to that name.
Bindings
listBindings() returns an enumeration of name-to-object bindings. A binding is a tuple containing the name of the bound object, the name of the object's class, and the object itself.
List
list()is similar to listBindings(), except that it returns an enumeration of names containing an object's name and the name of the object's class. list() is useful for applications such as browsers that want to discover information about the objects bound within a context but that don't need all of the actual objects. Although listBindings() provides all of the same information, it is potentially a much more expensive operation.
Name
Name is an interface that represents a generic name--an ordered sequence of zero or more components. The Naming Systems use this interface to define the names that follow its conventions as described in the Naming and Directory Concepts lesson.
References
Objects are stored in naming and directory services in different ways. A reference might be a very compact representation of an object.

The JNDI defines the Reference class to represent reference. A reference contains information on how to construct a copy of the object. The JNDI will attempt to turn references looked up from the directory into the Java objects that they represent so that JNDI clients have the illusion that what is stored in the directory are Java objects.

The Initial Context

In the JNDI, all naming and directory operations are performed relative to a context. There are no absolute roots. Therefore the JNDI defines an InitialContext, which provides a starting point for naming and directory operations. Once you have an initial context, you can use it to look up other contexts and objects.

Exceptions

The JNDI defines a class hierarchy for exceptions that can be thrown in the course of performing naming and directory operations. The root of this class hierarchy is NamingException. Programs interested in dealing with a particular exception can catch the corresponding subclass of the exception. Otherwise, they should catch NamingException.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Overview of JNDI
Next page: Directory and LDAP Packages


Directory and LDAP Packages (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Overview of JNDI)

Trail: Java Naming and Directory Interface(TM).
Lesson: Overview of JNDI
Overview of JNDI
Naming Package
Directory and LDAP Packages
Event and Service Provider Packages
Home Page > Java Naming and Directory Interface(TM). > Overview of JNDI
« Previous • Trail • Next »
Directory and LDAP Packages

Directory Package

The javax.naming package to provide functionality for accessing directory services in addition to naming services. This package allows applications to retrieve associated with objects stored in the directory and to search for objects using specified attributes.

The Directory Context

The DirContextinterface represents a directory context. DirContext also behaves as a naming context by extending the getAttributes()to retrieve the attributes associated with a directory entry (for which you supply the name). Attributes are modified using modifyAttributes()method. Other overloaded forms of search()support more sophisticated search filters.

LDAP Package

The javax.naming.ldap package contains classes and interfaces for using features that are specific to the LDAP v3 that are not already covered by the more generic javax.naming.directory package. In fact, most JNDI applications that use the LDAP will find the javax.naming.directory package sufficient and will not need to use the javax.naming.ldap package at all. This package is primarily for those applications that need to use "extended" operations, controls, or unsolicited notifications.

"Extended" Operation
In addition to specifying well defined operations such as search and modify, the LDAP v3 (RFC 2251) specifies a way to transmit yet-to-be defined operations between the LDAP client and the server. These operations are called "extended" operations. An "extended" operation may be defined by a standards organization such as the Internet Engineering Task Force (IETF) or by a vendor.
Controls
The LDAP v3 allows any request or response to be augmented by yet-to-be defined modifiers, called controls . A control sent with a request is a request control and a control sent with a response is a response control . A control may be defined by a standards organization such as the IETF or by a vendor. Request controls and response controls are not necessarily paired, that is, there need not be a response control for each request control sent, and vice versa.

Unsolicited Notifications
In addition to the normal request/response style of interaction between the client and server, the LDAP v3 also specifies unsolicited notifications--messages that are sent from the server to the client asynchronously and not in response to any client request.

The LDAP Context

The LdapContextinterface represents a context for performing "extended" operations, sending request controls, and receiving response controls. Examples of how to use these features are described in the JNDI Tutorial's Controls and Extensions lesson.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Naming Package
Next page: Event and Service Provider Packages


Event and Service Provider Packages (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Overview of JNDI)

Trail: Java Naming and Directory Interface(TM).
Lesson: Overview of JNDI
Overview of JNDI
Naming Package
Directory and LDAP Packages
Event and Service Provider Packages
Home Page > Java Naming and Directory Interface(TM). > Overview of JNDI
« Previous • Trail • Next »
Event and Service Provider Packages

Event Package

The javax.naming.event package contains classes and interfaces for supporting event notification in naming and directory services. Event notification is described in detail in the trail.
Events
A NamingEvent represents an event that is generated by a naming/directory service. The event contains a type that identifies the type of event. For example, event types are categorized into those that affect the namespace, such as "object added," and those that do not, such as "object changed."
Listeners
A NamingListener is an object that listens for NamingEvents. Each category of event type has a corresponding type of NamingListener. For example, a NamespaceChangeListener represents a listener interested in namespace change events and an ObjectChangeListener represents a listener interested in object change events.
To receive event notifications, a listener must be registered with either an EventContext or an EventDirContext. Once registered, the listener will receive event notifications when the corresponding changes occur in the naming/directory service. The details about Event Notification can be found in the JNDI Tutorial

Service Provider Package

The javax.naming.spi package provides the means by which developers of different naming/directory service providers can develop and hook up their implementations so that the corresponding services are accessible from applications that use the JNDI.
Plug-In Architecture
The javax.naming.spi package allows different implementations to be plugged in dynamically. These implementations include those for the initial context and for contexts that can be reached from the initial context.
Java Object Support
The javax.naming.spi package supports implementors of lookup and related methods to return Java objects that are natural and intuitive for the Java programmer. For example, if you look up a printer name from the directory, then you likely would expect to get back a printer object on which to operate. This support is provided in the form of object factories.

This package also provides support for doing the reverse. That is, implementors of Context.bind() and related methods can accept Java objects and store the objects in a format acceptable to the underlying naming/directory service. This support is provided in the form of state factories.

Multiple Naming Systems (Federation)
JNDI operations allow applications to supply names that span multiple naming systems. In the process of completing an operation, one service provider might need to interact with another service provider, for example to pass on the operation to be continued in the next naming system. This package provides support for different providers to cooperate to complete JNDI operations.
The details about the Service Provider mechanism can be found in the JNDI Tutorial
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Directory and LDAP Packages
Next page: Software Setup


Lesson: Software Setup (The Java™ Tutorials > Java Naming and Directory Interface(TM).)

Software Setup
LDAP Setup
Java Application Setup
Trail: Java Naming and Directory Interface(TM).
Home Page > Java Naming and Directory Interface(TM).
« Previous • Trail • Next »
Lesson: Software Setup

Required Software

Following is a list of the software/systems that you need:
  • Java platform software
  • Service provider software
  • Naming and directory server software

Java Platform Software

JNDI is included in the Java SE Platform.

To run the applets, you can use any Java-compatible Web browser, such as Firefox , or Internet Explorer v5 or later. To ensure that your applets take full advantage of the latest features of the Java platform software, you can use the Java Plug-in with your Web browser.

Note 1: If you are using JDK release prior to v 1.3, then you can use the JNDI software available from the JNDI Web site.

Service Provider Software

The JNDI API is a generic API for accessing any naming or directory service. Actual access to a naming or directory service is enabled by plugging in a service provider under the JNDI. An overview of the JNDI architecture and the role of service providers is given in the JNDI Overview lesson.

A service provider is software that maps the JNDI API to actual calls to the naming or directory server. Typically, the roles of the service provider and that of the naming/directory server differ. In the terminology of client/server software, the JNDI and the service provider are the client (called the JNDI client) and the naming/directory server is the server.

Clients and servers may interact in many ways. In one common way, they use a network protocol so that the client and server can exist autonomously in a networked environment. The server typically supports many different clients, not only JNDI clients, provided that the clients conform to the specified protocol. The JNDI does not dictate any particular style of interaction between JNDI clients and servers. For example, at one extreme the client and server could be the same entity.

You need to obtain the classes for the service providers that you will be using. For example, if you plan to use the JNDI to access an LDAP directory server, then you would need software for an LDAP service provider.

The JDK comes with service providers for:

  • Light Weight Directory Protocol (LDAP)
  • CORBA Common Object Services naming (COS naming)
  • RMI registry
  • Domain Name Service (DNS)
If you are interested in other providers please check the JNDI Web site for download information.

Note 2: The above service providers are bundled with JDK since v 1.3 except the DNS service Provider which was made available since JDK v 1.4.

This tutorial uses only the LDAP Service provider. When using the LDAP service provider, you need either to set up your own server or to have access to an existing server, as explained next.

Naming and Directory Server Software

Once you have obtained the service provider software, you then need to set up or have access to a corresponding naming/directory server. Setting up a naming/directory server is typically the job of a network system administrator. Different vendors have different installation procedures for their naming/directory servers. Some require special machine privileges before the server can be installed. You should consult the naming/directory server software's installation instructions.

For the directory examples in this tutorial, you need access to an LDAP server. If you would like to take a quick tour of what LDAP is check out here. You can use any LDAP-compliant server of your choice. The Sun Java Directory Server, which runs on many platforms, including Windows, is available for evaluation at: Sun Java Directory Server home.

You can also download free LDAP servers below:

  • OpenDS
  • OpenLDAP
  • Fedora Directory Server
  • Apache Directory Server

A publicly accessible server is available at: ldap://ldap.openldap.org Naming Context: dc=OpenLDAP,dc=org

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: LDAP Setup


LDAP Setup (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Software Setup)

Trail: Java Naming and Directory Interface(TM).
Lesson: Software Setup
Software Setup
LDAP Setup
Java Application Setup
Home Page > Java Naming and Directory Interface(TM). > Software Setup
« Previous • Trail • Next »
LDAP Setup
Below are the steps involved in building a Java Application that accesses an LDAP Directory Server.
  1. Install the Java Platform Software
  2. Get the Directory Server software as discussed earlier
  3. Configure the Directory Server with the desired schema. For using the examples in this tutorial a special schema needs to be configured on the server.
  4. Populate the directory server with the desired content. For using the examples in this tutorial a special content needs to be populated on the server.
  5. Write a JNDI application to access the Directory, compile and run it against the Directory Server to get your desired results. The JNDI examples are covered in the next lesson.
The first two steps are covered in the previous section. The rest of this lesson discusses steps three and part of step four. The step five that involves writing a JNDI application is covered in the next lesson that shows how to write JNDI applications to perform various operations on the directory.

Once you've set up the directory, or have directed your program to communicate with an existing directory, what sort of information can you expect to find there?

The directory can be viewed as consisting of name-to-object bindings. That is, each object in the directory has a corresponding name. You can retrieve an object in the directory by looking up its name.

Also stored in the directory are attributes. An object in the directory, in addition to having a name, also has an optional set of attributes. You can ask the directory for an object's attributes, as well as ask it to search for an object that has certain attributes.

Step 3: Directory Schema

A schema specifies the types of objects that a directory may contain. This tutorial populates the directory with entries, some of which require special schema definitions. To accommodate these entries, you must first either turn off schema-checking in the server or add the schema files that accompany this tutorial to the server. Both of these tasks are typically performed by the directory server's administrator.

This tutorial comes with two schema files that must be installed:

  • Schema for Java objects
  • Schema for CORBA objects
The format of these files is a formal description that possibly cannot be directly copied and pasted into server configuration files. Specifically, the attribute syntaxes are described in terms of RFC 2252.

Different directory servers have different ways of configuring their schema. This tutorial includes some tools for installing the Java and CORBA schemas on directory servers that permit their schemas to be modified via the LDAP. Following is a list of tasks the tools can perform.

  1. Create Java Schema
  2. Create CORBA Schema
Follow the instructions in the accompanying README file to run these programs.
Note: Windows Active Directory. Active Directory manages its schema by using an internal format. To update the schema, you can use either the Active Directory Management Console snap-in, ADSIEdit, or the CreateJavaSchema utility, following the instructions for Active Directory.

Step 4: Providing Directory Content for This Tutorial

In the examples of this trail, the results shown reflect how the LDAP directory has been set up using the configuration file (tutorial.ldif) that accompanies this tutorial. If you are using an existing server, or a server with a different setup, then you might see different results. Before you can load the configuration file (tutorial.ldif) into the directory server, you must follow the instructions for updating the server's schema or you can use ldapadd or ldapmodify command if available on your UNIX system.

For example, using ldapmodify you could do (by plugging in appropriate values for the hostname, administrator DN (-D option), and the password):

ldapmodify -a -c -v -h hostname -p 389\
        -D "cn=Administrator, cn=users, dc=xxx, dc=xxx"\
        -w passwd -f tutorial.ldif

Installation Note: Access Control. Different directory servers handle access control differently. Some examples in this tutorial perform updates to the directory. Also, the part of the namespace where you have installed the tutorial might have read access restrictions. Therefore, you need to take server-specific actions to make the directory readable and/or updatable in order for those examples to work. For the Sun Java Directory Server add the aci entry suggested in the sunds.aci.ldif file to the dn: o=JNDITutorial entry to make the entire directory readable and updatable. Alternatively, you may change the examples so that they authenticate to the directory. Details of how to do this are described in the Adavanced Topics for LDAP users lesson.

Installation Note: Namespace Setup. The entries in the tutorial.ldif file use the distinguished name (DN) "o=JNDITutorial" for the root naming context. If you have not configured your directory server to have "o=JNDITutorial" as a root naming context, then your attempt to import tutorial.ldif will fail. The easiest way to get around this problem is to add the DN of an existing root naming context to each "dn:" line in the tutorial.ldif file. For example, if your server already has the root naming context "dc=imc,dc=org", then you should change the line

dn: o=JNDITutorial
to
dn: o=JNDITutorial, dc=imc, dc=org
Make this change for each line that begins with "dn:" in the file. Then, in all of the examples in this tutorial, wherever it uses "o=JNDITutorial", use "o=JNDITutorial,dc=imc,dc=org" instead.

Installation Note: File Format. Depending on the operating system platform that you are using, you might need to edit tutorial.ldif so that it contains the correct newline characters for that platform. For example, if you find that tutorial.ldif contains Windows-style newline characters (CRLF) and you are importing this file into a directory server that is running on a Unix platform, then you need to edit the file and replace CRLF with LF. A symptom of this problem is that the directory server rejects all of the entries in tutorial.ldif.

Installation Note: Windows Active Directory.

  1. The root naming context is not going to be "o=jnditutorial". It will be of the form "dc=x,dc=y,dc=z". You need to follow the previous Namespace Setup note.
  2. Add the object classes and related attributes for the "inetOrgPerson" and "groupOfUniqueNames" object classes to the Active Directory schema by using the Active Directory Management Console snap-in, ADSIEdit. "groupOfUniqueNames" is defined in RFC 2256, "inetOrgPerson" in RFC 2798
  3. Some of hierarchical relationships used by the tutorial are not allowed by default in Active Directory. To enable these relationships, add them by using the Active Directory Management Console snap-in, ADSIEdit.
    objectclass: organizationalUnit
possible superiors: domainDNS
                    inetOrgPerson
                    organizaton
                    organizationalPerson
                    organizationalUnit
                    person
                    top

objectclass: groupOfUniqueNames
possible superiors: top

objectclass: inetOrgPerson
possible superiors: container
                    organizationalPerson
                    person
                    top
  4. Delete one of the two "sn" attributes from the Mark Twain entry in tutorial.ldif. Active Directory defines "sn" to be a single-valued attribute, contrary to RFC 2256.
  5. Use the ldifde command-line utility to load the modified tutorial.ldif file.
    # ldifde -i -v -k -f tutorial.ldif
  6. Most of the examples assume that the directory has been set up to permit unauthenticated read and update access. Your Active Directory setup might not allow you to do that. See the Access Control installation note.
  7. Reading an entry sometimes produces more attributes than are shown in the tutorial because Active Directory often returns some internal attributes.
  8. Creation of entries might require the specification of additional Active Directory-specific attributes or the use of other object classes.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Software Setup
Next page: Java Application Setup


Java Application Setup (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Software Setup)

Trail: Java Naming and Directory Interface(TM).
Lesson: Software Setup
Software Setup
LDAP Setup
Java Application Setup
Home Page > Java Naming and Directory Interface(TM). > Software Setup
« Previous • Trail • Next »
Java Application Setup
To use the JNDI in your program, you need to set up its compilation and execution environments.

Importing the JNDI Classes

Following are the JNDI packages:
  • javax.naming
  • javax.naming.directory
  • javax.naming.event
  • javax.naming.ldap
  • javax.naming.spi

The examples in this trail use classes and interfaces from the first two packages. You need to import these two packages into your program or import individual classes and interfaces that you use. The following two lines import all of the classes and interfaces from the two packages javax.naming and javax.naming.directory.

import javax.naming.*;
import javax.naming.directory.*;

Compilation Environment

To compile a program that uses the JNDI, you need access to the JNDI classes. The Java SE 6 already include the JNDI classes, so if you are using it you need not take further actions.

If you are using an older version- Java 2 SDK v1.2 or earlier, please refer to the main JNDI Tutorial for instructions on how to setup the compilation environment.

Execution Environment

To run a program that uses the JNDI, you need access to the JNDI classes and classes for any service providers that the program uses. The Java Runtime Environment (JRE) 6 already includes the JNDI classes and service providers for LDAP, COS naming, the RMI registry and the DNS .

If you are using some other service providers, then you need to download and install their archive files in the JAVA_HOME/jre/lib/ext directory, where JAVA_HOME is the directory that contains the JRE. The JNDI Web site lists some service providers. You may download these providers or use providers from other vendors.

If you are using an older version- JRE v1.2 or earlier, please refer to the main JNDI Tutorial for instructions on how to setup the runtime environment.

For using the examples in this trail, you'll need the LDAP service provider.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: LDAP Setup
Next page: Naming and Directory Operations


Lesson: Naming and Directory Operations (The Java™ Tutorials > Java Naming and Directory Interface(TM).)

Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Trail: Java Naming and Directory Interface(TM).
Home Page > Java Naming and Directory Interface(TM).
« Previous • Trail • Next »
Lesson: Naming and Directory Operations
You can use the JNDI to perform naming operations, including read operations and operations for updating the namespace. The following operations are described in this lesson:
  • Looking up an object
  • Listing the contents of a context
  • Adding, overwriting, and removing a binding
  • Renaming an object
  • Creating and destroying subcontexts

Configuration

Before performing any operation on a naming or directory service, you need to acquire an initial context--the starting point into the namespace. This is because all methods on naming and directory services are performed relative to some context. To get an initial context, you must follow these steps.
  1. Select the service provider of the corresponding service you want to access.
  2. Specify any configuration that the initial context needs.
  3. Call the InitialContext constructor.

Step1: Select the Service Provider for the Initial Context

You can specify the service provider to use for the initial context by creating a set of environment properties (a Hashtable) and adding the name of the service provider class to it. Environment properties are described in detail in the JNDI Tutorial

If you are using the LDAP service provider from Sun Microsystems, then your code would look like the following.

Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.ldap.LdapCtxFactory");
To specify the file system service provider from Sun Microsystems, you would write code that looks like the following.
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.fscontext.RefFSContextFactory");
You can also use system properties to specify the service provider to use. Check out the JNDI Tutorial for details.

Step2: Supply the Information Needed by the Initial Context

Clients of different directories might need various information for contacting the directory. For example, you might need to specify on which machine the server is running and what information is needed to identify the user to the directory. Such information is passed to the service provider via environment properties. The JNDI specifies some generic environment properties that service providers can use. Your service provider documentation will give details on the information required for these properties.

The LDAP provider requires that the program specify the location of the LDAP server, as well as user identity information. To provide this information, you would write code that looks as follows.

env.put(Context.PROVIDER_URL, "ldap://ldap.wiz.com:389");
env.put(Context.SECURITY_PRINCIPAL, "joeuser");
env.put(Context.SECURITY_CREDENTIALS, "joepassword");
This tutorial uses the LDAP service provider from Sun Microsystems. The examples assume that a server has been set up on the local machine at port 389 with the root-distinguished name of "o=JNDITutorial" and that no authentication is required for updating the directory. They include the following code for setting up the environment.
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");
If you are using a directory that is set up differently, then you will need to set up these environment properties accordingly. You will need to replace "localhost" with the name of that machine. You can run these examples against any public directory servers or your own server running on a different machine. You will need to replace "localhost" with the name of that machine and replace o=JNDITutorial with the naming context that is available.

Step3: Creating the Initial Context

You are now ready to create the initial context. To do that, you pass to the InitialContext constructor the environment properties that you created previously:
Context ctx = new InitialContext(env);

Now that you have a reference to a Context object, you can begin to access the naming service.

To perform directory operations, you need to use an InitialDirContext. To do that, use one of its constructors:

DirContext ctx = new InitialDirContext(env);

This statement returns a reference to a DirContext object for performing directory operations.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Naming Exceptions


Naming Exceptions (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Naming Exceptions
Many methods in the JNDI packages throw a NamingException when they need to indicate that the operation requested cannot be performed. Commonly, you will see a try/catch wrapper around the methods that can throw a NamingException:
try {
    Context ctx = new InitialContext();
    Object obj = ctx.lookup("somename");
} catch (NamingException e) {
    // Handle the error
    System.err.println(e);
}

Exception Class Hierarchy

The JNDI has a rich exception hierarchy stemming from the NamingException class. The class names of the exceptions are self-explanatory and are listed here .

To handle a particular subclass of NamingException specially, you catch the subclass separately. For example, the following code specially treats the AuthenticationException and its subclasses.

try {
    Context ctx = new InitialContext();
    Object obj = ctx.lookup("somename");
} catch (AuthenticationException e) {
    // attempt to reacquire the authentication information
    ...
} catch (NamingException e) {
    // Handle the error
    System.err.println(e);
}

Enumerations

Operations such as Context.list() and DirContext.search() return a NamingEnumeration . In these cases, if an error occurs and no results are returned, then NamingException or one of its appropriate subclasses will be thrown at the time that the method is invoked. If an error occurs but there are some results to be returned, then a NamingEnumeration is returned so that you can get those results. When all of the results are exhausted, invoking NamingEnumeration.hasMore() will cause a NamingException (or one of its subclasses) to be thrown to indicate the error. At that point, the enumeration becomes invalid and no more methods should be invoked on it.

For example, if you perform a search() and specify a count limit (n) of how many answers to return, then the search() will return an enumeration consisting of at most n results. If the number of results exceeds n, then when NamingEnumeration.hasMore() is invoked for the n+1 time, a SizeLimitExceededException will be thrown. See the count limit discussion of this lesson for a sample code.

Examples in This Tutorial

In the inline sample code that is embedded within the text of this tutorial, the try/catch clauses are usually omitted for the sake of readability. Typically, because only code fragments are shown here, only the lines that are directly useful in illustrating a concept are included. You will see appropriate placements of the try/catch clauses for NamingException if you look in the source files that accompany this tutorial.

The Exceptions in the javax.naming package can be found here .

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Naming and Directory Operations
Next page: Lookup an Object


Lookup an Object (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Lookup an Object
To look up an object from the naming service, use Context.lookup() and pass it the name of the object that you want to retrieve. Suppose that there is an object in the naming service with the name cn=Rosanna Lee,ou=People. To retrieve the object, you would write
Object obj = ctx.lookup("cn=Rosanna Lee,ou=People");

The type of object that is returned by lookup() depends both on the underlying naming system and on the data associated with the object itself. A naming system can contain many different types of objects, and a lookup of an object in different parts of the system might yield objects of different types. In this example, "cn=Rosanna Lee,ou=People" happens to be bound to a context object (javax.naming.ldap.LdapContext). You can cast the result of lookup() to its target class.

For example, the following code looks up the object "cn=Rosanna Lee,ou=People" and casts it to LdapContext.

import javax.naming.ldap.LdapContext;
...
LdapContext ctx = (LdapContext) ctx.lookup("cn=Rosanna Lee,ou=People");

The complete example is in the file Lookup.java.

There are two new static methods available in Java SE 6 to lookup a name:

  • InitialContext.doLookup(Name name)
  • InitialContext.doLookup(String name)

These methods provide a shortcut way of looking up a name without instantiating an InitialContext.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Naming Exceptions
Next page: List the Context


List the Context (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
List the Context
Instead of getting a single object at a time, as with Context.lookup() , you can list an entire context by using a single operation. There are two methods for listing a context: one that returns the bindings and one that returns only the name-to-object class name pairs.

The Context.List() Method

Context.list() returns an enumeration of NameClassPair. Each NameClassPair consists of the object's name and its class name. The following code fragment lists the contents of the "ou=People" directory (i.e., the files and directories found in "ou=People" directory).

NamingEnumeration list = ctx.list("ou=People");

while (list.hasMore()) {
    NameClassPair nc = (NameClassPair)list.next();
    System.out.println(nc);
}

Running this example yields the following output.
# java List
cn=Jon Ruiz: javax.naming.directory.DirContext
cn=Scott Seligman: javax.naming.directory.DirContext
cn=Samuel Clemens: javax.naming.directory.DirContext
cn=Rosanna Lee: javax.naming.directory.DirContext
cn=Maxine Erlund: javax.naming.directory.DirContext
cn=Niels Bohr: javax.naming.directory.DirContext
cn=Uri Geller: javax.naming.directory.DirContext
cn=Colleen Sullivan: javax.naming.directory.DirContext
cn=Vinnie Ryan: javax.naming.directory.DirContext
cn=Rod Serling: javax.naming.directory.DirContext
cn=Jonathan Wood: javax.naming.directory.DirContext
cn=Aravindan Ranganathan: javax.naming.directory.DirContext
cn=Ian Anderson: javax.naming.directory.DirContext
cn=Lao Tzu: javax.naming.directory.DirContext
cn=Don Knuth: javax.naming.directory.DirContext
cn=Roger Waters: javax.naming.directory.DirContext
cn=Ben Dubin: javax.naming.directory.DirContext
cn=Spuds Mackenzie: javax.naming.directory.DirContext
cn=John Fowler: javax.naming.directory.DirContext
cn=Londo Mollari: javax.naming.directory.DirContext
cn=Ted Geisel: javax.naming.directory.DirContext

The Context.listBindings() Method

Context.listBindings() returns an enumeration of Binding. Binding is a subclass of NameClassPair. A binding contains not only the object's name and class name, but also the object. The following code enumerates the "ou=People" context, printing out each binding's name and object.
NamingEnumeration bindings = ctx.listBindings("ou=People");

while (bindings.hasMore()) {
    Binding bd = (Binding)bindings.next();
    System.out.println(bd.getName() + ": " + bd.getObject());
}

Running this example yields the following output.

# java ListBindings
cn=Jon Ruiz: com.sun.jndi.ldap.LdapCtx@1d4c61c
cn=Scott Seligman: com.sun.jndi.ldap.LdapCtx@1a626f
cn=Samuel Clemens: com.sun.jndi.ldap.LdapCtx@34a1fc
cn=Rosanna Lee: com.sun.jndi.ldap.LdapCtx@176c74b
cn=Maxine Erlund: com.sun.jndi.ldap.LdapCtx@11b9fb1
cn=Niels Bohr: com.sun.jndi.ldap.LdapCtx@913fe2
cn=Uri Geller: com.sun.jndi.ldap.LdapCtx@12558d6
cn=Colleen Sullivan: com.sun.jndi.ldap.LdapCtx@eb7859
cn=Vinnie Ryan: com.sun.jndi.ldap.LdapCtx@12a54f9
cn=Rod Serling: com.sun.jndi.ldap.LdapCtx@30e280
cn=Jonathan Wood: com.sun.jndi.ldap.LdapCtx@16672d6
cn=Aravindan Ranganathan: com.sun.jndi.ldap.LdapCtx@fd54d6
cn=Ian Anderson: com.sun.jndi.ldap.LdapCtx@1415de6
cn=Lao Tzu: com.sun.jndi.ldap.LdapCtx@7bd9f2
cn=Don Knuth: com.sun.jndi.ldap.LdapCtx@121cc40
cn=Roger Waters: com.sun.jndi.ldap.LdapCtx@443226
cn=Ben Dubin: com.sun.jndi.ldap.LdapCtx@1386000
cn=Spuds Mackenzie: com.sun.jndi.ldap.LdapCtx@26d4f1
cn=John Fowler: com.sun.jndi.ldap.LdapCtx@1662dc8
cn=Londo Mollari: com.sun.jndi.ldap.LdapCtx@147c5fc
cn=Ted Geisel: com.sun.jndi.ldap.LdapCtx@3eca90

Terminating a NamingEnumeration

 A NamingEnumeration can be terminated in one of three ways: naturally, explicitly, or unexpectedly.
  • When NamingEnumeration.hasMore() returns false, the enumeration is complete and effectively terminated.
  • You can terminate an enumeration explicitly before it has completed by invoking NamingEnumeration.close(). Doing this provides a hint to the underlying implementation to free up any resources associated with the enumeration.
  • If either hasMore() or next() throws a NamingException, then the enumeration is effectively terminated.

Regardless of how an enumeration has been terminated, once terminated it can no longer be used. Invoking a method on a terminated enumeration yields an undefined result.

Why Two Different List Methods?

list() is intended for browser-style applications that just want to display the names of objects in a context. For example, a browser might list the names in a context and wait for the user to select one or a few of the names displayed to perform further operations. Such applications typically do not need access to all of the objects in a context.

listBindings() is intended for applications that need to perform operations on the objects in a context en masse. For example, a backup application might need to perform "file stats" operations on all of the objects in a file directory. Or a printer administration program might want to restart all of the printers in a building. To perform such operations, these applications need to obtain all of the objects bound in a context. Thus it is more expedient to have the objects returned as part of the enumeration.

The application can use either list() or the potentially more expensive listBindings(), depending on the type of information it needs.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Lookup an Object
Next page: Add, Replace or Remove a Binding


Add, Replace or Remove a Binding (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Add, Replace or Remove a Binding
The Context interface contains methods for adding, replacing, and removing a binding in a context.

Adding a Binding

Context.bind() is used to add a binding to a context. It accepts as arguments the name of the object and the object to be bound.
Before you go on: The examples in this lesson require that you make additions to the schema. You must either turn off schema-checking in the LDAP server or add the schema that accompanies this tutorial to the server. Both of these tasks are typically performed by the directory server's administrator. See the lesson.
// Create the object to be bound
Fruit fruit = new Fruit("orange");

// Perform the bind
ctx.bind("cn=Favorite Fruit", fruit);
This example creates an object of class Fruit and binds it to the name "cn=Favorite Fruit" in the context ctx. If you subsequently looked up the name "cn=Favorite Fruit" in ctx, then you would get the fruit object. Note that to compile the Fruit class, you need the FruitFactory class.

If you were to run this example twice, then the second attempt would fail with a NameAlreadyBoundException. This is because the name "cn=Favorite Fruit" is already bound. For the second attempt to succeed, you would have to use rebind().

Adding or Replacing a Binding

rebind() is used to add or replace a binding. It accepts the same arguments as bind(), but the semantics are such that if the name is already bound, then it will be unbound and the newly given object will be bound.
// Create the object to be bound
Fruit fruit = new Fruit("lemon");

// Perform the bind
ctx.rebind("cn=Favorite Fruit", fruit);
When you run this example, it will replace the binding created by the bind() example.

Removing a Binding

To remove a binding, you use unbind().
// Remove the binding
ctx.unbind("cn=Favorite Fruit");
This example, when run, removes the binding that was created by the bind() or rebind() example.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: List the Context
Next page: Rename


Rename (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Rename
You can rename an object in a context by using Context.rename().
// Rename to Scott S
ctx.rename("cn=Scott Seligman", "cn=Scott S");

This example renames the object that was bound to "cn=Scott Seligman" to "cn=Scott S". After verifying that the object got renamed, the program renames it to its original name ("cn=Scott Seligman"), as follows.

// Rename back to Scott Seligman
ctx.rename("cn=Scott S", "cn=Scott Seligman");

For more examples on renaming of LDAP entries check out the Advanced Topics for LDAP users lesson.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Add, Replace or Remove a Binding
Next page: Create and Destroy Subcontexts


Create and Destroy Subcontexts (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Create and Destroy Subcontexts
The Context interface contains methods for creating and destroying a subcontext, a context that is bound in another context of the same type.

This examples here use an object that has attributes and create a subcontext in the directory. You can use these DirContext methods to associate attributes with the object at the time that the binding or subcontext is added to the namespace. For example, you might create a Person object and bind it to the namespace and at the same time associate attributes about that Person object. The naming equivalent will have no attributes.

The createSubcontext() differs from bind() in that it creates a new Object i.e a new Context to be bound to the directory while as bind() binds the given Object in the directory.

Creating a Context

To create a naming context, you supply to createSubcontext() the name of the context that you want to create. To create a context that has attributes, you supply to DirContext.createSubcontext() the name of the context that you want to create and its attributes.
Before you go on: The examples in this lesson require that you make additions to the schema. You must either turn off schema-checking in the LDAP server or add the schema that accompanies this tutorial to the server. Both of these tasks are typically performed by the directory server's administrator. See the lesson.
// Create attributes to be associated with the new context
Attributes attrs = new BasicAttributes(true); // case-ignore
Attribute objclass = new BasicAttribute("objectclass");
objclass.add("top");
objclass.add("organizationalUnit");
attrs.put(objclass);

// Create the context
Context result = ctx.createSubcontext("NewOu", attrs);
This example creates a new context called "ou=NewOu" that has an attribute "objectclass" with two values, "top" and "organizationalUnit", in the context ctx.
# java Create
ou=Groups: javax.naming.directory.DirContext
ou=People: javax.naming.directory.DirContext
ou=NewOu: javax.naming.directory.DirContext
This example creates a new context, called "NewOu", that is a child of ctx.

Destroying a Context

To destroy a context, you supply to destroySubcontext() the name of the context to destroy.
// Destroy the context
ctx.destroySubcontext("NewOu");
This example destroys the context "NewOu" in the context ctx.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Rename
Next page: Attribute Names


Attribute Names (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Attribute Names
An attribute consists of an attribute identifier and a set of attribute values. The attribute identifier, also called attribute name, is a string that identifies an attribute. An attribute value is the content of the attribute and its type is not restricted to that of string. You use an attribute name when you want to specify a particular attribute for either retrieval, searches, or modification. Names are also returned by operations that return attributes (such as when you perform reads or searches in the directory).

When using attribute names, you need to be aware of certain directory server features so that you won't be surprised by the result. These features are described in the next subsections.

Attribute Type

In directories such as the LDAP, the attribute's name identifies the attribute's type and is often called the attribute type name. For example, the attribute name "cn" is also called the attribute type name. An attribute's type definition specifies the syntax that the attribute's value is to have, whether it can have multiple values, and equality and ordering rules to use when performing comparison and ordering operations on the attribute's values.

Attribute Subclassing

Some directory implementations support attribute subclassing, in which the server allows attribute types to be defined in terms of other attribute types. For example, a "name" attribute might be the superclass of all name-related attributes: "commonName" might be a subclass of "name". For directory implementations that support this, asking for the "name" attribute might return the "commonName" attribute.

When accessing directories that support attribute subclassing, you have to be aware that the server might return attributes that have names different from those that you requested. To minimize the chance of this, use the most derived subclass.

Attribute Name Synonyms

Some directory implementations support synonyms for attribute names. For example, "cn" might be a synonym for "commonName". Thus a request for the "cn" attribute might return the "commonName" attribute.

When accessing directories that support synonyms for attribute names, you must be aware that the server might return attributes that have names different from those you requested. To help prevent this from happening, use the canonical attribute name instead of one of its synonyms. The canonical attribute name is the name used in the attribute's definition; a synonym is the name that refers to the canonical attribute name in its definition.

Language Preferences

An extension to the LDAP v3 (RFC 2596) allows you to specify a language code along with an attribute name. This resembles attribute subclassing in that one attribute name can represent several different attributes. An example is a "description" attribute that has two language variations:
description: software
description;lang-en: software products
description;lang-de: Softwareprodukte
A request for the "description" attribute would return all three attributes.

When accessing directories that support this feature, you must be aware that the server might return attributes that have names different from those that you requested.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Create and Destroy Subcontexts
Next page: Read Attributes


Read Attributes (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Read Attributes
To read the attributes of an object from the directory, use DirContext.getAttributes() and pass it the name of the object for which you want the attributes. Suppose that an object in the naming service has the name "cn=Ted Geisel, ou=People". To retrieve this object's attributes, you'll need code that looks like this:
Attributes answer = ctx.getAttributes("cn=Ted Geisel, ou=People");

You can then print the contents of this answer as follows.

for (NamingEnumeration ae = answer.getAll(); ae.hasMore();) {
    Attribute attr = (Attribute)ae.next();
    System.out.println("attribute: " + attr.getID());
    /* Print each value */
    for (NamingEnumeration e = attr.getAll(); e.hasMore();
     System.out.println("value: " + e.next()))
    ;
}
This produces the following output.
# java GetattrsAll
attribute: sn
value: Geisel
attribute: objectclass
value: top
value: person
value: organizationalPerson
value: inetOrgPerson
attribute: jpegphoto
value: [B@1dacd78b
attribute: mail
value: Ted.Geisel@JNDITutorial.com
attribute: facsimiletelephonenumber
value: +1 408 555 2329
attribute: telephonenumber
value: +1 408 555 5252
attribute: cn
value: Ted Geisel

Returning Selected Attributes

To read a selective subset of attributes, you supply an array of strings that are attribute identifiers of the attributes that you want to retrieve.
// Specify the ids of the attributes to return
String[] attrIDs = {"sn", "telephonenumber", "golfhandicap", "mail"};

// Get the attributes requested
Attributes answer = ctx.getAttributes("cn=Ted Geisel, ou=People", attrIDs);
This example asks for the "sn", "telephonenumber", "golfhandicap" and "mail" attributes of the object "cn=Ted Geisel, ou=People". This object has all but the "golfhandicap" attribute, and so three attributes are returned in the answer. Following is the output of the example.
# java Getattrs
attribute: sn
value: Geisel
attribute: mail
value: Ted.Geisel@JNDITutorial.com
attribute: telephonenumber
value: +1 408 555 5252
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Attribute Names
Next page: Modify Attributes


Modify Attributes (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Modify Attributes
The DirContext interface contains methods for modifying the attributes and attribute values of objects in the directory.

Using a List of Modifications

One way to modify the attributes of an object is to supply a list of modification requests ( ModificationItem). Each ModificationItem consists of a numeric constant indicating the type of modification to make and an Attribute describing the modification to make. Following are the three types of modifications:
  • ADD_ATTRIBUTE
  • REPLACE_ATTRIBUTE
  • REMOVE_ATTRIBUTE

Modifications are applied in the order in which they appear in the list. Either all of the modifications are executed, or none are.

The following code creates a list of modifications. It replaces the "mail" attribute's value with a value of "geisel@wizards.com", adds an additional value to the "telephonenumber" attribute, and removes the "jpegphoto" attribute.

// Specify the changes to make
ModificationItem[] mods = new ModificationItem[3];

// Replace the "mail" attribute with a new value
mods[0] = new ModificationItem(DirContext.REPLACE_ATTRIBUTE,
    new BasicAttribute("mail", "geisel@wizards.com"));

// Add an additional value to "telephonenumber"
mods[1] = new ModificationItem(DirContext.ADD_ATTRIBUTE,
    new BasicAttribute("telephonenumber", "+1 555 555 5555"));

// Remove the "jpegphoto" attribute
mods[2] = new ModificationItem(DirContext.REMOVE_ATTRIBUTE,
    new BasicAttribute("jpegphoto"));
Windows Active Directory: Active Directory defines "telephonenumber" to be a single-valued attribute, contrary to RFC 2256. To get this example to work against Active Directory, you must either use an attribute other than "telephonenumber", or change the DirContext.ADD_ATTRIBUTE to DirContext.REPLACE_ATTRIBUTE.

After creating this list of modifications, you can supply it to modifyAttributes() as follows.

// Perform the requested modifications on the named object
ctx.modifyAttributes(name, mods);

Using Attributes

Alternatively, you can perform modifications by specifying the type of modification and the attributes to which to apply the modification.

For example, the following line replaces the attributes (identified in orig) associated with name with those in orig:

ctx.modifyAttributes(name, DirContext.REPLACE_ATTRIBUTE, orig);
Any other attributes of name remain unchanged.

Both of these uses of modifyAttributes() are demonstrated in the sample program. This program modifies the attributes by using a modification list and then uses the second form of modifyAttributes() to restore the original attributes.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Read Attributes
Next page: Add, Replace Bindings with Attributes


Add, Replace Bindings with Attributes (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Add, Replace Bindings with Attributes
The naming examples discussed how you can use bind(), rebind(), The DirContext interface contains overloaded versions of these methods that accept attributes. You can use these DirContext methods to associate attributes with the object at the time that the binding or subcontext is added to the namespace. For example, you might create a Person object and bind it to the namespace and at the same time associate attributes about that Person object.

Adding a Binding That Has Attributes

DirContext.bind() is used to add a binding that has attributes to a context. It accepts as arguments the name of the object, the object to be bound, and a set of attributes.
// Create the object to be bound
Fruit fruit = new Fruit("orange");

// Create attributes to be associated with the object
Attributes attrs = new BasicAttributes(true); // case-ignore
Attribute objclass = new BasicAttribute("objectclass");
objclass.add("top");
objclass.add("organizationalUnit");
attrs.put(objclass);

// Perform bind
ctx.bind("ou=favorite, ou=Fruits", fruit, attrs);
This example creates an object of class Fruit and binds it to the name "ou=favorite" into the context named "ou=Fruits", relative to ctx. This binding has the "objectclass" attribute. If you subsequently looked up the name "ou=favorite, ou=Fruits" in ctx, then you would get the fruit object. If you then got the attributes of "ou=favorite, ou=Fruits", you would get those attributes with which the object was created. Following is this example's output.
# java Bind
orange
attribute: objectclass
value: top
value: organizationalUnit
value: javaObject
value: javaNamingReference
attribute: javaclassname
value: Fruit
attribute: javafactory
value: FruitFactory
attribute: javareferenceaddress
value: #0#fruit#orange
attribute: ou
value: favorite

The extra attributes and attribute values shown are used to store information about the object (fruit). These extra attributes are discussed in more detail in the trail.

If you were to run this example twice, then the second attempt would fail with a NameAlreadyBoundException. This is because the name "ou=favorite" is already bound in the "ou=Fruits" context. For the second attempt to succeed, you would have to use rebind().

Replacing a Binding That Has Attributes

DirContext.rebind() is used to add or replace a binding and its attributes. It accepts the same arguments as bind(). However, rebind()'s semantics require that if the name is already bound, then it will be unbound and the newly given object and attributes will be bound.
// Create the object to be bound
Fruit fruit = new Fruit("lemon");

// Create attributes to be associated with the object
Attributes attrs = new BasicAttributes(true); // case-ignore
Attribute objclass = new BasicAttribute("objectclass");
objclass.add("top");
objclass.add("organizationalUnit");
attrs.put(objclass);

// Perform bind
ctx.rebind("ou=favorite, ou=Fruits", fruit, attrs);
When you run this example, it replaces the binding that the bind() example created.
# java Rebind
lemon
attribute: objectclass
value: top
value: organizationalUnit
value: javaObject
value: javaNamingReference
attribute: javaclassname
value: Fruit
attribute: javafactory
value: FruitFactory
attribute: javareferenceaddress
value: #0#fruit#lemon
attribute: ou
value: favorite
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Modify Attributes
Next page: Search


Search (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Search
One of the most useful features that a directory offers is its yellow pages, or search, service. You can compose a query consisting of attributes of entries that you are seeking and submit that query to the directory. The directory then returns a list of entries that satisfy the query. For example, you could ask the directory for all entries with a bowling average greater than 200 or all entries that represent a person with a surname beginning with "Sch."

The DirContext interface provides several methods for searching the directory, with progressive degrees of complexity and power. The various aspects of searching the directory are covered in the following sections:

  • Basic Search
  • Search Filters
  • Search Controls
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Add, Replace Bindings with Attributes
Next page: Basic Search


Basic Search (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Section: Search
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Basic Search
The simplest form of search requires that you specify the set of attributes that an entry must have and the name of the target context in which to perform the search.

The following code creates an attribute set matchAttrs, which has two attributes "sn" and "mail". It specifies that the qualifying entries must have a surname ("sn") attribute with a value of "Geisel" and a "mail" attribute with any value. It then invokes DirContext.search() to search the context "ou=People" for entries that have the attributes specified by matchAttrs.

// Specify the attributes to match
// Ask for objects that has a surname ("sn") attribute with
// the value "Geisel" and the "mail" attribute
Attributes matchAttrs = new BasicAttributes(true); // ignore attribute name case
matchAttrs.put(new BasicAttribute("sn", "Geisel"));
matchAttrs.put(new BasicAttribute("mail"));

// Search for objects that have those matching attributes
NamingEnumeration answer = ctx.search("ou=People", matchAttrs);
You can then print the results as follows.
while (answer.hasMore()) {
    SearchResult sr = (SearchResult)answer.next();
    System.out.println(">>>" + sr.getName());
    printAttrs(sr.getAttributes());
}
printAttrs()is similar to the code in the getAttributes() example that prints an attribute set.

Running this example produces the following result.

# java SearchRetAll
>>>cn=Ted Geisel
attribute: sn
value: Geisel
attribute: objectclass
value: top
value: person
value: organizationalPerson
value: inetOrgPerson
attribute: jpegphoto
value: [B@1dacd78b
attribute: mail
value: Ted.Geisel@JNDITutorial.com
attribute: facsimiletelephonenumber
value: +1 408 555 2329
attribute: cn
value: Ted Geisel
attribute: telephonenumber
value: +1 408 555 5252

Returning Selected Attributes

The previous example returned all attributes associated with the entries that satisfy the specified query. You can select the attributes to return by passing search() an array of attribute identifiers that you want to include in the result. After creating the matchAttrs as shown previously, you also need to create the array of attribute identifiers, as shown next.
// Specify the ids of the attributes to return
String[] attrIDs = {"sn", "telephonenumber", "golfhandicap", "mail"};

// Search for objects that have those matching attributes
NamingEnumeration answer = ctx.search("ou=People", matchAttrs, attrIDs);
This example returns the attributes "sn", "telephonenumber", "golfhandicap", and "mail" of entries that have an attribute "mail" and have a "sn" attribute with the value "Geisel". This example produces the following result. (The entry does not have a "golfhandicap" attribute, so it is not returned.)
# java Search
>>>cn=Ted Geisel
attribute: sn
value: Geisel
attribute: mail
value: Ted.Geisel@JNDITutorial.com
attribute: telephonenumber
value: +1 408 555 5252
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Search
Next page: Filters


Filters (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Section: Search
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Filters
In addition to specifying a search using a set of attributes, you can specify a search in the form of a search filter. A search filter is a search query expressed in the form of a logical expression. The syntax of search filters accepted by DirContext.search() is described in RFC 2254.

The following search filter specifies that the qualifying entries must have an "sn" attribute with a value of "Geisel" and a "mail" attribute with any value:

(&(sn=Geisel)(mail=*))

The following code creates a filter and default SearchControls, and uses them to perform a search. The search is equivalent to the one presented in the basic search example.

// Create the default search controls
SearchControls ctls = new SearchControls();

// Specify the search filter to match
// Ask for objects that have the attribute "sn" == "Geisel"
// and the "mail" attribute
String filter = "(&(sn=Geisel)(mail=*))";

// Search for objects using the filter
NamingEnumeration answer = ctx.search("ou=People", filter, ctls);
Running this example produces the following result.
# java SearchWithFilterRetAll
>>>cn=Ted Geisel
attribute: sn
value: Geisel
attribute: objectclass
value: top
value: person
value: organizationalPerson
value: inetOrgPerson
attribute: jpegphoto
value: [B@1dacd75e
attribute: mail
value: Ted.Geisel@JNDITutorial.com
attribute: facsimiletelephonenumber
value: +1 408 555 2329
attribute: cn
value: Ted Geisel
attribute: telephonenumber
value: +1 408 555 5252

Quick Overview of Search Filter Syntax

The search filter syntax is basically a logical expression in prefix notation (that is, the logical operator appears before its arguments). The following table lists the symbols used for creating filters.

Symbol Description
& conjunction (i.e., and -- all in list must be true)
| disjunction (i.e., or -- one or more alternatives must be true)
! negation (i.e., not -- the item being negated must not be true)
= equality (according to the matching rule of the attribute)
~= approximate equality (according to the matching rule of the attribute)
>= greater than (according to the matching rule of the attribute)
<= less than (according to the matching rule of the attribute)
=* presence (i.e., the entry must have the attribute but its value is irrelevant)
* wildcard (indicates zero or more characters can occur in that position); used when specifying attribute values to match
\ escape (for escaping '*', '(', or ')' when they occur inside an attribute value)

Each item in the filter is composed using an attribute identifier and either an attribute value or symbols denoting the attribute value. For example, the item "sn=Geisel" means that the "sn" attribute must have the attribute value "Geisel" and the item "mail=*" indicates that the "mail" attribute must be present.

Each item must be enclosed within a set of parentheses, as in "(sn=Geisel)". These items are composed using logical operators such as "&" (conjunction) to create logical expressions, as in "(& (sn=Geisel) (mail=*))".

Each logical expression can be further composed of other items that themselves are logical expressions, as in "(| (& (sn=Geisel) (mail=*)) (sn=L*))". This last example is requesting either entries that have both a "sn" attribute of "Geisel" and the "mail" attribute or entries whose "sn" attribute begins with the letter "L."

For a complete description of the syntax, see RFC 2254.

Returning Selected Attributes

The previous example returned all attributes associated with the entries that satisfy the specified filter. You can select the attributes to return by setting the search controls argument. You create an array of attribute identifiers that you want to include in the result and pass it to SearchControls.setReturningAttributes(). Here's an example.
// Specify the ids of the attributes to return
String[] attrIDs = {"sn", "telephonenumber", "golfhandicap", "mail"};
SearchControls ctls = new SearchControls();
ctls.setReturningAttributes(attrIDs);
This example is equivalent to the Returning Selected Attributes example in the Basic Search section. Running it produces the following results. (The entry does not have a "golfhandicap" attribute, so it is not returned.)
# java SearchWithFilter
>>>cn=Ted Geisel
attribute: sn
value: Geisel
attribute: mail
value: Ted.Geisel@JNDITutorial.com
attribute: telephonenumber
value: +1 408 555 5252
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Basic Search
Next page: Scope


Scope (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Section: Search
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Scope
The default SearchControls specifies that the search is to be performed in the named context ( SearchControls.ONELEVEL_SCOPE). This default is used in the examples in the Search Filters section.

In addition to this default, you can specify that the search be performed in the entire subtree or only in the named object.

Search the Subtree

A search of the entire subtree searches the named object and all of its descendants. To make the search behave in this way, pass SearchControls.SUBTREE_SCOPE to SearchControls.setSearchScope() as follows.

// Specify the ids of the attributes to return
String[] attrIDs = {"sn", "telephonenumber", "golfhandicap", "mail"};
SearchControls ctls = new SearchControls();
ctls.setReturningAttributes(attrIDs);
ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);

// Specify the search filter to match
// Ask for objects that have the attribute "sn" == "Geisel"
// and the "mail" attribute
String filter = "(&(sn=Geisel)(mail=*))";

// Search the subtree for objects by using the filter
NamingEnumeration answer = ctx.search("", filter, ctls);
This example searches the context ctx's subtree for entries that satisfy the specified filter. It finds the entry "cn= Ted Geisel, ou=People" in this subtree that satisfies the filter.
# java SearchSubtree
>>>cn=Ted Geisel, ou=People
attribute: sn
value: Geisel
attribute: mail
value: Ted.Geisel@JNDITutorial.com
attribute: telephonenumber
value: +1 408 555 5252

Search the Named Object

You can also search the named object. This is useful, for example, to test whether the named object satisfies a search filter. To search the named object, pass SearchControls.OBJECT_SCOPE to setSearchScope().

// Specify the ids of the attributes to return
String[] attrIDs = {"sn", "telephonenumber", "golfhandicap", "mail"};
SearchControls ctls = new SearchControls();
ctls.setReturningAttributes(attrIDs);
ctls.setSearchScope(SearchControls.OBJECT_SCOPE);

// Specify the search filter to match
// Ask for objects that have the attribute "sn" == "Geisel"
// and the "mail" attribute
String filter = "(&(sn=Geisel)(mail=*))";

// Search the subtree for objects by using the filter
NamingEnumeration answer =
    ctx.search("cn=Ted Geisel, ou=People", filter, ctls);
This example tests whether the object "cn=Ted Geisel, ou=People" satisfies the given filter.
# java SearchObject
>>>
attribute: sn
value: Geisel
attribute: mail
value: Ted.Geisel@JNDITutorial.com
attribute: telephonenumber
value: +1 408 555 5252
The example found one answer and printed it. Notice that the name of the result is the empty string. This is because the name of the object is always named relative to the context of the search (in this case, "cn=Ted Geisel, ou=People").
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Filters
Next page: Result Count


Result Count (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Section: Search
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Result Count
Sometimes, a query might produce too many answers and you want to limit the number of answers returned. You can do this by using the count limit search control. By default, a search does not have a count limit--it will return all answers that it finds. To set the count limit of a search, pass the number to SearchControls.setCountLimit().

The following example sets the count limit to 1.

// Set the search controls to limit the count to 1
SearchControls ctls = new SearchControls();
ctls.setCountLimit(1);
If the program attempts to get more than the count limit number of results, then a SizeLimitExceededException will be thrown. So if a program has set a count limit, then it should either differentiate this exception from other NamingExceptions or keep track of the count limit and not request more than that number of results.

Specifying a count limit for a search is one way of controlling the resources (such as memory and network bandwidth) that your application consumes. Other ways to control the resources consumed are to narrow your search filter (be more specific about what you seek), start your search in the appropriate context, and use the appropriate scope.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Scope
Next page: Time Limit


Time Limit (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Section: Search
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Time Limit
A time limit on a search places an upper bound on the amount of time that the search operation will block waiting for the answers. This is useful when you don't want to wait too long for an answer. If the time limit specified is exceeded before the search operation can be completed, then a TimeLimitExceededException will be thrown.

To set the time limit of a search, pass the number of milliseconds to SearchControls.setTimeLimit(). The following example sets the time limit to 1 second.

// Set the search controls to limit the time to 1 second (1000 ms)
SearchControls ctls = new SearchControls();
ctls.setTimeLimit(1000);
To get this particular example to exceed its time limit, you need to reconfigure it to use either a slow server, or a server that has lots of entries. Alternatively, you can use other tactics to make the search take longer than 1 second.

A time limit of zero means that no time limit has been set and that calls to the directory will wait indefinitely for an answer.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Result Count
Next page: Trouble Shooting Tips


Trouble Shooting Tips (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Naming and Directory Operations)

Trail: Java Naming and Directory Interface(TM).
Lesson: Naming and Directory Operations
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Home Page > Java Naming and Directory Interface(TM). > Naming and Directory Operations
« Previous • Trail • Next »
Trouble Shooting Tips
Here are the most common problems that you might encounter when you try to run a successfully compiled program that uses the JNDI classes.
  1. No Initial Context
  2. Connection Refused
  3. Connection Fails
  4. Program Hangs
  5. Name Not Found
  6. Cannot Connect to Arbitrary Hosts
  7. Cannot Access System Properties for Configuration
  8. Cannot Authenticate by Using CRAM-MD5

1. You get a NoInitialContextException.

Cause: You did not specify which implementation to use for the initial context. Specifically, the Context.INITIAL_CONTEXT_FACTORY environment property was not set to the class name of the factory that will create the initial context. Or, you did not make available to the program the classes of the service provider named by Context.INITIAL_CONTEXT_FACTORY.

Solution: Set the Context.INITIAL_CONTEXT_FACTORY environment property to the class name of the initial context implementation that you are using. See Configuration section for details.

If the property was set, then make sure that the class name was not mistyped, and that the class named is available to your program (either in its classpath or installed in the jre/lib/ext directory of the JRE). The Java Platform includes service providers for LDAP, COS naming, DNS, and the RMI registry. All other service providers must be installed and added to the execution environment.

2. You get a CommunicationException, indicating "connection refused."

Cause: The server and port identified by the Context.PROVIDER_URL environment property is not being served by the server. Perhaps someone has disabled or turned off the machine on which the server is running. Or, maybe you mistyped the server's name or port number.

Solution: Check that there is indeed a server running on that port, and restart the server if necessary. The way that you perform this check depends on the LDAP server that you are using. Usually, an administrative console or tool is available that you can use to administer the server. You may use that tool to verify the server's status.

3. The LDAP server responds to other utilities (such as its administration console) but does not seem to respond to your program's requests.

Cause: The server does not respond to LDAP v3 connection requests. Some servers (especially public servers) do not respond correctly to the LDAP v3, ignoring the requests instead of rejecting them. Also, some LDAP v3 servers have problems handling a control that Sun's LDAP service provider automatically sends and often return a server-specific failure code.

Solution. Try setting the environment property "java.naming.ldap.version" to "2". The LDAP service provider by default attempts to connect to an LDAP server using the LDAP v3; if that fails, then it uses the LDAP v2. If the server silently ignores the v3 request, then the provider will assume that the request worked. To work around such servers, you must explicitly set the protocol version to ensure proper behavior by the server.

If the server is a v3 server, then try setting the following environment property before creating the initial context:

env.put(Context.REFERRAL, "throw");
This will turn off the control that the LDAP provider sends automatically. (Check out the JNDI Tutorial for details.)

4. The program hangs.

Causes: Some servers (especially public ones) won't respond (not even with a negative answer) if you attempt to perform a search that would generate too many results or that would require the server to examine too many entries in order to generate the answer. Such servers are trying to limit the amount of resources that they expend on a per-request basis.

Or, you tried to use Secure Socket Layer (SSL) against a server/port that does not support it, and vice versa (that is, you tried to use a plain socket to talk to an SSL port).

And lastly, the server is either responding very slowly due to heavy load or is not responding at all for some reason.

Solution: If your program is hanging because the server is trying to restrict the use of its resources, then retry your request using a query that will return a single result or only a few results. This will help you to determine whether the server is alive. If it is, then you can broaden your initial query and resubmit it.

If your program is hanging because of SSL problems, then you need to find out whether the port is an SSL port and then set the Context.SECURITY_PROTOCOL environment property appropriately. If the port is an SSL port, then this property should be set to "ssl". If it is not an SSL port, then this property should not be set.

If you program is hanging for none of the above reasons the property com.sun.jndi.ldap.read.timeout comes in handy to specify the read timeout. The value of this property is the string representation of an integer representing the read timeout in milliseconds for LDAP operations. If the LDAP provider cannot get a LDAP response within that period, it aborts the read attempt. The integer should be greater than zero. An integer less than or equal to zero means no read timeout is specified which is equivalent to waiting for the response infinitely until it is received.

If this property is not specified, the default is to wait for the response until it is received.

For example,

env.put("com.sun.jndi.ldap.read.timeout", "5000");
causes the LDAP service provider to abort the read attempt if the server does not respond with a reply within 5 seconds.

5. You get a NameNotFoundException.

Causes: When you initialized the initial context for the LDAP, you supply a root-distinguished name. For example, if you set the Context.PROVIDER_URL environment property for the initial context to "ldap://ldapserver:389/o=JNDITutorial" and subsequently supplied a name such as "cn=Joe,c=us", then the full name that you passed to the LDAP service was "cn=Joe,c=us,o=JNDITutorial". If this was really the name that you intended, then you should check your server to make sure that it contains such an entry.

Also, the Sun Java Directory Server return this error if you supply an incorrect distinguished name for authentication purposes. For example, the LDAP provider will throw a NameNotFoundException if you set the Context.SECURITY_PRINCIPAL environment property to "cn=Admin, o=Tutorial", and "cn=Admin, o=Tutorial" is not an entry on the LDAP server. The correct error for the Sun Java Directory Server to return actually should be something related to authentication, rather than "name not found."

Solution: Verify the name that you supplied is that of an entry existing on the server. You can do this by listing the entry's parent context or using some other tool such as the directory server's administration console.

Here are some problems that you might encounter when trying to deploy an applet that uses the JNDI classes.

6. You get an AppletSecurityException when your applet attempts to communicate with a directory server that is running on a machine different from the one from which the applet was loaded

Cause: Your applet was not signed, so it can connect only to the machine from which it was loaded. Or, if the applet was signed, the browser has not granted the applet permission to connect to the directory server machine.

Solution: If you want to allow the applet to connect to directory servers running on arbitrary machines, then you need to sign both your applet and all of the JNDI JARs that your applet will be using. For information on signing jars, see Signing and Verifying JAR files .

7. You get an AppletSecurityException when your applet attempts to set up the environment properties using system properties.

Cause: Web browsers limit access to system properties and throw a SecurityException if you attempt to read them.

Solution: If you need to obtain input for your applet, then try using applet params instead.

8. You get an AppletSecurityException when an applet running inside Firefox attempts to authenticate using CRAM-MD5 to the LDAP server.

Cause: Firefox disables access to the java.security packages. The LDAP provider used the message digest functionality provided by java.security.MessageDigest for implementing CRAM-MD5.

Solution: Use the Java Plug-in.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Time Limit
Next page: Advanced Topics for LDAP Users


Lesson: Advanced Topics for LDAP Users (The Java™ Tutorials > Java Naming and Directory Interface(TM).)

Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Trail: Java Naming and Directory Interface(TM).
Home Page > Java Naming and Directory Interface(TM).
« Previous • Trail • Next »
Lesson: Advanced Topics for LDAP Users
The lessons in the LDAP trail provide details on the mapping between the LDAP and the JNDI. They also give hints and tips for accessing the LDAP service through the JNDI.

LDAP

X.500, is a CCITT standard for directory services that is part of the OSI suite of services. X.500 standard defines a protocol (among others) for a client application to access the X.500 directory called the Directory Access Protocol (DAP). It is layered on top of the Open Systems Interconnection (OSI) protocol stack.

The Internet community, recognizing the need for an X.500-like service but faced with different underlying network infrastructure (TCP/IP instead of OSI), designed a new protocol based on the X.500 DAP protocol, called Lightweight DAP, or LDAP. RFC 2251 defines what is now called version 3 of the LDAP (or LDAP v3), an improved version of its predecessor LDAP v2 specified in RFC 1777.

The goal of the LDAP was a protocol that could be easily implemented, with special focus on being able to build small and simple clients. One way that it attempted to achieve simplification was to use a lot of strings and to minimize wherever possible the use of structures. DNs, for example, are represented in the protocol as strings, as are attribute type names and many attribute values.

The protocol consists of the client's sending requests to the server, to which the server responds, though not necessarily in the same order in which the requests were sent. Each request is tagged with an ID so that requests and responses can be matched. The protocol works over either TCP or UDP, although the TCP version is most commonly used.

Because of the focus on clients, the LDAP community also defined standards for the string representation of DNs (RFC 2553), search filters (RFC 1960), and attribute syntaxes (RFC 1778), for a C language based API (RFC 1823), and for the format of URLs for accessing LDAP services (RFC 1959).

LDAP v3 supports internationalization, various authentication mechanisms, referrals, and a generic deployment mechanism. It allows new features to be added to the protocol without also requiring changes to the protocol by using extensions and controls.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: LDAP v3


LDAP v3 (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
LDAP v3

Internationalization

Internationalization is addressed via an international character set (ISO 10646) to represent protocol elements that are strings (such as DNs). Version 3 also differs from version 2 in that it uses UTF-8 to encode its strings.

Authentication

In addition to anonymous, simple (clear-text password) authentication, LDAP v3 uses the Simple Authentication and Security Layer (SASL) authentication framework (RFC 2222) to allow different authentication mechanisms to be used with the LDAP. SASL specifies a challenge-response protocol in which data is exchanged between the client and the server for the purposes of authentication.

Several SASL mechanisms are currently defined: DIGEST-MD5, CRAM-MD5, Anonymous, External, S/Key, GSSAPI, and Kerberos v4. An LDAP v3 client can use any of these SASL mechanisms, provided that the LDAP v3 server supports them. Moreover, new (yet-to-be defined) SASL mechanisms can be used without changes to the LDAP having to be made.

Referrals

A referral is information that a server sends back to the client indicating that the requested information can be found at another location (possibly at another server). In the LDAP v2, servers are supposed to handle referrals and not return them to the client. This is because handling referrals can be very complicated and therefore would result in more-complicated clients. As servers were built and deployed, referrals were found to be useful, but not many servers supported server-side referral handling. So a way was found to retrofit the protocol to allow it to return referrals. This was done by placing the referral inside of the error message of a "partial result" error response.

The LDAP v3 has explicit support for referrals and allows servers to return the referrals directly to the client. Referrals won't be covered in this lesson but you can always refer to JNDI Tutorial for managing referrals in your application.

Deployment

A common protocol such as the LDAP is useful for ensuring that all of the directory clients and servers "speak the same language." When many different directory client applications and directory servers are deployed in a network, it also is very useful for all of these entities to talk about the same objects.

A directory schema specifies, among other things, the types of objects that a directory may have and the mandatory and optional attributes that each type of object may have. The LDAP v3 defines a schema (RFC 2252 and RFC 2256) based on the X.500 standard for common objects found in the network, such as countries, localities, organizations, users/persons, groups, and devices. It also defines a way for a client application to access the server's schema so that it can find out the types of objects and attributes that a particular server supports.

The LDAP v3 further defines a set of syntaxes for representing attribute values (RFC 2252). For writing Java Applications that need to access schema please refer to the JNDI Tutorial

Extensions

In addition to the repertoire of predefined operations, such as "search" and "modify," the LDAP v3 defines an "extended" operation. The "extended" operation takes a request as an argument and returns a response. The request contains an identifier that identifies the request and the arguments of the request. The response contains the results of performing the request. The pair of "extended" operation request/response is called an extension. For example, there can be an extension for Start TLS, which is a request for the client to the server to activate the Start TLS protocol.

These extensions can be standard (defined by the LDAP community) or proprietary (defined by a particular directory vendor). For writing applications that need to use Extensions refer to the JNDI Tutorial

Controls

Another way to add new features is by using a control. The LDAP v3 allows the behavior of any operation to be modified through the use of controls. Any number of controls may be sent along with an operation, and any number of controls may be returned with its results. For example, you can send a Sort control along with a "search" operation that tells the server to sort the results of the search according to the "name" attribute.

Like extensions, such controls can be standard or proprietary. The standard controls are provided in the platform For writing applications that need to use controls refer to the JNDI Tutorial

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Advanced Topics for LDAP Users
Next page: JNDI as an LDAP API


JNDI as an LDAP API (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
JNDI as an LDAP API
Both the JNDI and LDAP models define a hierarchical namespace in which you name objects. Each object in the namespace may have attributes that can be used to search for the object. At this high level, the two models are similar, so it is not surprising that the JNDI maps well to the LDAP.

Models

You can think of an LDAP entry as a JNDI DirContext. Each LDAP entry contains a name and a set of attributes, as well as an optional set of child entries. For example, the LDAP entry "o=JNDITutorial" may have as its attributes "objectclass" and "o", and it may have as its children "ou=Groups" and "ou=People".

In the JNDI, the LDAP entry "o=JNDITutorial" is represented as a context with the name "o=JNDITutorial" that has two subcontexts, named: "ou=Groups" and "ou=People". An LDAP entry's attributes are represented by the Attributes interface, whereas individual attributes are represented by the Attribute interface.

See the next part of this lesson for details on how the LDAP operations are accessed through the JNDI.

Names

As a result of federation, the names that you supply to the JNDI's context methods can span multiple namespaces. These are called composite names. When using the JNDI to access an LDAP service, you should be aware that the forward slash character ("/") in a string name has special meaning to the JNDI. If the LDAP entry's name contains this character, then you need to escape it (using the backslash character ("\")). For example, an LDAP entry with the name "cn=O/R" must be presented as the string "cn=O\\/R" to the JNDI context methods. For more information about Names check out the JNDI Tutorial . The LdapName and Rdn classes simplify creation and manipulation of LDAP names.

LDAP names as they are used in the protocol are always fully qualified names that identify entries that start from the root of the LDAP namespace (as defined by the server). Following are some examples of fully qualified LDAP names.

cn=John Smith, ou=Marketing, o=Some Corporation, c=gb
cn=Vinnie Ryan, ou=People, o=JNDITutorial

In the JNDI, however, names are always relative; that is, you always name an object relative to a context. For example, you can name the entry "cn=Vinnie Ryan" relative to the context named "ou=People, o=JNDITutorial". Or you can name the entry "cn=Vinnie Ryan, ou=People" relative to the context named "o=JNDITutorial". Or, you can create an initial context that points at the root of the LDAP server's namespace and name the entry "cn=Vinnie Ryan, ou=People, o=JNDITutorial".

In the JNDI, you can also use LDAP URLs to name LDAP entries. See the LDAP URL discussion in the JNDI Tutorial

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: LDAP v3
Next page: How LDAP Operations Map to JNDI APIs


How LDAP Operations Map to JNDI APIs (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: JNDI as an LDAP API
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
How LDAP Operations Map to JNDI APIs
The LDAP defines a set of operations or requests (see RFC 2251). In the JNDI, these map to operations on the DirContext and LdapContext interfaces (which are sub interfaces of Context). For example, when a caller invokes a DirContext method, the LDAP service provider implements the method by sending LDAP requests to the LDAP server.

The following table shows how operations in the LDAP correspond to JNDI methods.

LDAP Operation | Corresponding JNDI Methods
bind | The corresponding way of creating an initial connection to the LDAP server in the JNDI is the creation of an InitialDirContext. When the application creates an initial context, it supplies client authentication information via environment properties. To change that authentication information for an existing context, use Context.addToEnvironment() and Context.removeFromEnvironment().
unbind | Context.close() is used to free resources used by a context. It differs from the LDAP "unbind" operation in that within a given service provider implementation, resources can be shared among contexts, so closing one context won't free all of the resources if those resources are being shared with another context. Make sure to close all contexts if your intent is to free all resources.
search | The corresponding method in the JNDI is the overloading of DirContext.search() that accepts a search filter (RFC 2254). See the filter example.
modify | The corresponding method in the JNDI is the overloading of DirContext.modifyAttributes() that accepts an array of DirContext.ModificationItems. See the Modify Attributes section for an example.
add | The corresponding methods in the JNDI are DirContext.bind() and DirContext.createSubcontext(). You can use either to add a new LDAP entry. Using bind(), you can specify not only a set of attributes for the new entry but also a Java object to be added along with the attributes. See the Add, replace bindings with Attributes section for an example.
delete | The corresponding methods in the JNDI are Context.unbind() and Context.destroySubcontext(). You can use either to remove an LDAP entry.
modify DN/RDN | The corresponding method in the JNDI is Context.rename(). See the Renaming Objects section for more details.
compare | The corresponding operation in the JNDI is a suitably constrained DirContext.search(). See the LDAP Compare section for an example.
abandon | When you close a context, all of its outstanding requests are abandoned. Similarly, when you close a NamingEnumeration, the corresponding LDAP "search" request is abandoned.
extended operation | The corresponding method in the JNDI is LdapContext.extendedOperation(). See the JNDI Tutorial for more details.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: JNDI as an LDAP API
Next page: How LDAP Error Codes Map to JNDI Exceptions


How LDAP Error Codes Map to JNDI Exceptions (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: JNDI as an LDAP API
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
How LDAP Error Codes Map to JNDI Exceptions
The LDAP defines a set of status codes that are returned with LDAP responses sent by the LDAP server (see RFC 2251). In the JNDI, error conditions are indicated as checked exceptions that are subclasses of NamingException. See the Naming Exceptions section for an overview of the JNDI exception classes.

The LDAP service provider translates the LDAP status code it receives from the LDAP server to the appropriate subclass of NamingException. The following table shows the mapping between LDAP status codes and JNDI exceptions.

LDAP Status Code | Meaning | Exception or Action
0 | Success | Report success.
1 | Operations error | NamingException
2 | Protocol error | CommunicationException
3 | Time limit exceeded. | TimeLimitExceededException
4 | Size limit exceeded. | SizeLimitExceededException
5 | Compared false. | Used by DirContext.search(). Does not generate an exception.
6 | Compared true. | Used by DirContext.search(). Does not generate an exception.
7 | Authentication method not supported. | AuthenticationNotSupportedException
8 | Strong authentication required. | AuthenticationNotSupportedException
9 | Partial results being returned. | If the environment property "java.naming.referral" is set to "ignore" or the contents of the error do not contain a referral, throw a PartialResultException. Otherwise, use contents to build a referral.
10 | Referral encountered. | If the environment property "java.naming.referral" is set to "ignore", then ignore. If the property is set to "throw", throw ReferralException. If the property is set to "follow", then the LDAP provider processes the referral. If the "java.naming.ldap.referral.limit" property has been exceeded, throw LimitExceededException.
11 | Administrative limit exceeded. | LimitExceededException
12 | Unavailable critical extension requested. | OperationNotSupportedException
13 | Confidentiality required. | AuthenticationNotSupportedException
14 | SASL bind in progress. | Used internally by the LDAP provider during authentication.
16 | No such attribute exists. | NoSuchAttributeException
17 | An undefined attribute type. | InvalidAttributeIdentifierException
18 | Inappropriate matching | InvalidSearchFilterException
19 | A constraint violation. | InvalidAttributeValueException
20 | An attribute or value already in use. | AttributeInUseException
21 | An invalid attribute syntax. | InvalidAttributeValueException
32 | No such object exists. | NameNotFoundException
33 | Alias problem | NamingException
34 | An invalid DN syntax. | InvalidNameException
35 | Is a leaf. | Used by the LDAP provider; usually doesn't generate an exception.
36 | Alias dereferencing problem | NamingException
48 | Inappropriate authentication | AuthenticationNotSupportedException
49 | Invalid credentials | AuthenticationException
50 | Insufficient access rights | NoPermissionException
51 | Busy | ServiceUnavailableException
52 | Unavailable | ServiceUnavailableException
53 | Unwilling to perform | OperationNotSupportedException
54 | Loop detected. | NamingException
64 | Naming violation | InvalidNameException
65 | Object class violation | SchemaViolationException
66 | Not allowed on non-leaf. | ContextNotEmptyException
67 | Not allowed on RDN. | SchemaViolationException
68 | Entry already exists. | NameAlreadyBoundException
69 | Object class modifications prohibited. | SchemaViolationException
71 | Affects multiple DSAs. | NamingException
80 | Other | NamingException

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How LDAP Operations Map to JNDI APIs
Next page: Security


Security (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
Security
An LDAP service provides a generic directory service. It can be used to store information of all sorts. All LDAP servers have some system in place for controlling who can read and update the information in the directory.

To access the LDAP service, the LDAP client first must authenticate itself to the service. That is, it must tell the LDAP server who is going to be accessing the data so that the server can decide what the client is allowed to see and do. If the client authenticates successfully to the LDAP server, then when the server subsequently receives a request from the client, it will check whether the client is allowed to perform the request. This process is called access control.

The LDAP standard has proposed ways in which LDAP clients can authenticate to LDAP servers (RFC 2251 and RFC 2829). These are discussed in general in the LDAP Authentication section and Authentication Mechanisms section. This lesson also contains descriptions of how to use the anonymous, simple and SASL authentication mechanisms.

Access control is supported in different ways by different LDAP server implementations. It is not discussed in this lesson.

Another security aspect of the LDAP service is support the use of secure channels to communicate with clients, for example to send and receive attributes that contain secrets, such as passwords and keys. LDAP servers use SSL for this purpose. This lesson also shows how to use SSL with the LDAP service provider.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: How LDAP Error Codes Map to JNDI Exceptions
Next page: Modes of Authenticating to LDAP


Modes of Authenticating to LDAP (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: Security
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
Modes of Authenticating to LDAP
In the LDAP, authentication information is supplied in the "bind" operation. In LDAP v2, a client initiates a connection with the LDAP server by sending the server a "bind" operation that contains the authentication information.

In the LDAP v3, this operation serves the same purpose, but it is optional. A client that sends an LDAP request without doing a "bind" is treated as an anonymous client (see the Anonymous Authentication section for details). In the LDAP v3, the "bind" operation may be sent at any time, possibly more than once, during the connection. A client can send a "bind" request in the middle of a connection to change its identity. If the request is successful, then all outstanding requests that use the old identity on the connection are discarded and the connection is associated with the new identity.

The authentication information supplied in the "bind" operation depends on the authentication mechanism that the client chooses. See the next section for a discussion of the authentication mechanism.

Authenticating to the LDAP by Using the JNDI

In the JNDI, authentication information is specified in environment properties. When you create an initial context by using the InitialDirContext class (or its superclass or subclass), you supply a set of environment properties, some of which might contain authentication information. You can use the following environment properties to specify the authentication information.
  • Context.SECURITY_AUTHENTICATION ("java.naming.security.authentication").
    Specifies the authentication mechanism to use. For the Sun LDAP service provider, this can be one of the following strings: "none", "simple", sasl_mech, where sasl_mech is a space-separated list of SASL mechanism names. See the next section for a description of these strings.

  • Context.SECURITY_PRINCIPAL ("java.naming.security.principal").
    Specifies the name of the user/program doing the authentication and depends on the value of the Context.SECURITY_AUTHENTICATION property. See the next few sections in this lesson for details and examples.

  • Context.SECURITY_CREDENTIALS ("java.naming.security.credentials").
    Specifies the credentials of the user/program doing the authentication and depends on the value of the Context.SECURITY_AUTHENTICATION property. See the next few sections in this lesson for details and examples.
When the initial context is created, the underlying LDAP service provider extracts the authentication information from these environment properties and uses the LDAP "bind" operation to pass them to the server.

The following example shows how, by using a simple clear-text password, a client authenticates to an LDAP server.

// Set up the environment for creating the initial context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

// Authenticate as S. User and password "mysecret"
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=S. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "mysecret");

// Create the initial context
DirContext ctx = new InitialDirContext(env);

// ... do something useful with ctx

Using Different Authentication Information for a Context

If you want to use different authentication information for an existing context, then you can use Context.addToEnvironment() and Context.removeFromEnvironment() to update the environment properties that contain the authentication information. Subsequent invocations of methods on the context will use the new authentication information to communicate with the server.

The following example shows how the authentication information of a context is changed to "none" after the context has been created.

// Authenticate as S. User and the password "mysecret"
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=S. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "mysecret");

// Create the initial context
DirContext ctx = new InitialDirContext(env);

// ... do something useful with ctx

// Change to using no authentication
ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "none");

// ... do something useful with ctx

Authentication Failures

Authentication can fail for a number of reasons. For example, if you supply incorrect authentication information, such as an incorrect password or principal name, then an AuthenticationException is thrown.

Here's an example that is a variation of the previous example. This time, an incorrect password causes the authentication to fail.

// Authenticate as S. User and give an incorrect password
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=S. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "notmysecret");
This produces the following output.
javax.naming.AuthenticationException: [LDAP: error code 49 - Invalid Credentials]
    ...

Because different servers support different authentication mechanisms, you might request an authentication mechanism that the server does not support. In this case, an AuthenticationNotSupportedException will be thrown.

Here's an example that is a variation of the previous example. This time, an unsupported authentication mechanism ("custom") causes the authentication to fail.

// Authenticate as S. User and the password "mysecret"
env.put(Context.SECURITY_AUTHENTICATION, "custom");
env.put(Context.SECURITY_PRINCIPAL, "cn=S. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "mysecret");
This produces the following output.
javax.naming.AuthenticationNotSupportedException: custom
    ...
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Security
Next page: Authentication Mechanisms


Authentication Mechanisms (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: Security
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
Authentication Mechanisms
Different versions of the LDAP support different types of authentication. The LDAP v2 defines three types of authentication: anonymous, simple (clear-text password), and Kerberos v4.

The LDAP v3 supports anonymous, simple, and SASL authentication. SASL is the Simple Authentication and Security Layer (RFC 2222). It specifies a challenge-response protocol in which data is exchanged between the client and the server for the purposes of authentication and establishment of a security layer on which to carry out subsequent communication. By using SASL, the LDAP can support any type of authentication agreed upon by the LDAP client and server.

This lesson contains descriptions of how to authenticate by using anonymous, simple, and SASL authentication.

Specifying the Authentication Mechanism

The authentication mechanism is specified by using the Context.SECURITY_AUTHENTICATION environment property. The property may have one of the following values.

sasl_mech | A space-separated list of SASL mechanism names. Use one of the SASL mechanisms listed (e.g., "CRAM-MD5" means to use the CRAM-MD5 SASL mechanism described in RFC 2195).
none | Use no authentication (anonymous)
simple | Use weak authentication (clear-text password)

The Default Mechanism

If the client does not specify any authentication environment properties, then the default authentication mechanism is "none". The client will then be treated as an anonymous client.

If the client specifies authentication information without explicitly specifying the Context.SECURITY_AUTHENTICATION property, then the default authentication mechanism is "simple".

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Modes of Authenticating to LDAP
Next page: Anonymous


Anonymous (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: Security
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
Anonymous
As just stated, the default authentication mechanism is "none" if no authentication environment properties have been set. If the client sets the Context.SECURITY_AUTHENTICATION environment property to "none", then the authentication mechanism is "none" and all other authentication environment properties are ignored. You would want to do this explicitly only to ensure that any other authentication properties that might have been set are ignored. In either case, the client will be treated as an anonymous client. This means that the server does not know or care who the client is and will allow the client to access (read and update) any data that has been configured to be accessible by any unauthenticated client.

Because none of the directory examples in the Naming and Directory Operations lesson set any of the authentication environment properties, all of them use anonymous authentication.

Here is an example that explicitly sets the Context.SECURITY_AUTHENTICATION property to "none" (even though doing this is not strictly necessary because that is the default).

// Set up the environment for creating the initial context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

// Use anonymous authentication
env.put(Context.SECURITY_AUTHENTICATION, "none");

// Create the initial context
DirContext ctx = new InitialDirContext(env);

// ... do something useful with ctx
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Authentication Mechanisms
Next page: Simple


Simple (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: Security
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
Simple
Simple authentication consists of sending the LDAP server the fully qualified DN of the client (user) and the client's clear-text password (see RFC 2251 and RFC 2829). This mechanism has security problems because the password can be read from the network. To avoid exposing the password in this way, you can use the simple authentication mechanism within an encrypted channel (such as SSL), provided that this is supported by the LDAP server.

Both the LDAP v2 and v3 support simple authentication.

To use the simple authentication mechanism, you must set the three authentication environment properties as follows.

Context.SECURITY_AUTHENTICATION.
Set to "simple".
Context.SECURITY_PRINCIPAL.
Set to the fully qualified DN of the entity that is being authenticated (e.g., "cn=S. User, ou=NewHires, o=JNDITutorial"). It is of type java.lang.String.
Context.SECURITY_CREDENTIALS.
Set to the password of the principal (e.g., "mysecret"). It is of type java.lang.String, char array (char[]), or byte array (byte[]). If the password is a java.lang.String or a char array, then it is encoded using UTF-8 for the LDAP v3 and using ISO-Latin-1 for the LDAP v2 for transmission to the server. If the password is a byte[], then it is transmitted as is to the server.
See the example earlier in this section that illustrates how to use simple authentication.
Note: If you supply an empty string, an empty byte/char array, or null to the Context.SECURITY_CREDENTIALS environment property, then the authentication mechanism will be "none". This is because the LDAP requires the password to be nonempty for simple authentication. The protocol automatically converts the authentication to "none" if a password is not supplied.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Anonymous
Next page: SASL


SASL (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: Security
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
SASL
The LDAP v3 protocol uses the SASL to support pluggable authentication. This means that the LDAP client and server can be configured to negotiate and use possibly nonstandard and/or customized mechanisms for authentication, depending on the level of protection desired by the client and the server. The LDAP v2 protocol does not support the SASL.

Several SASL mechanisms are currently defined:

  • Anonymous (RFC 2245)
  • CRAM-MD5 (RFC 2195)
  • Digest-MD5 (RFC 2831)
  • External (RFC 2222)
  • Kerberos V4 (RFC 2222)
  • Kerberos V5 (RFC 2222)
  • SecurID (RFC 2808)
  • S/Key (RFC 2222)

SASL Mechanisms Supported by LDAP Servers

Of the mechanisms on the previous list, popular LDAP servers (such as those from Sun, OpenLDAP, and Microsoft) support External, Digest-MD5, and Kerberos V5. RFC 2829 proposes the use of Digest-MD5 as the mandatory default mechanism for LDAP v3 servers.

Here is a simple program for finding out the list of SASL mechanisms that an LDAP server supports.

// Create initial context
DirContext ctx = new InitialDirContext();

// Read supportedSASLMechanisms from root DSE
Attributes attrs = ctx.getAttributes(
    "ldap://localhost:389", new String[]{"supportedSASLMechanisms"});
Here is the output produced by running this program against a server that supports the External SASL mechanism.
{supportedsaslmechanisms=supportedSASLMechanisms: EXTERNAL, GSSAPI, DIGEST-MD5}

Specifying the Authentication Mechanism

To use a particular SASL mechanism, you specify its Internet Assigned Numbers Authority (IANA)-registered mechanism name in the Context.SECURITY_AUTHENTICATION environment property. You can also specify a list of mechanisms for the LDAP provider to try. This is done by specifying an ordered list of space-separated mechanism names. The LDAP provider will use the first mechanism for which it finds an implementation.

Here's an example that asks the LDAP provider to try to get the implementation for the DIGEST-MD5 mechanism and if that's not available, use the one for GSSAPI.

env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5 GSSAPI");
You might get this list of authentication mechanisms from the user of your application. Or you might get it by asking the LDAP server, via a call similar to that shown previously. The LDAP provider itself does not consult the server for this information. It simply attempts to locate and use the implementation of the specified mechanisms.

The LDAP provider in the platform has built-in support for the External, Digest-MD5, and GSSAPI (Kerberos v5) SASL mechanisms. You can add support for additional mechanisms.

Specifying Input for the Authentication Mechanism

Some mechanisms, such as External, require no additional input--the mechanism name alone is sufficient for the authentication to proceed. The External example shows how to use the External SASL mechanism.

Most other mechanisms require some additional input. Depending on the mechanism, the type of input might vary. Following are some common inputs required by mechanisms.

  • Authentication id. The identity of the entity performing the authentication.
  • Authorization id. The identity of the entity for which access control checks should be made if the authentication succeeds.
  • Authentication credentials. For example, a password or a key.
The authentication and authorization ids might differ if the program (such as a proxy server) is authenticating on behalf of another entity. The authentication id is specified by using the Context.SECURITY_PRINCIPAL environment property. It is of type java.lang.String.

The password/key of the authentication id is specified by using the Context.SECURITY_CREDENTIALS environment property. It is of type java.lang.String, char array (char[]), or byte array (byte[]). If the password is a byte array, then it is transformed into a char array by using an UTF-8 encoding.

If the "java.naming.security.sasl.authorizationId" property has been set, then its value is used as the authorization ID. Its value must be of type java.lang.String. By default, the empty string is used as the authorization ID, which directs the server to derive an authorization ID from the client's authentication credentials.

The Digest-MD5 example shows how to use the Context.SECURITY_PRINCIPAL and Context.SECURITY_CREDENTIALS properties for Digest-MD5 authentication.

If a mechanism requires input other than those already described, then you need to define a callback object for the mechanism to use, you can check out the callback example in the JNDI Tutorial . The next part of this lesson discusses how to use SASL Digest-MD5 authentication mechanism. The SASL Policies , GSS API (Kerberos v5) and CRAM-MD5 mechanisms are covered in the JNDI Tutorial.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Simple
Next page: Digest-MD5


Digest-MD5 (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: Security
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
Digest-MD5
Digest-MD5 authentication is the required authentication mechanism for LDAP v3 servers (RFC 2829). Because the use of SASL is part of the LDAP v3 (RFC 2251), servers that support only the LDAP v2 do not support Digest-MD5.

The Digest-MD5 mechanism is described in RFC 2831. It is based on the HTTP Digest Authentication (RFC 2617). In Digest-MD5, the LDAP server sends data that includes various authentication options that it is willing to support plus a special token to the LDAP client. The client responds by sending an encrypted response that indicates the authentication options that it has selected. The response is encrypted in such a way that proves that the client knows its password. The LDAP server then decrypts and verifies the client's response.

To use the Digest-MD5 authentication mechanism, you must set the authentication environment properties as follows.

Context.SECURITY_AUTHENTICATION.
Set to the string "DIGEST-MD5".
Context.SECURITY_PRINCIPAL.
Set to the principal name. This is a server-specific format. Some servers support a login user id format, such as that defined for Unix or Windows login screens. Others accept a distinguished name. Yet others use the authorization id formats defined in RFC 2829. In that RFC, the name should be either the string "dn:", followed by the fully qualified DN of the entity being authenticated, or the string "u:", followed by the user id. Some servers accept multiple formats. Examples of some of these formats are "cuser", "dn: cn=C. User, ou=NewHires, o=JNDITutorial", and "u: cuser" The data type of this property must be java.lang.String.
Context.SECURITY_CREDENTIALS.
Set to the password of the principal (e.g., "mysecret"). It is of type java.lang.String, char array (char[]), or byte array (byte[]). If the password is a java.lang.String or char[], then it is encoded by using UTF-8 for transmission to the server. If the password is a byte[], then it is transmitted as is to the server.

The following example shows how a client performs authentication using Digest-MD5 to an LDAP server.

// Set up the environment for creating the initial context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

// Authenticate as C. User and password "mysecret"
env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
env.put(Context.SECURITY_PRINCIPAL, "dn:cn=C. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "mysecret");

// Create the initial context
DirContext ctx = new InitialDirContext(env);

// ... do something useful with ctx
Note: The Sun Java Directory Server, v5.2 supports the Digest-MD5 authentication mechanism for users that have clear-text passwords. You must set the password encryption mode before you create the user. If you have already created the user, delete it and recreate it. To set the password encryption mode using the Administration Console, select the Configuration tab and the Data node. In the Passwords pane, select the "No encryption (CLEAR)" option for "Password encryption." The server accepts simple user names (that is, the value of the "uid" attribute for entries that have one) and the "dn:" format of user names. See the server's documentation for detailed information.

Specifying the Realm

A realm defines the namespace from which the authentication entity (the value of the Context.SECURITY_PRINCIPAL property) is selected. A server might have multiple realms. For example, a server for a university might be configured to have two realms, one for its student users and another for faculty users. Realm configuration is done by the directory administrator. Some directories have a default single realm. For example, the Sun Java Directory Server, v5.2, uses the fully qualified hostname of the machine as the default realm.

In Digest-MD5 authentication, you must authenticate to a specific realm. You may use the following authentication environment property to specify the realm. If you do not specify a realm, then any one of the realms offered by the server will be used.

java.naming.security.sasl.realm
Set to the realm of the principal. This is a deployment-specific and/or server-specific case-sensitive string. It identifies the realm or domain from which the principal name (Context.SECURITY_PRINCIPAL) should be chosen. If this realm does not match one of the realms offered by the server, then the authentication fails.

The following example shows how to set the environment properties for performing authentication using Digest-MD5 and a specified realm. To make this example work in your environment, you must change the source code so that the realm value reflects what has been configured on your directory server.

// Authenticate as C. User and password "mysecret" in realm "JNDITutorial"
env.put(Context.SECURITY_AUTHENTICATION, "DIGEST-MD5");
env.put(Context.SECURITY_PRINCIPAL, "dn:cn=C. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "mysecret");
env.put("java.naming.security.sasl.realm", "JNDITutorial");
If you need to use privacy protection and other SASL properties, these are discussed in the JNDI Tutorial.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: SASL
Next page: SSL and Custom Sockets


SSL and Custom Sockets (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: Security
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
SSL and Custom Sockets
In addition to SASL authentication, most LDAP servers allow their services to be accessed through SSL. SSL is especially useful for LDAP v2 servers because the v2 protocol does not support SASL authentication.

An SSL-enabled server often supports SSL in two ways. In the most basic way, the server supports SSL ports in addition to normal (unprotected) ports. The other way in which a server supports SSL is via the use of the Start TLS Extension (RFC 2830). This option is available only to LDAP v3 servers and is described in detail in the section.

Using the SSL Socket Property

By default, Sun's LDAP service provider uses plain sockets when communicating with the LDAP server. To request that SSL sockets be use, set the Context.SECURITY_PROTOCOL property to "ssl".

In the following example, the LDAP server is offering SSL at port 636. To run this program, you must enable SSL on port 636 on your LDAP server. This procedure is typically carried out by the directory's administrator.

Server Requirements: The LDAP server must be set up with an X.509 SSL server certificate and have SSL enabled. Typically, you must first obtain a signed certificate for the server from a certificate authority (CA). Then, follow the instructions from your directory vendor on how to enable SSL. Different vendors have different tools for doing this.

For the Sun Java Directory Server, v5.2, use the Manage Certificates tool in the Administration Console to generate a Certificate Signing Request (CSR). Submit the CSR to a CA to obtain an X.509 SSL server certificate. Using the Administration Console, add the certificate to the server's list of certificates. Also install the CA's certificate if it is not already in the server's list of trusted CAs. Enable SSL by using the Configuration tab in the Administration Console. Select the server in the left pane. Select the Encryption tab in the right pane. Click the checkboxes for "Enable SSL for this server" and "Use this cipher family: RSA", ensuring that the server certificate you have added is in the list of certificates.

Client Requirements: You need to ensure that the client trusts the LDAP server that you'll be using. You must install the server's certificate (or its CA's certificate) in your JRE's database of trusted certificates. Here is an example.

# cd JAVA_HOME/lib/security
# keytool -import -file server_cert.cer -keystore jssecacerts
For information on how to use the security tools, see the Security trail. For information on the JSSE, read the JSSE Reference Guide.
// Set up the environment for creating the initial context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:636/o=JNDITutorial");

// Specify SSL
env.put(Context.SECURITY_PROTOCOL, "ssl");

// Authenticate as S. User and password "mysecret"
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=S. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "mysecret");

// Create the initial context
DirContext ctx = new InitialDirContext(env);

// ... do something useful with ctx

Note: If you use SSL to connect to a server on a port that is not using SSL, then your program will hang. Similarly, if you use a plain socket to connect to a server's SSL socket, then your application will hang. This is a characteristic of the SSL protocol.

Using the LDAPS URL

 Instead of requesting the use of SSL via the use of the Context.SECURITY_PROTOCOL property, you can also request the use of SSL via the use of LDAPS URLs. An LDAPS URL is similar to an LDAP URL except that the URL scheme is "ldaps" instead of "ldap". It specifies the use of SSL when communicating with the LDAP server.

In the following example, the LDAP server is offering SSL at port 636. To run this program, you must enable SSL on port 636 on your LDAP server.

// Set up the environment for creating the initial context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.ldap.LdapCtxFactory");

// Specify LDAPS URL
env.put(Context.PROVIDER_URL, "ldaps://localhost:636/o=JNDITutorial");

// Authenticate as S. User and password "mysecret"
env.put(Context.SECURITY_AUTHENTICATION, "simple");
env.put(Context.SECURITY_PRINCIPAL, "cn=S. User, ou=NewHires, o=JNDITutorial");
env.put(Context.SECURITY_CREDENTIALS, "mysecret");

// Create the initial context
DirContext ctx = new InitialDirContext(env);

// ... do something useful with ctx
LDAPS URLs are accepted anywhere LDAP URLs are accepted. Check out the JNDI Tutorial for details on LDAP and LDAPS URLs.

Client Authentication: Using SSL with the External SASL Mechanism

 SSL provides authentication and other security services at a lower layer than the LDAP. If authentication has already been done at the SSL, the LDAP layer can use that authentication information from SSL by using the External SASL mechanism.

The following example is like the previous SSL example, except that instead of using simple authentication, it uses the External SASL authentication. By using External, you do not need to supply any principal or password information, because they get picked up from the SSL.

Server Requirements: This example requires the LDAP server to allow certificate-based client authentication. In addition, the LDAP server must trust (the CAs of) the client certificates that it receives, and must be able to map the owner distinguished names in the client certificates to principals that it knows about. Follow the instructions from your directory vendor on how to perform these tasks.

Client Requirements: This example requires the client to have an X.509 SSL client certificate. Moreover, the certificate must be stored as the first key entry in a keystore file. If this entry is password-protected, it must have the same password as the keystore. For more information about JSSE keystores, see the JSSE Reference Guide.

// Set up the environment for creating the initial context
Hashtable env = new Hashtable(11);
env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:636/o=JNDITutorial");

// Principal and credentials will be obtained from the connection
env.put(Context.SECURITY_AUTHENTICATION, "EXTERNAL");

// Specify SSL
env.put(Context.SECURITY_PROTOCOL, "ssl");

// Create the initial context
DirContext ctx = new InitialDirContext(env);

...
To run this program so that the client's certificate is used for authentication, you must provide (as system properties) the location and password of the keystore containing the client's certificate. Here is an example of how to run the program.
java -Djavax.net.ssl.keyStore=MyKeystoreFile \
    -Djavax.net.ssl.keyStorePassword=mysecret \
    External

If you do not supply a keystore, the program will run using anonymous authentication because no client credential exists at the SSL.

This example shows the most basic way to accomplish certificate-based client authentication. More advanced ways can be accomplished by writing and using a custom socket factory that accesses the client certificate in a more flexible manner, perhaps by using an LDAP directory. The next section shows how to use a custom socket factory with your JNDI application.

Using Custom Sockets

When using SSL, the LDAP provider will, by default, use the socket factory, javax.net.ssl.SSLSocketFactory , for creating an SSL socket to communicate with the server, using the default JSSE configuration. The JSSE can be customized in a variety of ways, as detailed in the JSSE Reference Guide. However, there are times when those customizations are not sufficient and you need to have more control over the SSL sockets, or sockets in general, used by the LDAP service provider. For example, you might need sockets that can bypass firewalls, or JSSE sockets that use nondefault caching/retrieval policies for its trust and key stores. To set the socket factory implementation used by the LDAP service provider, set the "java.naming.ldap.factory.socket" property to the fully qualified class name of the socket factory. This class must implement the javax.net.SocketFactory abstract class and provide an implementation of the getDefault() method that returns an instance of the socket factory. See the JSSE Reference Guide for details.

Here is an example of a custom socket factory that produces plain sockets.

public class CustomSocketFactory extends SocketFactory {
    public static SocketFactory getDefault() {

    System.out.println("[acquiring the default socket factory]");
    return new CustomSocketFactory();
    }
    ...
}
Note that this example creates a new instance of CustomSocketFactory each time a new LDAP connection is created. This might be appropriate for some applications and socket factories. If you want to reuse the same socket factory, getDefault() should return a singleton.

To use this custom socket factory with a JNDI program, set the "java.naming.ldap.factory.socket" property, as shown in the following example.

// Set up the environment for creating the initial context
Hashtable env = new Hashtable();
env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

// Specify the socket factory
env.put("java.naming.ldap.factory.socket", "CustomSocketFactory");

// Create the initial context
DirContext ctx = new InitialDirContext(env);

// ... do something useful with ctx

The "java.naming.ldap.factory.socket" property is useful for setting the socket factory on a per context basis. Another way to control the sockets used by the LDAP service provider is to set the socket factory for all sockets used in the entire program, by using java.net.Socket.setSocketImplFactory(). Use of this method is less flexible because it affects all socket connections, not just LDAP connections and therefore, should be used with care.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Digest-MD5
Next page: More LDAP Operations


More LDAP Operations (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
More LDAP Operations
The rest of the LDAP lesson covers how the JNDI provides ability to perform certain interesting LDAP operations.

Renaming Objects

You use Context.rename() to rename an object in the directory. In the LDAP v2, this corresponds to the "modify RDN" operation that renames an entry within the same context (that is, renaming a sibling). In the LDAP v3, this corresponds to the "modify DN" operation, which is like "modify RDN," except that the old and new entries need not be in the same context. You can use Context.rename() to rename a leaf entry or an interior node. The example shown in the Naming and Directory Operations lesson renames a leaf entry. The following code renames an interior node from "ou=NewHires" to "ou=OldHires":
ctx.rename("ou=NewHires", "ou=OldHires");

Note: The Sun Java Directory Server v5.2 does not support renaming interior nodes. If you run this example, then you will get a ContextNotEmptyException.

Renaming to a Different Part of the DIT

With the LDAP v3, you can rename an entry to a different part of the DIT. To do this by using Context.rename(), you must use a context that is the common ancestor for both the new and the old entries. For example, to rename "cn=C. User, ou=NewHires, o=JNDITutorial" to "cn=C. User, ou=People, o=JNDITutorial", you must use the context named by "o=JNDITutorial". Following is an example that demonstrates this. If you try to run this example against an LDAP v2 server, then you will get an InvalidNameException because version 2 does not support this feature.

ctx.rename("cn=C. User, ou=NewHires", "cn=C. User, ou=People");
Note: The Sun Java Directory Server v5.2 does not support renaming with different parent nodes. If you run this example by using that server, then you will get a OperationNotSupportedException (indicating a "protocol error").

Keeping the Old Name Attributes

In the LDAP, when you rename an entry, you have the option of keeping the entry's old RDN as an attribute of the updated entry. For example, if you rename the entry "cn=C. User" to "cn=Claude User", you can specify whether you want the old RDN "cn=C. User" to be kept as an attribute.

To specify whether you want to keep the old name attribute when you use Context.rename(), use the "java.naming.ldap.deleteRDN" environment property. If this property's value is "true" (the default), the old RDN is removed. If its value is "false", then the old RDN is kept as an attribute of the updated entry. The complete example is here.

// Set the property to keep RDN
env.put("java.naming.ldap.deleteRDN", "false");

// Create the initial context
DirContext ctx = new InitialDirContext(env);

// Perform the rename
ctx.rename("cn=C. User, ou=NewHires", "cn=Claude User,ou=NewHires");
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: SSL and Custom Sockets
Next page: LDAP Compare


LDAP Compare (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: More LDAP Operations
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
LDAP Compare
The LDAP "compare" operation allows a client to ask the server whether the named entry has an attribute/value pair. This allows the server to keep certain attribute/value pairs secret (i.e., not exposed for general "search" access) while still allowing the client limited use of them. Some servers might use this feature for passwords, for example, although it is insecure for the client to pass clear-text passwords in the "compare" operation itself.

To accomplish this in the JNDI, use suitably constrained arguments for the following methods:

  • search(Name name, String filter, SearchControls ctls)
  • search(Name name, String filterExpr, Object[]filterArgs, SearchControls ctls)

  1. The filter must be of the form "(name=value)". You cannot use wild cards.
  2. The search scope must be SearchControls.OBJECT_SCOPE.
  3. You must request that no attributes be returned. If these criteria are not met, then these methods will use an LDAP "search" operation instead of an LDAP "compare" operation.

Here's an example that causes an LDAP "compare" operation to be used.

// Value of the attribute
byte[] key = {(byte)0x61, (byte)0x62, (byte)0x63, (byte)0x64,
    (byte)0x65, (byte)0x66, (byte)0x67};

// Set up the search controls
SearchControls ctls = new SearchControls();
ctls.setReturningAttributes(new String[0]);       // Return no attrs
ctls.setSearchScope(SearchControls.OBJECT_SCOPE); // Search object only

// Invoke search method that will use the LDAP "compare" operation
NamingEnumeration answer = ctx.search("cn=S. User, ou=NewHires",
    "(mySpecialKey={0})", new Object[]{key}, ctls);
If the compare is successful, the resulting enumeration will contain a single item whose name is the empty name and which contains no attributes.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: More LDAP Operations
Next page: Search Results


Search Results (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: More LDAP Operations
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
Search Results
When you use the search methods in the DirContext interface, you get back a NamingEnumeration. Each item in NamingEnumeration is a SearchResult, which contains the following information:
  • Name
  • Object
  • Class name
  • Attributes

Name

 Each SearchResult contains the name of the LDAP entry that satisfied the search filter. You obtain the name of the entry by using getName(). This method returns the composite name of the LDAP entry relative to the target context. The target context is the context to which the name parameter resolves. In LDAP parlance, the target context is the base object for the search. Here's an example.
NamingEnumeration answer = ctx.search("ou=NewHires",
    "(&(mySpecialKey={0}) (cn=*{1}))",      // Filter expression
    new Object[]{key, name},                // Filter arguments
    null);				    // Default search controls
The target context in this example is that named by "ou=NewHires". The names in SearchResults in answer are relative to "ou=NewHires". For example, if getName() returns "cn=J. Duke", then its name relative to ctx will be "cn=J. Duke, ou=NewHires".

If you performed the search by using SearchControls.SUBTREE_SCOPE or SearchControls.OBJECT_SCOPE and the target context itself satisfied the search filter, then the name returned will be "" (the empty name) because that is the name relative to the target context.

This isn't the whole story. If the search involves referrals (see the JNDI Tutorial ) or dereferencing aliases (see the JNDI Tutorial ), then the corresponding SearchResults will have names that are not relative to the target context. Instead, they will be URLs that refer directly to the entry. To determine whether the name returned by getName() is relative or absolute, use isRelative(). If this method returns true, then the name is relative to the target context; if it returns false, the name is a URL.

If the name is a URL and you need to use that URL, then you can pass it to the initial context, which understands URLs (see the JNDI Tutorial ).

If you need to get the entry's full DN, you can use NameClassPair.getNameInNamespace().

Object

If the search was conducted requesting that the entry's object be returned (SearchControls.setReturningObjFlag() was invoked with true), then SearchResult will contain an object that represents the entry. To retrieve this object, you invoke getObject(). If a java.io.Serializable, Referenceable, or Reference object was previously bound to that LDAP name, then the attributes from the entry are used to reconstruct that object (see the example in the JNDI Tutorial ). Otherwise, the attributes from the entry are used to create a DirContext instance that represents the LDAP entry. In either case, the LDAP provider invokes DirectoryManager.getObjectInstance() on the object and returns the results.

Class Name

 If the search was conducted requesting that the entry's object be returned, then the class name is derived from the returned object. If the search requested attributes that included the retrieval of the "javaClassName" attribute of the LDAP entry, then the class name is the value of that attribute. Otherwise, the class name is "javax.naming.directory.DirContext". The class name is obtained from getClassName().

Attributes

 When you perform a search, you can select the return attributes either by supplying a parameter to one of the search() methods or by setting the search controls using SearchControls.setReturningAttributes(). If no attributes have been specified explicitly, then all of the LDAP entry's attributes are returned. To specify that no attributes be returned, you must pass an empty array (new String[0]).

To retrieve the LDAP entry's attributes, you invoke getAttributes() on the SearchResult.

Response Controls

See the Controls and Extensionslesson of the JNDI Tutorial for details on how to retrieve a search result's response controls.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: LDAP Compare
Next page: LDAP Unsolicited Notifications


LDAP Unsolicited Notifications (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: More LDAP Operations
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
LDAP Unsolicited Notifications
The LDAP v3 (RFC 2251) defines an unsolicited notification, a message that is sent by an LDAP server to the client without any provocation from the client. An unsolicited notification is represented in the JNDI by the UnsolicitedNotification interface.

Because unsolicited notifications are sent asynchronously by the server, you can use the same event model used for receiving notifications about namespace changes and object content changes. You register interest in receiving unsolicited notifications by registering an UnsolicitedNotificationListener with an EventContext or EventDirContext.

Here is an example of an UnsolicitedNotificationListener.

public class UnsolListener implements UnsolicitedNotificationListener {
    public void notificationReceived(UnsolicitedNotificationEvent evt) {
        System.out.println("received: " + evt);
    }

    public void namingExceptionThrown(NamingExceptionEvent evt) {
        System.out.println(">>> UnsolListener got an exception");
        evt.getException().printStackTrace();
    }
}

Following is an example that registers an implementation of UnsolicitedNotificationListener with an event source. Note that only the listener argument to EventContext.addNamingListener() is relevant. The name and scope parameters are not relevant to unsolicited notifications.

// Get the event context for registering the listener
EventContext ctx = (EventContext)
    (new InitialContext(env).lookup("ou=People"));

// Create the listener
NamingListener listener = new UnsolListener();

// Register the listener with the context (all targets equivalent)
ctx.addNamingListener("", EventContext.ONELEVEL_SCOPE, listener);
When running this program, you need to point it at an LDAP server that can generate unsolicited notifications and prod the server to emit the notification. Otherwise, after one minute the program will exit silently.

A listener that implements UnsolicitedNotificationListener can also implement other NamingListener interfaces, such as NamespaceChangeListener and ObjectChangeListener.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Search Results
Next page: Connection Management


Connection Management (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
Connection Management
JNDI provides a high-level interface for accessing naming and directory services. The mapping between a JNDI Context instance and an underlying network connection might not be one-to-one. The service provider is free to share and reuse connections as long as the interface semantics are preserved. The application developer usually does not need to know the details of how Context instances create and use connections. These details are useful when the developer needs to tune his program.

This lesson describes how the LDAP service provider uses connections. It describes when connections are created and how to specify special connection parameters, such as multiple servers and connection timeouts. This lesson also shows how to dynamically discover and use LDAP servers in network environments that support it.

A connection that is created must eventually be closed. This lesson contains a section that describes connection closures by the client and the server.

Finally, this lesson shows you how to use connection pooling to make applications that use many short-lived connections more efficient.

Note: Information presented in this lesson are specific to Sun's LDAP service provider. LDAP service providers from other vendors might not use the same policies for managing connections.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: LDAP Unsolicited Notifications
Next page: Creation


Creation (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: Connection Management
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
Creation
There are several ways in which a connection is created. The most common way is from the creation of an initial context. When you create an InitialContext, InitialDirContext, or InitialLdapContext by using the LDAP service provider, a connection is set up immediately with the target LDAP server named in the Context.PROVIDER_URL property. Each time an initial context is created, a new LDAP connection is created. See the Connection Pooling section for information on how to change this behavior.

If the property value contains more than one URL, then each URL is tried in turn until one is used to create a successful connection. The property value is then updated to be the successful URL. See the JNDI Tutorial for an example of how to create an initial context using a list of URLs.

There are three other direct ways in which a connection is created.

  1. By passing a URL as the name argument to the initial context. When an LDAP or LDAPS URL is pass as a name parameter to the initial context, the information in the URL is used to create a new connection to the LDAP server, regardless of whether the initial context instance itself has a connection to an LDAP server. In fact, the initial context might not be connected to any server. See the JNDI Tutorial for more information on how URLs are used as names.
  2. Another way that a connection is created is by use of a Reference. When a Reference containing an LDAP or LDAPS URL is passed to NamingManager.getObjectInstance() or DirectoryManager.getObjectInstance(), a new connection is created using information specified in the URL.
  3. Finally, when a referral is followed manually or automatically, the information in the referral is used to create a new connection. See the JNDI Tutorial for information on referrals.

    4. Shared Connections

    Context instances and NamingEnumerations that are derived from one Context instance share the same connection until changes to one of the Context instances make sharing no longer possible. For example, if you invoke Context.lookup(), Context.listBindings() or DirContext.search() from the initial context and get back other Context instances, then all of those Context instances will share the same connection.

    Here is an example.

    // Create initial context
DirContext ctx = new InitialDirContext(env);

// Get a copy of the same context
Context ctx2 = (Context)ctx.lookup("");

// Get a child context
Context ctx3 = (Context) ctx.lookup("ou=NewHires");
    In this example, ctx, ctx2, and ctx3 will share the same connection.

    Sharing is done regardless of how the Context instance came into existence. For example, a Context instance obtained by following a referral will share the same connection as the referral.

    When you change a Context instance's environment properties that are related to a connection, such as the principal name or credentials of the user, the Context instance on which you make these changes will get its own connection (if the connection is shared). Context instances that are derived from this Context instance in the future will share this new connection. Context instances that previously shared the old connection are not affected (that is, they continue to use the old connection).

    Here is an example that uses two connections.

    // Create initial context (first connection)
DirContext ctx = new InitialDirContext(env);

// Get a copy of the same context
DirContext ctx2 = (DirContext)ctx.lookup("");

// Change authentication properties in ctx2
ctx2.addToEnvironment(Context.SECURITY_PRINCIPAL,
    "cn=C. User, ou=NewHires, o=JNDITutorial");
ctx2.addToEnvironment(Context.SECURITY_CREDENTIALS, "mysecret");

// Method on ctx2 will use new connection
System.out.println(ctx2.getAttributes("ou=NewHires"));
    ctx2 initially shares the same connection with ctx. But when its principal and password properties are changed, it can no longer use ctx's connection. The LDAP provider will automatically create a new connection for ctx2.

    Similarly, if you use LdapContext.reconnect() to change the Context instance's connection controls, the Context instance will get its own connection if the connection was being shared.

    If the Context instance's connection was not being shared (i.e., no Contexts have been derived from it), then changes to its environment or connection controls will not cause a new connection to be created. Instead, any changes relevant to the connection will be applied to the existing connection.

    Creation Timeouts

    Not all connection creations are successful. If the LDAP provider cannot establish a connection within a certain timeout period, it aborts the connection attempt. By default, this timeout period is the network (TCP) timeout value, which is in the order of a few minutes. To change the timeout period, you use the "com.sun.jndi.ldap.connect.timeout" environment property. The value of this property is the string representation of an integer representing the connection timeout in milliseconds.

    Here is an example.

    // Set up environment for creating initial context
Hashtable env = new Hashtable(11);
env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

// Specify timeout to be 5 seconds
env.put("com.sun.jndi.ldap.connect.timeout", "5000");

// Create initial context
DirContext ctx = new InitialDirContext(env);

// do something useful with ctx
    In this example, if a connection cannot be created within 5 seconds, an exception will be thrown.

    If the Context.PROVIDER_URL property contains more than one URL, the provider will use the timeout for each URL. For example, if there are 3 URLs and the timeout has been specified to be 5 seconds, then the provider will wait for a maximum of 15 seconds in total.

    See the Connection Pooling section for information on how this property affects connection pooling.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Connection Management
Next page: Closing


Closing (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: Connection Management
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
Closing
Normal garbage collection takes care of removing Context instances when they are no longer in use. Connections used by Context instances being garbage collected will be closed automatically. Therefore, you do not need to explicitly close connections. Network connections, however, are limited resources and for certain programs, you might want to have control over their proliferation and usage. This section contains information on how to close connections and how to get notified if the server closes the connection.

Explicit Closures

You invoke Context.close() on a Context instance to indicate that you no longer need to use it. If the Context instance being closed is using a dedicated connection, the connection is also closed. If the Context instance is sharing a connection with other Context and unterminated NamingEnumeration instances, the connection will not be closed until close() has been invoked on all such Context and NamingEnumeration instances.

In the example from the Connection Creation section, all three Context instances must be closed before the underlying connection is closed.

// Create initial context
DirContext ctx = new InitialDirContext(env);

// Get a copy of the same context
Context ctx2 = (Context)ctx.lookup("");

// Get a child context
Context ctx3 = (Context) ctx.lookup("ou=NewHires");

// do something useful with ctx, ctx2, ctx3

// Close the contexts when we're done
ctx.close();
ctx2.close();
ctx3.close();

Forced Implicit Closures

As mentioned previously, for those Context and NamingEnumeration instances that are no longer in scope, the Java runtime system will eventually garbage collect them, thus cleaning up the state that a close() would have done. To force the garbage collection, you can use the following code.
Runtime.getRuntime().gc();
Runtime.getRuntime().runFinalization();
Depending on the state of the program, performing this procedure can cause serious (temporary) performance degradation. If you need to ensure that connections are closed, track Context instances and close them explicitly.

Detecting Connection Closures

LDAP servers often have an idle timeout period after which they will close connections no longer being used. When you subsequently invoke a method on a Context instance that is using such a connection, the method will throw a CommunicationException. To detect when the server closes the connection that a Context instance is using, you register an UnsolicitedNotificationListener with the Context instance. An example is shown in the LDAP Unsolicited Notifications section. Although the example is designed for receiving unsolicited notification from the server, it can also be used to detect connection closures by the server. After starting the program, stop the LDAP server and observe that the listener's namingExceptionThrown() method gets called.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Creation
Next page: Pooling


Pooling (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: Connection Management
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
Pooling
The Connection Creation section described when connections are created. It described how several Context instances can share the same connection.

Another type of connection sharing supported by the LDAP service provider is called connection pooling. In this type of sharing, the LDAP service provider maintains a pool of (possibly) previously used connections and assigns them to a Context instance as needed. When a Context instance is done with a connection (closed or garbage collected), the connection is returned to the pool for future use. Note that this form of sharing is sequential: a connection is retrieved from the pool, used, returned to the pool, and then, retrieved again from the pool for another Context instance.

The pool of connections is maintained per Java runtime system. For some situations, connection pooling can improve performance significantly. For example, only one connection is required for processing a search response that contains four referral references to the same LDAP server if connection pooling is used. Without connection pooling, such a scenario would require four separate connections.

The rest of this lesson describes in more detail how to use connection pooling.

How to Use Connection Pooling

You request connection pooling by adding the property, "com.sun.jndi.ldap.connect.pool" to the environment properties passed to the initial context constructor. Here is an example.
// Set up environment for creating initial context
Hashtable env = new Hashtable(11);
env.put(Context.INITIAL_CONTEXT_FACTORY,
    "com.sun.jndi.ldap.LdapCtxFactory");
env.put(Context.PROVIDER_URL, "ldap://localhost:389/o=JNDITutorial");

// Enable connection pooling
env.put("com.sun.jndi.ldap.connect.pool", "true");

// Create one initial context (Get connection from pool)
DirContext ctx = new InitialDirContext(env);

// do something useful with ctx

// Close the context when we're done
ctx.close();   // Return connection to pool

// Create another initial context (Get connection from pool)
DirContext ctx2 = new InitialDirContext(env);

// do something useful with ctx2

// Close the context when we're done
ctx2.close();   // Return connection to pool

This example creates two initial contexts in succession. The second initial context will reuse the connection used by the first. To run this program and observe how the connections are retrieved and returned to the pool, use the following command line.

#java -Dcom.sun.jndi.ldap.connect.pool.debug=fine UsePool
This should produce output that looks as follows.
Create com.sun.jndi.ldap.LdapClient@5d173[localhost:389]
Use com.sun.jndi.ldap.LdapClient@5d173
{ou=ou: NewHires, objectclass=objectClass: top, organizationalUnit}
Release com.sun.jndi.ldap.LdapClient@5d173
Use com.sun.jndi.ldap.LdapClient@5d173
{ou=ou: People, objectclass=objectClass: top, organizationalunit}
Release com.sun.jndi.ldap.LdapClient@5d173

You can decide when and where to use pooling by including or omitting the "com.sun.jndi.ldap.connect.pool" property, and thus control pooling on a per-context basis. In the previous example, if you removed this property from the environment properties before creating the second initial context, the second initial context would not use a pooled connection.

The LDAP provider keeps track of whether a connection is being used through indications from the application. It assumes that an application that is maintaining an open context handle is using the connection. Therefore, in order for the LDAP provider to properly manage the pooled connections, you must be diligent about invoking Context.close() on contexts that you no longer need.

Bad connections are automatically detected and removed from the pool by the LDAP provider. The probability of a context ending up with a bad connection is the same regardless of whether connection pooling is used.

Creation Timeout

The pool of connections maintained by the LDAP service provider may be limited in size; this is described in detail in the Connection Pooling Configuration section. When connection pooling has been enabled and no pooled connection is available, the client application will block, waiting for an available connection. You can use the "com.sun.jndi.ldap.connect.timeout" environment property to specify how long to wait for a pooled connection. If you omit this property, the application will wait indefinitely.

This same property is also used to specify a timeout period for establishment of the LDAP connection, as described in the Connection Creation section.

When Not to Use Pooling!!

Pooled connections are intended to be reused. Therefore, if you plan to perform operations on a Context instance that might alter the underlying connection's state, then you should not use connection pooling for that Context instance. For example, if you plan to invoke the Start TLS extended operation on a Context instance, or plan to change security-related properties (such as "java.naming.security.principal" or "java.naming.security.protocol") after the initial context has been created, you should not use connection pooling for that Context instance because the LDAP provider does not track any such state changes. If you use connection pooling in such situations, you might be compromising the security of your application.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Closing
Next page: Configuration


Configuration (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Section: Connection Management
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
Configuration
Connection pooling is configured and maintained per Java runtime. Connections are not shared across different runtimes. To use connection pooling, no configuration is required. Configuration is necessary only if you want to customize how pooling is done, such as to control the size of the pools and which types of connections are pooled.

You configure connection pooling by using a number of system properties at program startup time. Note that these are system properties, not environment properties and that they affect all connection pooling requests.

Here is an example of a command line that sets the maximum pool size to 20, the preferred pool size to 10, and the idle timeout to a minute for pooled connections.

# java -Dcom.sun.jndi.ldap.connect.pool.maxsize=20 \
       -Dcom.sun.jndi.ldap.connect.pool.prefsize=10 \
       -Dcom.sun.jndi.ldap.connect.pool.timeout=60000 \
    UsePool

The following table lists the system properties for configuring connection pooling. They are described in more detail in the rest of this section.

System Property Name | Description | Default
com.sun.jndi.ldap.connect.pool.authentication | A list of space-separated authentication types of connections that may be pooled. Valid types are "none", "simple", and "DIGEST-MD5". | "none simple"
com.sun.jndi.ldap.connect.pool.debug | A string that indicates the level of debug output to produce. Valid values are "fine" (trace connection creation and removal) and "all" (all debugging information).
com.sun.jndi.ldap.connect.pool.initsize | The string representation of an integer that represents the number of connections per connection identity to create when initially creating a connection for the identity. | 1
com.sun.jndi.ldap.connect.pool.maxsize | The string representation of an integer that represents the maximum number of connections per connection identity that can be maintained concurrently. | no maximum size
com.sun.jndi.ldap.connect.pool.prefsize | The string representation of an integer that represents the preferred number of connections per connection identity that should be maintained concurrently. | no preferred size
com.sun.jndi.ldap.connect.pool.protocol | A list of space-separated protocol types of connections that may be pooled. Valid types are "plain" and "ssl". | "plain"
com.sun.jndi.ldap.connect.pool.timeout | The string representation of an integer that represents the number of milliseconds that an idle connection may remain in the pool without being closed and removed from the pool. | no timeout

What Gets Pooled

When you request that a Context instance use connection pooling by using the "com.sun.jndi.ldap.connect.pool" environment property, the connection that is used might or might not be pooled. The default rule is that plain (non-SSL) connections that use simple or no authentication are allowed to be pooled. You can change this default to include SSL connections and the DIGEST-MD5 authentication type by using system properties. To allow both plain and SSL connections to be pooled, set the "com.sun.jndi.ldap.connect.pool.protocol" system property to the string "plain ssl". To allow connections of anonymous (none), simple and DIGEST-MD5 authentication types to be pooled, set the com.sun.jndi.ldap.connect.pool.authentication system property to the string "none simple DIGEST-MD5".

There are a couple of environment properties that automatically disqualify a Context instance from using a pooled connection. A Context instance cannot use a pooled connection if it has its "java.naming.ldap.factory.socket" property set to a custom socket factory class, or its "java.naming.security.sasl.callback" property set to a custom callback handler class, or its "com.sun.jndi.ldap.trace.ber" property set to enable protocol tracing.

How Connections are Pooled

When a Context instance requests to use a pooled connection, the LDAP provider needs to determine whether the request can be satisfied by an existing pooled connection. It does this by assigning a connection identity to each pooled connection and checking whether the incoming request has the same connection identity as that of one of its pooled connections.

A connection identity is the set of the parameters required to create a possibly authenticated LDAP connection. Its composition depends on the authentication type of the request, as shown in the following table.

Authentication Type Connection Identity Contents
none
  • connection controls
  • host name, port number as specified in the "java.naming.provider.url" property, referral, or URL supplied to the initial context
  • the contents of the following properties:
    java.naming.security.protocol
java.naming.ldap.version
simple
  • all of the information listed for none
  • the contents of following properties:
    java.naming.security.principal
java.naming.security.credentials
DIGEST-MD5
  • all of the information listed for simple
  • the contents of following properties:
    java.naming.security.sasl.authorizationId
java.naming.security.sasl.realm
javax.security.sasl.qop
javax.security.sasl.strength
javax.security.sasl.server.authentication
javax.security.sasl.maxbuffer
javax.security.sasl.policy.noplaintext
javax.security.sasl.policy.noactive
javax.security.sasl.policy.nodictionary
javax.security.sasl.policy.noanonymous
javax.security.sasl.policy.forward
javax.security.sasl.policy.credentials

Pool Sizes

The LDAP provider maintains pools of connections; each pool holds connections (either in-use or idle) that have the same connection identity. There are three sizes that affect the management of each pool. These sizes are global and affect all pools.

The initial pool size is the number of connections per connection identity that the LDAP service provider creates when first creating the pool (which corresponds to when the application first requests a pooled connection for that connection identity). Authentication of each connection in the pool is performed on demand, as the connection gets used. By default, the initial pool size is 1 and can be changed by using the system property "com.sun.jndi.ldap.connect.pool.initsize". It is typically used at application start-up time to prime the pool with a certain number of connections to a server.

The maximum pool size is the maximum number of connections per connection identity that can be maintained concurrently by the LDAP service provider. Both in-use and idle connections contribute to this number. When the pool size reaches this number, no new connection for the corresponding connection identity may be created until a connection in the pool has been removed (i.e., the physical connection is closed). When the pool size reaches the maximum and all of the connections in the pool are in use, the application's request for a connection from that pool is blocked until a connection in the pool either becomes idle or is removed. A maximum pool size of 0 means that there is no maximum size: A request for a pooled connection will use an existing pooled idle connection or a newly created pooled connection.

The preferred pool size is the preferred number of connections per connection identity that the LDAP service provider should maintain. Both in-use and idle connections contribute to this number. When an application requests the use of a pooled connection and the pool size is less than the preferred size, the LDAP provider will create and use a new pooled connection regardless of whether an idle connection is available. When an application is finished with a pooled connection (by invoking Context.close() on all contexts that share the connection) and the pool size is greater than the preferred size, the LDAP provider will close and remove the pooled connection from the pool. A preferred pool size of 0 means that there is no preferred size: A request for a pooled connection will result in a newly created connection only if no idle ones are available.

Note that the maximum pool size overrides both the initial and preferred pool sizes. For example, setting the preferred pool size greater than the maximum pool size is effectively setting it to the maximum pool size.

Idle Connections

When the application is finished with a pooled connection (by invoking Context.close() on all contexts that share the connection), the underlying pooled connection is marked as idle, waiting to be reused. By default, idle connections remain in the pool indefinitely until they are garbage-collected. If the "com.sun.jndi.ldap.connect.pool.timeout" system property has been set, the LDAP provider will automatically close and remove pooled connections that have been idle for more than the specified period.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Pooling
Next page: Frequently Asked Questions


Frequently Asked Questions (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users)

Trail: Java Naming and Directory Interface(TM).
Lesson: Advanced Topics for LDAP Users
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Home Page > Java Naming and Directory Interface(TM). > Advanced Topics for LDAP Users
« Previous • Trail • Next »
Frequently Asked Questions
This lesson answers the frequently asked questions users often have when using the JNDI to access LDAP services. Some of the common problems are answered in the Trouble Shooting Tips of the Naming and Directory Operations lesson.

    Contexts:

  1. Is the context safe for multithreaded access?
  2. Why does the LDAP provider ignore my security environment properties?
  3. Why do I keep getting a CommunicationException?
  4. How can I get a trace of LDAP messages?
  5. How do I use a different authentication mechanism such as Kerberos?
  6. Should I enable ssl when changing the password?

    7. Attributes:

  7. When I ask for one attribute, I get back another. Why?
  8. How do I know the type of an attribute's value?
  9. How do I get back an attribute's value in a form other than a String or byte array?
  10. Why does putting an "*" as an attribute value not work as expected in my search?

    11. Searches:

  11. Why don't wildcards in search filters always work?
  12. Why do I get back only n number of entries when I know there are more in the directory?
  13. How do I pass controls with my search?
  14. How do I find out how many search results I got back?

    15. Names:

  15. Why do I get an empty string as a name in my SearchResult?
  16. Why do I get a URL string as a name in my SearchResult?
  17. What type is the Name argument passed to the context methods?
  18. Can I pass the name I got back from NameParser to the Context methods?
  19. What's the relationship between the name I use for the Context.SECURITY_PRINCIPAL property and the directory?
  20. Why are there strange quotation marks and escapes in the names that I read from the directory?
  21. How do I get an LDAP entry's full DN?

1. Is the context safe for multithreaded access, or do I need to lock/synchronize access to a context?

The answer depends on the implementation. This is because the Context and DirContext interfaces do not specify synchronization requirements. Sun's LDAP implementation is optimized for single-threaded access. If you have multiple threads accessing the same Context instance, then each thread needs to lock the Context instance when using it. This also applies to any NamingEnumeration that is derived from the same Context instance. However, multiple threads can access different Context instances (even those derived from the same initial context) concurrently without locks.

2. Why does the LDAP provider ignore my security environment properties if I do not set the Context.SECURITY_CREDENTIALS ("java.naming.security.credentials") property or set it to the empty string?

If you supply an empty string, an empty byte/char array, or null to the Context.SECURITY_CREDENTIALS environment property, then an anonymous bind will occur even if the Context.SECURITY_AUTHENTICATION property was set to "simple". This is because for simple authentication, the LDAP requires the password to be nonempty. If a password is not supplied, then the protocol automatically converts the authentication to "none".

3. Why do I keep getting a CommunicationException when I try to create an initial context?

You might be talking to a server that supports only the LDAP v2. See the Miscellaneous lesson of the JNDI Tutorial for an example of how to set the version number.

4. How can I trace the LDAP message?

Try using the "com.sun.jndi.ldap.trace.ber" environment property. If the value of this property is an instance of java.io.OutputStream, then trace information about BER buffers sent and received by the LDAP provider is written to that stream. If the property's value is null, then no trace output is written.

For example, the following code will send the trace output to System.err.

env.put("com.sun.jndi.ldap.trace.ber", System.err);

5. How do I use a different authentication mechanism such as Kerberos?

Follow the instructions in the GSS-API/Kerberos v5 Authentication of the JNDI Tutorial for information on how to use Kerberos authentication. To use other authentication mechanisms, see the Using Arbitrary SASL Mechanisms section of the JNDI tutorial .

6. Should I enable SSL when changing the password? /

It really depends on the directory server you are using. Some directory servers won't allow you to change the password if SSL is not enabled but some do allow it. It's good to have SSL enabled to have your password secured in the communication channel.

7. When I ask for one attribute, I get back another. Why?

The attribute name that you are using might be a synonym for another attribute. In this case, the LDAP server might return the canonical attribute name instead of the one that you supplied. When you look in the Attributes returned by the server, you need to use the canonical name instead of the synonym.

For example, "fax" might be a synonym for the canonical attribute name "facsimiletelephonenumber". If you ask for "fax", the server will return the attribute named "facsimiletelephonenumber". See the Naming and Directory Operations lesson for details on synonyms and other issues regarding attribute names.

8. How do I know the type of an attribute's value?

An attribute's value can be either java.lang.String or byte[]. See the Miscellaneous section of the JNDI Tutorial for information on which attributes' values are returned as byte[]. To do this programmatically, you can use the instanceof operator to examine the attribute value that you get back from the LDAP provider.

9. How do I get back an attribute's value in a form other than a String or byte array?

Currently you can't. The LDAP provider returns only attribute values that are either java.lang.String or byte[]. See the Miscellaneous section of the JNDI Tutorial .

10. Why does putting an "*" as an attribute value not work as expected in my search?

When you use the following form of search(), the attribute values are treated as literals; that is, the attribute in the directory entry is expected to contain exactly that value:

search(Name name, Attributes matchingAttrs)
To use wildcards, you should use the string filter forms of search(), as follows.
search(Name name, String filter, SearchControls ctls)
search(Name name, String filterExpr, Object[]filterArgs, SearchControls ctls)
For the last form, the wildcard characters must appear in the filterExpr argument, and not in filterArgs. The values in filterArgs are also treated as literals.

11. Why don't wildcards in search filters always work?

A wildcard that appears before or after the attribute value (such as in "attr=*I*") indicates that the server is to search for matching attribute values by using the attribute's substring matching rule. If the attribute's definition does not have a substring matching rule, then the server cannot find the attribute. You'll have to search by using an equality or "present" filter instead.

12. Why do I get back only n number of entries when I know there are more in the directory? Some servers are configured to limit the number of entries that can be returned. Others also limit the number of entries that can be examined during a search. Check your server configuration.

13. How do I pass controls with my search?

Controls are not explained in this tutorial. Check out the JNDI Tutorial .

14. How do I find out how many search results I got back?

You must keep count as you enumerate through the results. The LDAP does not provide this information.

15. Why do I get an empty string as a name in my SearchResult?

getName() always returns a name relative to the target context of the search. So, if the target context satisfies the search filter, then the name returned will be "" (the empty name) because that is the name relative to the target context. See the Search Results section for details.

16. Why do I get a URL string as a name in my SearchResult?

The LDAP entry was retrieved by following either an alias or a referral, so its name is a URL. See the Search Results lesson for details.

17. What type is the Name argument passed to the Context and DirContext methods? - a CompoundName or a CompositeName?

The string forms accept the string representation of a composite name. That is, using a string name is equivalent to calling new CompositeName(stringName) and passing the results to the Context/DirContext method. The Name argument can be any object that implements the Name interface. If it is an instance of CompositeName, then the name is treated as a composite name; otherwise, it is treated as a compound name.

18. Can I pass the name I got back from NameParser to Context methods?

This is related to the previous question. Yes, you can. NameParser.parse() returns a compound name that implements the Name interface. This name can be passed to the Context methods, which will interpret it as a compound name.

19. What's the relationship between the name I use for the Context.SECURITY_PRINCIPAL property and the directory?

You can think of the principal name as coming from a different namespace than the directory. See RFC 2829 and the Security section for details on LDAP authentication mechanisms. Sun's LDAP service provider accepts a string principal name, which it passes directly to the LDAP server. Some LDAP servers accept DNs, whereas others support the schemes proposed by RFC 2829.

20. Why are there strange quotation marks and escapes in the names that I read from the directory?

Sun's LDAP name parser is conservative with respect to quoting rules, but it nevertheless produces "correct" names. Also, remember that the names of entries returned by NamingEnumerations are composite names that can be passed back to the Context and DirContext methods. So, if the name contains a character that conflicts with the composite name syntax (such as the forward slash character "/"), then the LDAP provider will provide an encoding to ensure that the slash character will be treated as part of the LDAP name rather than as a composite name separator.

Start using the LdapName and Rdn classes that enable easy name manipulation.

21. How do I get an LDAP entry's full DN?

You can use NameClassPair.getNameInNamespace().

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Configuration
Next page: Java Objects in the Directory


Lesson: Java Objects in the Directory (The Java™ Tutorials > Java Naming and Directory Interface(TM).)

Java Objects in the Directory
Storing and Reading Objects
Serializable Objects
Trail: Java Naming and Directory Interface(TM).
Home Page > Java Naming and Directory Interface(TM).
« Previous • Trail • Next »
Lesson: Java Objects in the Directory
Traditionally, directories have been used to store data. Users and programmers think of the directory as a hierarchy of directory entries, each containing a set of attributes. You look up an entry from the directory and extract the attribute(s) of interest.

For applications written in the JavaTM programming language, Java objects may sometimes be shared across applications. For such applications, it makes sense to be able to use the directory as a repository for Java objects. The directory provides a centrally administered, and possibly replicated, service for use by Java applications distributed across the network. For example, an application server might use the directory for registering objects that represent the services that it manages so that a client can later search the directory to locate those services as needed. An example of where JNDI is used as a directory of services is Apache DS. More information about this can be found here.

The JNDI provides an object-oriented view of the directory, thereby allowing Java objects to be added to and retrieved from the directory without requiring the client to manage data representation issues. This lesson discusses the use of the directory for storing and retrieving Java objects at a basic level. The JNDI provides what are known as object and state factories for creating and storing the objects accessed from the directory.

Object Factory

An object factory is a producer of objects. It accepts some information about how to create an object, such as a reference, and then returns an instance of that object. For details about Object Factories and the format in which objects are stored in the directory please refer to the JNDI Tutorial

State Factory

 A state factory transforms an object into another object. The input is the object and optional attributes, supplied to Context.bind() and the output is another object and optional attributes, to be stored in the underlying naming service or directory. For details about State Factories and on how to write your own state factory please refer to the JNDI Tutorial

The next part of the lesson discusses how to access Objects in the Directory It describes how serializable objects can be stored and read in the directory. For other types of objects please check out the JNDI Tutorial

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Storing and Reading Objects


Storing and Reading Objects (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Java Objects in the Directory)

Trail: Java Naming and Directory Interface(TM).
Lesson: Java Objects in the Directory
Java Objects in the Directory
Storing and Reading Objects
Serializable Objects
Home Page > Java Naming and Directory Interface(TM). > Java Objects in the Directory
« Previous • Trail • Next »
Storing and Reading Objects

Applications and services can use the directory in different ways to store and locate objects:

  • Store (a copy of) the object itself.
  • Store a reference to an object.
  • Store attributes that describe the object.
In general terms, a JavaTM object's serialized form contains the object's state and an object's reference in a compact representation of addressing information that can be used to contact the object. Some examples are given in the Naming and Directory Operations lesson. An object's attributes are properties that are used to describe the object; attributes might include addressing and/or state information.

Which of these three ways to use depends on the application/system that is being built and how it needs to interoperate with other applications and systems that will share the objects stored in the directory. Another factor is the support provided by the service provider and the underlying directory service.

Programmatically, all applications use one of the following methods when storing objects in the directory:

  • Context.bind()
  • DirContext.bind()
  • Context.rebind()
  • DirContext.rebind()
The application passes the object that it wants to store to one of these methods. Then, depending on the types of objects that the service provider supports, the object will be transformed into a representation acceptable to the underlying directory service.

This lesson shows how to store serializable objects in the directory once the object is stored, you can simply use lookup()to get a copy of the object back from the directory, regardless of what type of information was actually stored.

You can get the object back not only by using lookup(), but also when you list a context and when you search a context or its subtree. In all of these cases, object factories might be involved. Object factories are discussed in detail in the JNDI Tutorial

For storing below objects types, please refer to the JNDI Tutorial

  • Referenceable objects and JNDI References
    The bind() examples in the Naming and Directory Operations lesson use Referenceable objects.
  • Objects with attributes (DirContext)
  • RMI (Java Remote Method Invocation) objects (including those that use IIOP)
  • CORBA objects

Before you go on: To run these examples successfully, you must either turn off schema-checking in the server or add the Java schema that accompany this tutorial to the server. This task is typically performed by the directory server's administrator. See the Software Setup lesson for more information.

Windows Active Directory: Context.rebind() and DirContext.rebind() do not work against Active Directory because these methods work by reading the attributes of the entry to be updated, removing the entry, and then adding a new entry that contains the modified attributes. Active Directory returns some attributes that cannot be set by the user, causing the final addition step to fail. The workaround for this problem is to use DirContext.getAttributes() to obtain and save the attributes that you want to keep. Then, remove the entry and add it back with the saved attributes (and any others that you want to add) using DirContext.bind().

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Java Objects in the Directory
Next page: Serializable Objects


Serializable Objects (The Java™ Tutorials > Java Naming and Directory Interface(TM). > Java Objects in the Directory)

Trail: Java Naming and Directory Interface(TM).
Lesson: Java Objects in the Directory
Java Objects in the Directory
Storing and Reading Objects
Serializable Objects
Home Page > Java Naming and Directory Interface(TM). > Java Objects in the Directory
« Previous • Trail • Next »
Serializable Objects
To serialize an object means to convert its state to a byte stream so way that the byte stream can be reverted back into a copy of the object. A Java object is serializable if its class or any of its superclasses implements either the java.io.Serializable interface or its subinterface, java.io.Externalizable. Deserialization is the process of converting the serialized form of an object back into a copy of the object.

For example, the java.awt.Button class implements the Serializable interface, so you can serialize a java.awt.Button object and store that serialized state in a file. Later, you can read back the serialized state and deserialize into a java.awt.Button object.

The Java platform specifies a default way by which serializable objects are serialized. A (Java) class can override this default serialization and define its own way of serializing objects of that class. The Object Serialization Specification describes object serialization in detail.

When an object is serialized, information that identifies its class is recorded in the serialized stream. However, the class's definition ("class file") itself is not recorded. It is the responsibility of the system that is deserializing the object to determine how to locate and load the necessary class files. For example, a Java application might include in its classpath a JAR file that contains the class files of the serialized object(s) or load the class definitions by using information stored in the directory, as explained later in this lesson.

Binding a Serializable Object

You can store a serializable object in the directory if the underlying service provider supports that action, as does Sun's LDAP service provider.

The following example invokes Context.bind() to bind an AWT button to the name "cn=Button". To associate attributes with the new binding, you use DirContext.bind(). To overwrite an existing binding, use Context.rebind() and DirContext.rebind().

// Create the object to be bound
Button b = new Button("Push me");

// Perform the bind
ctx.bind("cn=Button", b);
You can then read the object back using Context.lookup(), as follows.
// Check that it is bound
Button b2 = (Button)ctx.lookup("cn=Button");
System.out.println(b2);
Running this example produces the following output.
# java SerObj
java.awt.Button[button0,0,0,0x0,invalid,label=Push me]

Specifying a Codebase
Note: The procedures described here are for binding a serializable object in a directory service that follows the schema defined in RFC 2713. These procedures might not be generally applicable to other naming and directory services that support binding a serializable object with a specified codebase.
When a serialized object is bound in the directory as shown in the previous example, applications that read the serialized object from the directory must have access to the class definitions necessary to deserialize the object.

Alternatively, you can record a codebase with the serialized object in the directory, either when you bind the object or subsequently by adding an attribute by using DirContext.modifyAttributes(). You can use any attribute to record this codebase and have your application read that attribute from the directory and use it appropriately. Or you can use the "javaCodebase" attribute specified in . In the latter case, Sun's LDAP service provider will automatically use the attribute to load the class definitions as needed. "javaCodebase" should contain the URL of a codebase directory or a JAR file. If the codebase contains more than one URL, then each URL must be separated by a space character.

The following example resembles the one for binding a java.awt.Button. It differs in that it uses a user-defined Serializable class, Flower, and supplies a "javaCodebase" attribute that contains the location of Flower's class definition. Here's the code that does the binding.

String codebase = ...;

// Create the object to be bound
Flower f = new Flower("rose", "pink");

// Perform the bind and specify the codebase
ctx.bind("cn=Flower", f, new BasicAttributes("javaCodebase", codebase));
When you run this example, you must supply the URL of the location at which the class file Flower.class was installed. For example, if Flower.class was installed at the Web server web1, in the directory example/classes, then you would run this example as follows.
# java SerObjWithCodebase http://web1/example/classes/
pink rose
Afterward, you may remove Flower.class from your classpath and run any program that looks up or lists this object without directly referencing the Flower class. If your program references Flower directly, then you must make its class file available for compilation and execution.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Storing and Reading Objects
Next page: New features in JDK 5.0 and JDK 6


Lesson: New features in JDK 5.0 and JDK 6 (The Java™ Tutorials > Java Naming and Directory Interface(TM).)

New features in JDK 5.0 and JDK 6
Retrieving Distinguished Name
Standard LDAP Controls
Paged Results Control
Sort Control
Manage Referral Control
Manipulating LdapName (Distinguished Name)
Manipulating Relative Distringuished Name (RDN)
Setting Timeout for Ldap Operations
Trail: Java Naming and Directory Interface(TM).
Home Page > Java Naming and Directory Interface(TM).
« Previous • Trail • Next »
Lesson: New features in JDK 5.0 and JDK 6
In this lesson we will discuss about the new features listed below that are supported by the JNDI and the LDAP Service provider in the JDK 5.0 and JDK 6 releases.
  • Retreiving the distinguished name (DN) from the search result.
  • Using standard LDAP controls.
  • Manipulation of LDAP names.
  • Setting read timeout for LDAP operations.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Previous Lesson
Next page: Retrieving Distinguished Name


Retrieving Distinguished Name (The Java™ Tutorials > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6)

Trail: Java Naming and Directory Interface(TM).
Lesson: New features in JDK 5.0 and JDK 6
New features in JDK 5.0 and JDK 6
Retrieving Distinguished Name
Standard LDAP Controls
Paged Results Control
Sort Control
Manage Referral Control
Manipulating LdapName (Distinguished Name)
Manipulating Relative Distringuished Name (RDN)
Setting Timeout for Ldap Operations
Home Page > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6
« Previous • Trail • Next »
Retrieving Distinguished Name
In the JDK releases prior to 5.0, there is no direct way of obtaining the Distinguished Name (DN) from the search results. The SearchResults.getName() method always returns the name that is relative to the context on which the search is performed. In order to get the absolute, or full name of the search entry some amount of book-keeping is required to track the ancestor contexts. Two new APIs below are added in JDK 5.0 to retrieve the absolute name from the NameClassPair, whenever a search, list, or listBindings operation is performed on a context:
  • NameClassPair.getNameInNameSpace(Name name)
  • NameClassPair.getNameInNameSpace(String name)
Here is an example that retrieves DNs from an LDAP search:

     public static void printSearchEnumeration(NamingEnumeration retEnum) {
         try {
             while (retEnum.hasMore()) {
                 SearchResult sr = (SearchResult) retEnum.next();
                 System.out.println(">>" + sr.getNameInNamespace());
             }
         } catch (NamingException e) {
             e.printStackTrace();
         }
     }
The complete example can be obtained from here. This program generates the output as below:

        >>cn=Jon Ruiz, ou=People, o=JNDITutorial
    >>cn=Scott Seligman, ou=People, o=JNDITutorial
    >>cn=Samuel Clemens, ou=People, o=JNDITutorial
    >>cn=Rosanna Lee, ou=People, o=JNDITutorial
    >>cn=Maxine Erlund, ou=People, o=JNDITutorial
    >>cn=Niels Bohr, ou=People, o=JNDITutorial
    >>cn=Uri Geller, ou=People, o=JNDITutorial
    >>cn=Colleen Sullivan, ou=People, o=JNDITutorial
    >>cn=Vinnie Ryan, ou=People, o=JNDITutorial
    >>cn=Rod Serling, ou=People, o=JNDITutorial
    >>cn=Jonathan Wood, ou=People, o=JNDITutorial
    >>cn=Aravindan Ranganathan, ou=People, o=JNDITutorial
    >>cn=Ian Anderson, ou=People, o=JNDITutorial
    >>cn=Lao Tzu, ou=People, o=JNDITutorial
    >>cn=Don Knuth, ou=People, o=JNDITutorial
    >>cn=Roger Waters, ou=People, o=JNDITutorial
    >>cn=Ben Dubin, ou=People, o=JNDITutorial
    >>cn=Spuds Mackenzie, ou=People, o=JNDITutorial
    >>cn=John Fowler, ou=People, o=JNDITutorial
    >>cn=Londo Mollari, ou=People, o=JNDITutorial
    >>cn=Ted Geisel, ou=People,o=JNDITutorial
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: New features in JDK 5.0 and JDK 6
Next page: Standard LDAP Controls


Standard LDAP Controls (The Java™ Tutorials > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6)

Trail: Java Naming and Directory Interface(TM).
Lesson: New features in JDK 5.0 and JDK 6
New features in JDK 5.0 and JDK 6
Retrieving Distinguished Name
Standard LDAP Controls
Paged Results Control
Sort Control
Manage Referral Control
Manipulating LdapName (Distinguished Name)
Manipulating Relative Distringuished Name (RDN)
Setting Timeout for Ldap Operations
Home Page > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6
« Previous • Trail • Next »
Standard LDAP Controls
In LDAP v3, a Control is a message that enhances the existing LDAP operation by associating it with more information useful to the server or the client. A control can be either a request control or a response control. A request control is sent from the client to the server along with an LDAP request. A response control is sent from the server to the client along with an LDAP response. Either is represented by the interface javax.naming.ldap.Control

See the controls lesson in the JNDI tutorial if you haven't programmed using controls before.

In this lesson we will discuss the standard LDAP controls that are added to JDK 5.0. The necessary LDAP controls are already supported in the LDAP Booster Pack extension package available for the JNDI/LDAP service provider under com.sun.jndi.ldap.ctl package. The LDAP controls that are standardized by IETF are now made available in the javax.naming.ldap package of JDK through the following classes.

  • ManageReferralControl (RFC 3296)
  • PagedResultsControl (RFC 2696)
  • PagedResultsResponseControl
  • SortControl (RFC 2891)
  • SortKey
  • SortResponseControl
  • BasicControl

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Retrieving Distinguished Name
Next page: Paged Results Control


Paged Results Control (The Java™ Tutorials > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6)

Trail: Java Naming and Directory Interface(TM).
Lesson: New features in JDK 5.0 and JDK 6
New features in JDK 5.0 and JDK 6
Retrieving Distinguished Name
Standard LDAP Controls
Paged Results Control
Sort Control
Manage Referral Control
Manipulating LdapName (Distinguished Name)
Manipulating Relative Distringuished Name (RDN)
Setting Timeout for Ldap Operations
Home Page > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6
« Previous • Trail • Next »
Paged Results Control

BasicControl

The javax.naming.ldap.BasicControl which implements the javax.naming.ldap.Control serves as a base implementation for extending other controls.

Paged Results Control

The paged results control is useful for LDAP clients which want to receive search results in a controlled manner limited by the page size. The page size can be configured by the client as per the availability of its resources, like bandwidth and the processing capability.

The server uses a cookie (similar to the HTTP session cookie mechanism) to maintain the state of the search requests in order to track the results being sent to the client. The paged results control is specified in RFC 2696. The classes below provide the functionality required to support paged results control.

  • javax.naming.ldap.PagedResultsControl
  • javax.naming.ldap.PagedResultsResponseControl
How to use Paged Results Control?
The example below illustrates the client-server interaction between a client doing a search requesting a page size limit of 5. The entire result set returned by the server contains 21 entries.
  1. Client sends a search request asking for paged results with a page size of 5.

    // Activate paged results
     int pageSize = 5; // 5 entries per page
     byte[] cookie = null;
     int total;
     ctx.setRequestControls(new Control[]{
         new PagedResultsControl(pageSize, Control.CRITICAL) });
     // Perform the search
     NamingEnumeration results =
         ctx.search("", "(objectclass=*)", new SearchControls());
  2. The server responds with entries plus an indication of 21 total entries in the search result and an opaque cookie to be used by the client when retrieving subsequent pages.

   // Iterate over a batch of search results sent by the server
         while (results != null && results.hasMore()) {
             // Display an entry
             SearchResult entry = (SearchResult)results.next();
             System.out.println(entry.getName());

             // Handle the entry's response controls (if any)
             if (entry instanceof HasControls) {
                 // ((HasControls)entry).getControls();
             }
         }
   // Examine the paged results control response
         Control[] controls = ctx.getResponseControls();
         if (controls != null) {
             for (int i = 0; i < controls.length; i++) {
                 if (controls[i] instanceof PagedResultsResponseControl) {
                     PagedResultsResponseControl prrc =
                         (PagedResultsResponseControl)controls[i];
                     total = prrc.getResultSize();
                     cookie = prrc.getCookie();
                 } else {
                     // Handle other response controls (if any)
                 }
             }
         }
  3. Client sends an identical search request, returning the opaque cookie, asking for the next page.

  // Re-activate paged results
         ctx.setRequestControls(new Control[]{
             new PagedResultsControl(pageSize, cookie, Control.CRITICAL) });
  4. Server responds with five entries plus an indication that there are more entries The client repeats the search performed in step 4 until a null cookie is returned by the server, which indicates no more entries to be sent by the server.

The complete JNDI example can be found here.

Note: The Paged Search Control is supported by the Windows Active Directory Server. It's not supported by the Sun Java Directory Server version 5.2
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Standard LDAP Controls
Next page: Sort Control


Sort Control (The Java™ Tutorials > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6)

Trail: Java Naming and Directory Interface(TM).
Lesson: New features in JDK 5.0 and JDK 6
New features in JDK 5.0 and JDK 6
Retrieving Distinguished Name
Standard LDAP Controls
Paged Results Control
Sort Control
Manage Referral Control
Manipulating LdapName (Distinguished Name)
Manipulating Relative Distringuished Name (RDN)
Setting Timeout for Ldap Operations
Home Page > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6
« Previous • Trail • Next »
Sort Control
The sort control is used when a client wants the server to send the sorted search results. The server-side sorting is useful in a situation where the client needs to sort the results according to some criteria but is not equipped to perform the sort process on its own. The sort control is specified in RFC 2891. The classes below provide the functionality required to support sort control.
  • javax.naming.ldap.SortControl
  • javax.naming.ldap.SortKey
  • javax.naming.ldap.SortResponseControl

The SortKey is an odered list of keys based upon which the server sorts the result.

How to use Sort Control?
The example below illustrates the client-server interaction between a client performing a search requesting a server-side sorting based on the attribute "cn".
  1. Client sends a search request asking for

    // Activate sorting
     String sortKey = "cn";
     ctx.setRequestControls(new Control[] {
         new SortControl(sortKey, Control.CRITICAL) });

     // Perform a search
     NamingEnumeration results =
         ctx.search("", "(objectclass=*)", new SearchControls());
  2. The server responds with entries that are sorted based on the "cn" attribute and its corresponding matching rule.

    // Iterate over sorted search results
     while (results != null && results.hasMore()) {
         // Display an entry
         SearchResult entry = (SearchResult)results.next();
         System.out.println(entry.getName());

         // Handle the entry's response controls (if any)
         if (entry instanceof HasControls) {
             // ((HasControls)entry).getControls();
         }
     }
     // Examine the sort control response
     Control[] controls = ctx.getResponseControls();
     if (controls != null) {
         for (int i = 0; i < controls.length; i++) {
             if (controls[i] instanceof SortResponseControl) {
                 SortResponseControl src = (SortResponseControl)controls[i];
                 if (! src.isSorted()) {
                     throw src.getException();
                 }
             } else {
                 // Handle other response controls (if any)
             }
         }
     }
    The complete JNDI example can be found here

    Note: The sort control is supported by both Sun Java Directory Server and the Windows Active Directory server.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Paged Results Control
Next page: Manage Referral Control


Manage Referral Control (The Java™ Tutorials > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6)

Trail: Java Naming and Directory Interface(TM).
Lesson: New features in JDK 5.0 and JDK 6
New features in JDK 5.0 and JDK 6
Retrieving Distinguished Name
Standard LDAP Controls
Paged Results Control
Sort Control
Manage Referral Control
Manipulating LdapName (Distinguished Name)
Manipulating Relative Distringuished Name (RDN)
Setting Timeout for Ldap Operations
Home Page > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6
« Previous • Trail • Next »
Manage Referral Control
The Manage Referral control (RFC3296) enables manipulation of the referral and other special objects as normal objects when performing an LDAP operation. In other words, Manage Referral control tells the LDAP server to return referral entries as ordinary entries instead of returning "referral" error responses or continuation references. The new class in JDK 5.0 below enables you to send Manage Referral Control along with an LDAP request:

javax.naming.ldap.ManageReferralControl

The Sun LDAP service provider will send this control automatically along with any request. You can also explicitly enable it setting Context.REFERRAL environment property to "ignore". For more information on Referral handling check the Referrals in the JNDI section of the JNDI Tutorial.

Here is an example that sends Manage Referral control along with an LDAP request.

       // Create initial context
        LdapContext ctx = (LdapContext) new InitialDirContext(env);
        ctx.setRequestControl(new Control[] new ManageReferralControl());

        // Set controls for performing subtree search
        SearchControls ctls = new SearchControls();
        ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);

        // Perform search
        NamingEnumeration answer = ctx.search("", "(objectclass=*)", ctls);

        // Print the answer
        while (answer.hasMore()) {
        System.out.println(">>>" + ((SearchResult)answer.next()).getName());
        }

        // Close the context when we're done
        ctx.close();
The complete example can be found here.
Note 1: The above example will require you to set up a second server using the configuration file refserver.ldif. The server must support LDAP v3 and RFC 3296. If the server does not support referrals in this way, then the example won't work as shown. The configuration file contains referrals that point to the original server that you've set up. It assumes that the original server is on port 389 on the local machine. If you have set up the server on another machine or port, then you need to edit the "ref" entries in the refserver.ldif file and replace "localhost:389" with the appropriate setting. The second server is to be set up on port 489 on the local machine. If you set up the second server on another machine or port, then you need to adjust the setting of the Context.PROVIDER_URL environment property for the initial context accordingly.

Setting up a directory server is typically performed by the directory or system administrator. See the Software Setup lesson for more information.

Note 2: Windows Active Directory: Because Active Directory does not support the Manage Referral control, none of the examples in this lesson will work against Active Directory.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Sort Control
Next page: Manipulating LdapName (Distinguished Name)


Manipulating LdapName (Distinguished Name) (The Java™ Tutorials > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6)

Trail: Java Naming and Directory Interface(TM).
Lesson: New features in JDK 5.0 and JDK 6
New features in JDK 5.0 and JDK 6
Retrieving Distinguished Name
Standard LDAP Controls
Paged Results Control
Sort Control
Manage Referral Control
Manipulating LdapName (Distinguished Name)
Manipulating Relative Distringuished Name (RDN)
Setting Timeout for Ldap Operations
Home Page > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6
« Previous • Trail • Next »
Manipulating LdapName (Distinguished Name)
The Distinguished Name (DN) is used by LDAP in its string representation. The string format used to represent a DN is specified in RFC2253. The DN is made up of components called the Relative Distinguished Names (RDN). Below is an example of a DN:

"CN=Steve Kille, O=Isode Limited, C=GB"

It consist of the following RDNs:
  • CN=Steve Kille
  • O=Isode Limited
  • C=GB

The classes below that are available in JDK 5.0 represent the DN and RDN respectively.

  • javax.naming.ldap.LdapName
  • javax.naming.ldap.Rdn

The LdapName class implements the javax.naming.Name interface similar to the javax.naming.CompoundName and javax.naming.CompositeName classes.

LdapName and Rdn classes allow easy manipulation of DNs and RDNs. Using these APIs it's easy to construct an RDN by pairing up names and values. A DN can be constructed with a list of RDNs. Similarly the individual components of DN and RDN can be retrieved from their string representation.

LdapName

An LdapName can be created with its string representation as defined in RFC2253 or with a list of Rdns. When the former way is used, the specified string is parsed as per the rules defined in RFC2253. An InvalidNameException is thrown if the string is not a valid DN. Here's an example that uses the constructor to parse an LDAP name and print its components.

    String name = "cn=Mango,ou=Fruits,o=Food";
    try {
        LdapName dn = new LdapName(name);
        System.out.println(dn + " has " + dn.size() + " RDNs: ");
        for (int i = 0; i < dn.size(); i++) {
            System.out.println(dn.get(i));
        }
    } catch (InvalidNameException e) {
        System.out.println("Cannot parse name: " + name);
    }
Running this example with an input of "cn=Mango,ou=Fruits,o=Food" produces the following results:

    cn=Mango,ou=Fruits,o=Food has 3 RDNs:
    o=Food
    ou=Fruits
    cn=Mango

The LdapName class contains methods to access its components as RDNs and strings, to modify an LdapName, to compare two LdapNames for equality, and to get a string representation of the name.

Accessing the name components of an LDAP name:

Here are the methods that you can use to access the name components as RDNs and strings:

getRdn(int posn)
get(int posn)
getRdns()
getAll()
getPrefix(int posn)
getSuffix(int posn)
clone()

To retrieve the component at a particular position within an LdapName, you use getRdn() or get(). The previous constructor example shows an example of its use. getRdns() returns a list of all the RDNs and getAll() returns all of the components of an LdapName as an enumeration.

The right most RDN is at index 0, and the left most RDN is at index n-1. For example, the distinguished name: "cn=Mango, ou=Fruits, o=Food" is numbered in the following sequence ranging from 0 to 2: {o=Food, ou=Fruits, cn=Mango}

You can also get a LdapNames's suffix or prefix as a LdapName instance. Here's an example that gets the suffix and prefix of an LDAP name.

    LdapName dn = new LdapName("cn=Mango, ou=Fruits, o=Food");
    Name suffix = dn.getSuffix(1);  // 1 <= index="index" <="<" cn.size()="cn.size()" Name="Name" prefix="dn.getPrefix(1);" //="//" 0="0" <="index" <="<" 1="1"

When you run this program, it generates the following output:

        cn=Mango ou=Fruits
        o=Food

To make a copy of an LdapName, you use clone().

Modifying an LDAP name

Following are the methods that you can use to modify an LDAP name:

add(Rdn rdn)

add(String comp)

add(int posn, String comp)

addAll(List suffixRdns)

addAll(Name suffix)

addAll(int posn, List suffixRdns)

addAll(int posn, Name suffix)

remove(int posn)

After creating an LdapName instance, you can add and remove components from it.
Here's an  example that appends an
LdapName to an existing LdapName,
adds components to the front and the end, and removes the second component.

     LdapName dn = new LdapName("ou=Fruits,o=Food");
     LdapName dn2 = new LdapName("ou=Summer");
     System.out.println(dn.addAll(dn2)); // ou=Summer,ou=Fruits,o=Food
     System.out.println(dn.add(0, "o=Resources")); // ou=Summer,ou=Fruits,o=Food,o=Resources
     System.out.println(dn.add("cn=WaterMelon")); // cn=WaterMelon,ou=Summer,ou=Fruits,o=Food,o=Resources
     System.out.println(dn.remove(1));  // o=Food
     System.out.println(dn);  // cn=WaterMelon,ou=Summer,ou=Fruits,o=Resources

Comparing an LDAP name

Following are the methods that you can use to compare two LDAP names:

compareTo(Object name)

equals(Object name)

endsWith(List)

endWith(Name name)

startsWith(List rdns)

startsWith(Name name)

isEmpty()

You can use compareTo() to sort a list of LdapName instances.
equals() lets you determine whether two LdapNames are syntactically equal.
Two LdapNames are equal if they both have the same (case-exact matched)
components in the same order.

With startsWith() and endsWith(), you can learn whether an LdapName starts
or ends with another LdapName; that is, whether an LdapName is a suffix or
prefix of another LdapName.

The convenience method isEmpty() enables you to determine whether an
LdapName has zero components. You can also use the expression size() == 0 to perform the same check.

Here is an example that
uses some of these comparison methods.

    LdapName one = new LdapName("cn=Vincent Ryan, ou=People, o=JNDITutorial");
    LdapName two = new LdapName("cn=Vincent Ryan");
    LdapName three = new LdapName("o=JNDITutorial");
    LdapName four = new LdapName("");

    System.out.println(one.equals(two)); 	// false
    System.out.println(one.startsWith(three));  // true
    System.out.println(one.endsWith(two));      // true
    System.out.println(one.startsWith(four));   // true
    System.out.println(one.endsWith(four));     // true
    System.out.println(one.endsWith(three));    // false
    System.out.println(one.isEmpty());	        // false
    System.out.println(four.isEmpty());	        // true
    System.out.println(four.size() == 0);	// true

Getting the String Representation

The method below gets you the string representation of an LDAP name
formatted according to the syntax specified in RFC2253:

toString()

When you use the LdapName constructor, you supply the string representation of an LDAP name
and get back an LdapName instance. To do the reverse, that is, to get the string representation
of an LdapName instance, you use toString(). The result of toString() can be fed back to the
constructor to produce a LdapName instance that is equal to the original LdapName instance.
Here's an  example.

    LdapName dn = new LdapName(name);
    String str = dn.toString();
    System.out.println(str);
    LdapName dn2 = new LdapName(str);
    System.out.println(dn.equals(dn2));	 // true

LdapName as an Argument to Context Methods

The Context method require either a composite or a compound name passed as
argument to its methods.

Hence an LdapName can be directly passed to a context method as shown in the
 example below:

    // Create the initial context
    Context ctx = new InitialContext(env);

    // An LDAP name
    LdapName dn = new LdapName("ou=People,o=JNDITutorial");

    // Perform the lookup using the dn
    Object obj = ctx.lookup(dn);

Similarly, when the Context methods return results from list(), listBindings(), or
search() operations, the DN can be retrieved by calling
getNameInNamespace(). The LdapName can be constructed directly from the DN as shown in the
 example below:

     while (answer.hasMore()) {
         SearchResult sr = (SearchResult) answer.next();
         String name = sr.getNameInNamespace();
         System.out.println(name);
         LdapName dn = new LdapName(name);

     // do something with the dn
     }
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Manage Referral Control
Next page: Manipulating Relative Distringuished Name (RDN)


Manipulating Relative Distringuished Name (RDN) (The Java™ Tutorials > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6)

Trail: Java Naming and Directory Interface(TM).
Lesson: New features in JDK 5.0 and JDK 6
New features in JDK 5.0 and JDK 6
Retrieving Distinguished Name
Standard LDAP Controls
Paged Results Control
Sort Control
Manage Referral Control
Manipulating LdapName (Distinguished Name)
Manipulating Relative Distringuished Name (RDN)
Setting Timeout for Ldap Operations
Home Page > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6
« Previous • Trail • Next »
Manipulating Relative Distringuished Name (RDN)
The class javax.naming.ldap.Rdn represents a Relative Distinguished name (RDN) as specified in RFC2253. An RDN represents a component of a DN as explained in the Manipulating LdapName lesson. An RDN is made up of type and value pair(s). Examples of RDNs are:

  • OU=Sun
  • OU=Sales+CN=J.Smith.
    The above example shows a representation of a multi-valued RDN.
The Rdn class provides methods to access name/value pair(s) of an RDN, obtain its string representation, retrieve an Attributes view, compare and determine equality of RDNs and methods to escape and unescape the value part of the RDN.

The Rdn class is immutable.

Constructing an Rdn

An Rdn can be constructed with the specified name and value pair, if it's a single name/value paired RDN. For a multi-valued RDN, you should create an attribute set consisting of all the name/value pairs and use a constructor that takes Attributes as an argument. You can also create an Rdn from its string representation specified in RFC2253. Finally, you can clone an Rdn using its copy constructor. Here is an example that creates RDNs using different types of constructors.

    Rdn rdn1 = new Rdn("ou= Juicy\\, Fruit");
        System.out.println("rdn1:" + rdn1.toString());

        Rdn rdn2 = new Rdn(rdn1);
        System.out.println("rdn2:" + rdn2.toString());

        Attributes attrs = new BasicAttributes();
        attrs.put("ou", "Juicy, Fruit");
        attrs.put("cn", "Mango");
        Rdn rdn3 = new Rdn(attrs);
        System.out.println("rdn3:" + rdn3.toString());

        Rdn rdn4 = new Rdn("ou", "Juicy, Fruit");
        System.out.println("rdn4:" + rdn4.toString());

Accessing type/value pairs of an RDN

The type/values of and RDN can be obtained using the methods below:

getType()
getValue()
toAttributes()

For a an RDN made up of single type/value pair, the getType() method returns the type and the getValue() method returns the value of the RDN. The method toAttributes() returns the attribute view of the type/value pairs. The example below prints the type/value pairs of RDNs.

    Attributes attrs = new BasicAttributes();
        attrs.put("o", "Yellow");
        attrs.put("cn", "Mango");

    // create a binary value for the RDN
        byte[] mangoJuice = new byte[6];
        for (int i = 0; i < mangoJuice.length; i++) {
            mangoJuice[i] = (byte) i;
        }
        attrs.put("ou", mangoJuice);
        Rdn rdn = new Rdn(attrs);

        System.out.println();
        System.out.println("size:" + rdn.size());
        System.out.println("getType(): " + rdn.getType());
        System.out.println("getValue(): " + rdn.getValue());

        // test toAttributes
        System.out.println();
        System.out.println("toAttributes(): " + rdn.toAttributes());

Getting the String Representation

In order to get the string representation of an RDN formatted according to the syntax specified in RFC2253, you can use:

toString()

When you use the Rdn constructor that takes a String argument, you supply the string representation of an RDN, and get back an Rdn instance. To do the reverse, that is, to get the string representation of a Rdn instance, you use toString(). The result of toString() can be fed back to the Rdn constructor to produce an Rdn instance that is equal to the original Rdn instance.

Here's an example:

    Rdn rdn = new Rdn("cn=Juicy\\,Fruit");
    String str = rdn.toString();
    System.out.println(str);
    Rdn rdn2 = new Rdn(str);
    System.out.println(rdn.equals(rdn2));    // true

Comparing RDNs

The methods below enable comparison of RDNs:

equals(Object Rdn)
compareTo(Object Rdn)

You can use compareTo() to sort a list of Rdn instances. equals() lets you determine whether two Rdns are syntactically equal. Two Rdns are equal if they both have the same (case-exact matched) type/value pairs. The order of components in a multi-valued RDNs is not significant.

Here's an example:

    Rdn one = new Rdn("ou=Sales+cn=Bob");
        Rdn two = new Rdn("cn=Bob+ou=Sales");
        Rdn three = new Rdn("ou=Sales+cn=Bob+c=US");
        Rdn four = new Rdn("cn=lowercase");
        Rdn five = new Rdn("cn=LowerCASE");
        System.out.println(one.equals(two));    // true
        System.out.println(two.equals(three));  // false
        System.out.println(one.equals(three));  // false
        System.out.println(four.equals(five));  // true

Escaping and Unescaping of Special Characters

One of the best use of Rdn class is when one has to deal with DNs consisting of special characters. It automatically takes care of escaping and unescaping the special characters. The characters such has '\' (backslash), ','(comma), + (plus) etc have a specific semantic according to RFC2253. You can find the list of all the special characters in RFC2253. When these characters are used as literals in a DN, they must be escaped with a '\' (blackslash).

For example, consider an RDN:

     cn=Juicy, Fruit
The character , (comma) appearing between Juicy and Fruit is a special character that needs to be escaped by a '\' (blackslash). The resulting syntactically formatted RDN looks as below:
    cn=Juicy\, Fruit
However, the '\' (backslash) character itself is a special character according to the Java Language String syntax, and it needs to escaped with a '\' (backslash) again. The Java Language String format and RFC2253 both use '\' (backslash) to escape the special characters. And therefore the Java formatted RDN String looks as below:
    cn=Juicy\\, Fruit
Note that, the above mentioned formatting rules apply only to the value component of an Rdn. The Rdn class provides two static methods to handle automatic escaping and unescaping of the RDN values:

escapeValue()
unescapeValue()

The example below shows how to get the string representation of a DN without having to deal with the syntax for handling special characters defined in RFC2253.

    // DN with ',' (comma)
    String unformatted = "Juicy, Fruit";
    String formatted = Rdn.escapeValue(unformatted);
    LdapName dn = new LdapName("cn=" + formatted);
    System.out.println("dn:" + dn);

    unformatted = "true+false";
    formatted = Rdn.escapeValue(unformatted);
    dn = new LdapName("cn=" + formatted);
    System.out.println("dn:" + dn);

    // DN with a binary value as one one of its attribute value
    byte[] bytes = new byte[] {1, 2, 3, 4};
    formatted = Rdn.escapeValue(bytes);
    System.out.println("Orig val: " + bytes +
        "	Escaped val: " + formatted);
Similarly the using the static unescapeValue() method one can obtain the original string from the formatted value. Here is an example for retrieving the original value.

    // DN with ',' (comma)
    String unformatted = "Juicy, Fruit";
    String formatted = Rdn.escapeValue(unformatted);
    System.out.println("Formatted:" + formatted);
    Object original = Rdn.unescapeValue(formatted);
    System.out.println("Original:" +  original);

    // DN with a '+' (plus)
    unformatted = "true+false";
    formatted = Rdn.escapeValue(unformatted);
    System.out.println("Formatted:" + formatted);
    original = Rdn.unescapeValue(formatted);
    System.out.println("Original:" +  original);

    // DN with a binary value as one one of its attribute value
    byte[] bytes = new byte[] {1, 2, 3, 4};
    formatted = Rdn.escapeValue(bytes);
    System.out.println("Formatted:" + formatted);
    original = Rdn.unescapeValue(formatted);
    System.out.println("Original:" +  original);

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Manipulating LdapName (Distinguished Name)
Next page: Setting Timeout for Ldap Operations


Setting Timeout for Ldap Operations (The Java™ Tutorials > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6)

Trail: Java Naming and Directory Interface(TM).
Lesson: New features in JDK 5.0 and JDK 6
New features in JDK 5.0 and JDK 6
Retrieving Distinguished Name
Standard LDAP Controls
Paged Results Control
Sort Control
Manage Referral Control
Manipulating LdapName (Distinguished Name)
Manipulating Relative Distringuished Name (RDN)
Setting Timeout for Ldap Operations
Home Page > Java Naming and Directory Interface(TM). > New features in JDK 5.0 and JDK 6
« Previous • Trail • Next »
Setting Timeout for Ldap Operations
When an LDAP request is made by a client to a server and the server does not respond for some reason, the client waits forever for the server to respond until the TCP timeouts. On the client-side what the user experiences is esentially a process hang. In order to control the LDAP request in a timely manner, a read timeout can be configured for the Sun JNDI/LDAP Service Provider since Java SE 6.

The new environment property:

 com.sun.jndi.ldap.read.timeout
can be used to specify the read timeout for an LDAP operation. The value of this property is the string representation of an integer representing the read timeout in milliseconds for LDAP operations. If the LDAP provider doesn't get an LDAP response within the specified period, it aborts the read attempt. The integer should be greater than zero. An integer less than or equal to zero means no read timeout is specified which is equivalent to waiting for the response infinitely until it is received which defaults to the original behavior.

If this property is not specified, the default is to wait for the response until it is received.
For example,

    env.put("com.sun.jndi.ldap.read.timeout", "5000");
causes the LDAP service provider to abort the read attempt if the server does not respond with a reply within 5 seconds.

Here is an example that uses a dummy server which does not respond to LDAP requests to show how this property behaves when set to a non-zero value.

    env.put(Context.INITIAL_CONTEXT_FACTORY,
             "com.sun.jndi.ldap.LdapCtxFactory");
    env.put("com.sun.jndi.ldap.read.timeout", "1000");
    env.put(Context.PROVIDER_URL, "ldap://localhost:2001");

    Server s = new Server();

    try {

             // start the server
             s.start();

           // Create initial context
           DirContext ctx = new InitialDirContext(env);
           System.out.println("LDAP Client: Connected to the Server");
        :
            :
     } catch (NamingException e) {
            e.printStackTrace();
    }

The above program prints the stack trace below, as the server does not even respond to the LDAP bind request when an InitialDirContext is created. The client times out waiting for the server's response.

    Server: Connection accepted
    javax.naming.NamingException: LDAP response read timed out, timeout used:1000ms.
    :
    :

        at javax.naming.directory.InitialDirContext.(InitialDirContext.java:82)
        at ReadTimeoutTest.main(ReadTimeoutTest.java:32)
Note that this property is different from the another environment property com.sun.jndi.ldap.connect.timeout that sets the timeout for connecting to the server. The read timeout applies to the LDAP response from the server after the initial connection is established with the server.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Manipulating Relative Distringuished Name (RDN)
Next page: End of Trail


Trail: Drag and Drop (The Java™ Tutorials)

Home Page
« Previous
Trail: Drag and Drop
Please check out the drag and drop lesson in the Swing tutorial:
Introduction to DnD
The lesson tells how to use the drag-and-drop support built into Swing components and contains many examples that implement drag-and-drop and cut/copy/paste support.
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: End of Trail


The Really Big Index
A list of all content pages in the The JavaTM Tutorial

Trail: Getting Started

The Java Technology Phenomenon
About the Java Technology
What Can Java Technology Do?
How Will Java Technology Change My Life?
The "Hello World!" Application
"Hello World!" for the NetBeans IDE
"Hello World!" for Microsoft Windows
"Hello World!" for Solaris OS and Linux
A Closer Look at the "Hello World!" Application
Questions and Exercises: Getting Started
Common Problems (and Their Solutions)

Trail: Learning the Java Language

Object-Oriented Programming Concepts
What Is an Object?
What Is a Class?
What Is Inheritance?
What Is an Interface?
What Is a Package?
Questions and Exercises: Object-Oriented Programming Concepts
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises: Variables
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises: Operators
Expressions, Statements, and Blocks
Questions and Exercises: Expressions, Statements, and Blocks
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises: Control Flow Statements
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises: Classes
Questions and Exercises: Objects
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises: Nested Classes
Enum Types
Questions and Exercises: Enum Types
Annotations
Questions and Exercises: Annotations
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises: Interfaces
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises: Inheritance
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises: Numbers
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises: Characters and Strings
Generics
Introduction
Generic Types
Generic Methods and Constructors
Bounded Type Parameters
Subtyping
Wildcards
Type Erasure
Summary of Generics
Questions and Exercises: Generics
Packages
Creating and Using Packages
Creating a Package
Naming a Package
Using Package Members
Managing Source and Class Files
Summary of Creating and Using Packages
Questions and Exercises: Creating and Using Packages

Trail: Essential Classes

Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises: Basic I/O
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises: Concurrency
The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises: The Platform Environment
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises: Regular Expressions

Trail: Deployment

Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Java Web Start
Running Java Web Start Applications
Deploying Java Web Start Applications
Developing Java Web Start Applications
The JNLP API
Java Web Start and Security
Common Java Web Start Problems
Questions and Exercises: Java Web Start
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises: Java Applets

Trail: Graphical User Interfaces

A Brief Introduction to the Swing Package
What is Swing?
A Swing Demo
Swing Features
A Visual Guide to Swing Components (Java Look and Feel)
A Visual Guide to Swing Components (Windows Look and Feel)
Pluggable Look and Feel
Data Transfer
Internationalization and Localization
Accessibility
Integrating with the Desktop
System Tray Icon Support
Questions and Exercises: Graphical User Interfaces

Trail: Creating a GUI with JFC/Swing

Getting Started with Swing
About the JFC and Swing
Compiling and Running Swing Programs
Learning Swing with the NetBeans IDE
Setting up the CelsiusConverter Project
NetBeans IDE Basics
Creating the CelsiusConverter GUI
Adjusting the CelsiusConverter GUI
Adding the Application Logic
Questions and Exercises: Learning Swing with the NetBeans IDE
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Questions and Exercises: Using Swing Components
Concurrency in Swing
Initial Threads
The Event Dispatch Thread
Worker Threads and SwingWorker
Simple Background Tasks
Tasks that Have Interim Results
Canceling Background Tasks
Bound Properties and Status Methods
Questions and Exercises: Concurrency in Swing
Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Questions and Exercises: Laying Out Components within a Container
Modifying the Look and Feel
How to Set the Look and Feel
The Synth Look and Feel
A Synth Example
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Questions and Exercises: Writing Event Listeners
Performing Custom Painting
Creating the Demo Application (Step 1)
Creating the Demo Application (Step 2)
Creating the Demo Application (Step 3)
Refining the Design
A Closer Look at the Paint Mechanism
Summary
Solving Common Painting Problems

Trail: Collections

Introduction to Collections
Interfaces
The Collection Interface
The Set Interface
The List Interface
The Queue Interface
The Map Interface
Object Ordering
The SortedSet Interface
The SortedMap Interface
Summary of Interfaces
Questions and Exercises: Interfaces
Implementations
Set Implementations
List Implementations
Map Implementations
Queue Implementations
Wrapper Implementations
Convenience Implementations
Summary of Implementations
Questions and Exercises: Implementations
Algorithms
Custom Collection Implementations
Interoperability
Compatibility
API Design

Trail: Internationalization

Introduction
A Quick Example
Before Internationalization
After Internationalization
Running the Sample Program
Internationalizing the Sample Program
Checklist
Setting the Locale
Creating a Locale
Identifying Available Locales
The Scope of a Locale
Locale-Sensitive Services SPI
Isolating Locale-Specific Data
About the ResourceBundle Class
Preparing to Use a ResourceBundle
Backing a ResourceBundle with Properties Files
Using a ListResourceBundle
Customizing Resource Bundle Loading
Formatting
Numbers and Currencies
Using Predefined Formats
Customizing Formats
Dates and Times
Using Predefined Formats
Customizing Formats
Changing Date Format Symbols
Messages
Dealing with Compound Messages
Handling Plurals
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Internationalization of Network Resources
Internationalized Domain Name
Internationalized Resource Identifier

Trail: 2D Graphics

Overview of the Java 2D API Concepts
Coordinates
Java 2D Rendering
Geometric Primitives
Text
Images
Printing
Getting Started with Graphics
Working with Geometry
Drawing Geometric Primitives
Drawing Arbitrary Shapes
Stroking and Filling Graphics Primitives
Working with Text APIs
Selecting a Font
Measuring Text
Advanced Text Display
Displaying Antialiased Text by Using Rendering Hints
Using Text Attributes to Style Text
Drawing Multiple Lines of Text
Working with Images
Reading/Loading an Image
Drawing an Image
Creating and Drawing to an Image
Writing/Saving an Image
Printing
A Basic Printing Program
Using Print Setup Dialogs
Printing a Multiple Page Document
Working with Print Services and Attributes
Printing the Contents of a User Interface
Printing Support in Swing Components
Advanced Topics in Java2D
Transforming Shapes, Text, and Images
Clipping the Drawing Region
Compositing Graphics
Controlling Rendering Quality
Constructing Complex Shapes from Geometry Primitives
Supporting User Interaction

Trail: Sound

Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services

Trail: JavaBeans(TM)

JavaBeans Concepts
Using the NetBeans GUI Builder
Writing a Simple Bean
Properties
Simple Properties
Bound Properties
Constrained Properties
Indexed Properties
Manipulating Events
Bean Persistence
Long Term Persistence
Introspection
Bean Customization
Using the BeanContext API
Overview of the BeanContext API
Bean Context #1: Containment Only
Bean Context #2: Containment and Services
AWT Containers and the BeanContextProxy Interface

Trail: JDBC(TM) Database Access

JDBC Introduction
JDBC Architecture
A Relational Database Overview
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application

Trail: Java Management Extensions (JMX)

Overview of the JMX Technology
Why Use the JMX Technology?
Architecture of the JMX Technology
Monitoring and Management of the Java Virtual Machine
Introducing MBeans
Standard MBeans
MXBeans
Notifications
Remote Management
Exposing a Resource for Remote Management By JConsole
Creating a Custom JMX Client

Trail: RMI

An Overview of RMI Applications
Writing an RMI Server
Designing a Remote Interface
Implementing a Remote Interface
Creating a Client Program
Compiling and Running the Example
Compiling the Example Programs
Running the Example Programs

Trail: Security Features in Java SE

Security Features Overview
Quick Tour of Controlling Applets
Observe Applet Restrictions
Set up a Policy File to Grant the Required Permission
Start Policy Tool
Grant the Required Permission
Save the Policy File
See the Policy File Effects
Quick Tour of Controlling Applications
Observe Application Freedom
See How to Restrict Applications
Set up the Policy File to Grant the Required Permissions
Open the Policy File
Grant the Required Permissions
Save the Policy File
See the Policy File Effects
API and Tools Use for Secure Code and File Exchanges
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Exchanging Files
Steps for the Contract Sender
Create a JAR File Containing the Contract
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Contract Receiver
Import the Certificate as a Trusted Certificate
Verify the JAR File Signature
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Implementing Your Own Permission
TerrysGame
The HighScore Class
The HighScorePermission Class
A Sample Policy File
Putting It All Together
Steps for the HighScore Developer (Chris)
Steps for the TerrysGame Developer (Terry)
Steps for a User Running TerrysGame (Kim)

Trail: The Extension Mechanism

Creating and Using Extensions
Installed Extensions
Download Extensions
Understanding Extension Class Loading
Making Extensions Secure
Setting Privileges for Extensions
Sealing Packages in Extensions

Trail: The Reflection API

Classes
Retrieving Class Objects
Examining Class Modifiers and Types
Discovering Class Members
Troubleshooting
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Arrays and Enumerated Types
Arrays
Identifying Array Types
Creating New Arrays
Getting and Setting Arrays and Their Components
Troubleshooting
Enumerated Types
Examining Enums
Getting and Setting Fields with Enum Types
Troubleshooting

Trail: Custom Networking

Overview of Networking
What You May Already Know About Networking in Java
Networking Basics
Working with URLs
What Is a URL?
Creating a URL
Parsing a URL
Reading Directly from a URL
Connecting to a URL
Reading from and Writing to a URLConnection
All About Sockets
What Is a Socket?
Reading from and Writing to a Socket
Writing the Server Side of a Socket
All About Datagrams
What Is a Datagram?
Writing a Datagram Client and Server
Broadcasting to Multiple Recipients
Programmatic Access to Network Parameters
What Is a Network Interface?
Retrieving Network Interfaces
Listing Network Interface Addresses
Network Interface Parameters
Working With Cookies
HTTP State Management With Cookies
CookieHandler Callback Mechanism
Default CookieManager
Custom CookieManager

Trail: Bonus

Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode
Display Mode
Passive vs. Active Rendering
Double Buffering and Page Flipping
BufferStrategy and BufferCapabilities
Examples
Preparation for Java Programmer Language Certification

Trail: Java Naming and Directory Interface(TM).

Naming and Directory Concepts
Directory Concepts
Overview of JNDI
Naming Package
Directory and LDAP Packages
Event and Service Provider Packages
Software Setup
LDAP Setup
Java Application Setup
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Java Objects in the Directory
Storing and Reading Objects
Serializable Objects
New features in JDK 5.0 and JDK 6
Retrieving Distinguished Name
Standard LDAP Controls
Paged Results Control
Sort Control
Manage Referral Control
Manipulating LdapName (Distinguished Name)
Manipulating Relative Distringuished Name (RDN)
Setting Timeout for Ldap Operations

Trail: Drag and Drop

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.


Search The Java Tutorial

The JavaTM Tutorial

Search the JavaTM Tutorial

Search:

Help on searching is available.

You can also perform a targeted search of each release's API documentation and of additional code examples.

All of the material in The Java Tutorial is copyright-protected and may not be published in other works without express written permission from Sun Microsystems.


2D Graphics: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
2D Graphics: End of Trail
You've reached the end of the "2D Graphics" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

Creating a GUI with JFC/Swing: You can apply what you learned in this trail about 2D graphics when writing custom Swing components.

Sound: Learn how to use sound to enhance your program's user interface.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Supporting User Interaction


Trail: 2D Graphics: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: 2D Graphics: Table of Contents
Overview of the Java 2D API Concepts
Coordinates
Java 2D Rendering
Geometric Primitives
Text
Images
Printing
Getting Started with Graphics
Working with Geometry
Drawing Geometric Primitives
Drawing Arbitrary Shapes
Stroking and Filling Graphics Primitives
Working with Text APIs
Selecting a Font
Measuring Text
Advanced Text Display
Displaying Antialiased Text by Using Rendering Hints
Using Text Attributes to Style Text
Drawing Multiple Lines of Text
Working with Images
Reading/Loading an Image
Drawing an Image
Creating and Drawing to an Image
Writing/Saving an Image
Printing
A Basic Printing Program
Using Print Setup Dialogs
Printing a Multiple Page Document
Working with Print Services and Attributes
Printing the Contents of a User Interface
Printing Support in Swing Components
Advanced Topics in Java2D
Transforming Shapes, Text, and Images
Clipping the Drawing Region
Compositing Graphics
Controlling Rendering Quality
Constructing Complex Shapes from Geometry Primitives
Supporting User Interaction
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Collections: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
Collections: End of Trail
You've reached the end of the "Collections" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

Essential Java Classes: This trail covers other classes and interfaces that are essential to most Java programs.

Internationalization: This trail shows you how to ready your program for users all over the world. The information about formatting dates, numbers, and strings can be used by any program.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: API Design


Trail: Collections: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: Collections: Table of Contents
Introduction to Collections
Interfaces
The Collection Interface
The Set Interface
The List Interface
The Queue Interface
The Map Interface
Object Ordering
The SortedSet Interface
The SortedMap Interface
Summary of Interfaces
Questions and Exercises: Interfaces
Implementations
Set Implementations
List Implementations
Map Implementations
Queue Implementations
Wrapper Implementations
Convenience Implementations
Summary of Implementations
Questions and Exercises: Implementations
Algorithms
Custom Collection Implementations
Interoperability
Compatibility
API Design
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Answers to Questions and Exercises: (The Java™ Tutorials > Collections > Implementations)

Trail: Collections
Lesson: Implementations
Home Page > Collections > Implementations
« Previous • TOC
Answers to Questions and Exercises:

Questions

  1. Question: You plan to write a program that uses several basic collection interfaces: Set, List, Queue, and Map. You're not sure which implementations will work best, so you decide to use general-purpose implementations until you get a better idea how your program will work in the real world. Which implementations are these?

    Answer:
    Set: HashSet
    List: ArrayList
    Queue: LinkedList
    Map: HashMap Question: If you need a Set implementation that provides value-ordered iteration, which class should you use?

    Answer: TreeSet guarantees that the sorted set is in ascending element order, sorted according to the natural order of the elements or by the Comparator provided.

  2. Question: Which class do you use to access wrapper implementations?

    Answer: You use the Collections class, which provides static methods that operate on or return collections.

Exercises

  1. Exercise: Write a program that reads a text file, specified by the first command line argument, into a List. The program should then print random lines from the file, the number of lines printed to be specified by the second command line argument. Write the program so that a correctly-sized collection is allocated all at once, instead of being gradually expanded as the file is read in. Hint: To determine the number of lines in the file, use java.io.File.length to obtain the size of the file, then divide by an assumed size of an average line.

    Answer: Since we're accessing the List randomly, we'll use ArrayList. We estimate the number of lines by taking the file size and dividing by 50. We then double that figure, since it's more efficient to overestimate than to underestmate.

    /*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.*;
import java.io.*;

public class FileList {
    public static void main(String[] args) {
        final int assumedLineLength = 50;
        File file = new File(args[0]);
        List<String> fileList =
            new ArrayList<String>((int)(file.length() / assumedLineLength) * 2);
        BufferedReader reader = null;
        int lineCount = 0;
        try {
            reader = new BufferedReader(new FileReader(file));
            for (String line = reader.readLine(); line != null;
                    line = reader.readLine()) {
                fileList.add(line);
                lineCount++;
            }
        } catch (IOException e) {
            System.err.format("Could not read %s: %s%n", file, e);
            System.exit(1);
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {}
            }
        }
        int repeats = Integer.parseInt(args[1]);
        Random random = new Random();
        for (int i = 0; i < repeats; i++) {
            System.out.format("%d: %s%n", i,
                    fileList.get(random.nextInt(lineCount - 1)));
        }
    }
}
    This program actually spends most of its time reading in the file, so pre-allocating the ArrayList has little affect on its performance. Specifying an initial capacity in advance is more likely to be useful when your program repeatly creates large ArrayList objects without intervening I/O.
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Implementations


aa
aah
aahed
aahing
aahs
aal
aalii
aaliis
aals
aardvark
aardwolf
aargh
aarrgh
aarrghh
aas
aasvogel
ab
aba
abaca
abacas
abaci
aback
abacus
abacuses
abaft
abaka
abakas
abalone
abalones
abamp
abampere
abamps
abandon
abandons
abapical
abas
abase
abased
abasedly
abaser
abasers
abases
abash
abashed
abashes
abashing
abasia
abasias
abasing
abatable
abate
abated
abater
abaters
abates
abating
abatis
abatises
abator
abators
abattis
abattoir
abaxial
abaxile
abba
abbacies
abbacy
abbas
abbatial
abbe
abbes
abbess
abbesses
abbey
abbeys
abbot
abbotcy
abbots
abdicate
abdomen
abdomens
abdomina
abduce
abduced
abducens
abducent
abduces
abducing
abduct
abducted
abductor
abducts
abeam
abed
abele
abeles
abelia
abelian
abelias
abelmosk
aberrant
abet
abetment
abets
abettal
abettals
abetted
abetter
abetters
abetting
abettor
abettors
abeyance
abeyancy
abeyant
abfarad
abfarads
abhenry
abhenrys
abhor
abhorred
abhorrer
abhors
abidance
abide
abided
abider
abiders
abides
abiding
abigail
abigails
ability
abioses
abiosis
abiotic
abject
abjectly
abjure
abjured
abjurer
abjurers
abjures
abjuring
ablate
ablated
ablates
ablating
ablation
ablative
ablaut
ablauts
ablaze
able
ablegate
abler
ables
ablest
ablings
ablins
abloom
abluent
abluents
ablush
abluted
ablution
ably
abmho
abmhos
abnegate
abnormal
abo
aboard
abode
aboded
abodes
aboding
abohm
abohms
aboideau
aboil
aboiteau
abolish
abolla
abollae
aboma
abomas
abomasa
abomasal
abomasi
abomasum
abomasus
aboon
aboral
aborally
aborning
abort
aborted
aborter
aborters
aborting
abortion
abortive
aborts
abos
abought
aboulia
aboulias
aboulic
abound
abounded
abounds
about
above
aboves
abrachia
abradant
abrade
abraded
abrader
abraders
abrades
abrading
abrasion
abrasive
abreact
abreacts
abreast
abri
abridge
abridged
abridger
abridges
abris
abroach
abroad
abrogate
abrosia
abrosias
abrupt
abrupter
abruptly
abs
abscess
abscise
abscised
abscises
abscisin
abscissa
abscond
absconds
abseil
abseiled
abseils
absence
absences
absent
absented
absentee
absenter
absently
absents
absinth
absinthe
absinths
absolute
absolve
absolved
absolver
absolves
absonant
absorb
absorbed
absorber
absorbs
abstain
abstains
absterge
abstract
abstrict
abstruse
absurd
absurder
absurdly
absurds
abubble
abulia
abulias
abulic
abundant
abusable
abuse
abused
abuser
abusers
abuses
abusing
abusive
abut
abutilon
abutment
abuts
abuttal
abuttals
abutted
abutter
abutters
abutting
abuzz
abvolt
abvolts
abwatt
abwatts
aby
abye
abyes
abying
abys
abysm
abysmal
abysms
abyss
abyssal
abysses
acacia
acacias
academe
academes
academia
academic
academy
acajou
acajous
acaleph
acalephe
acalephs
acanthi
acanthus
acapnia
acapnias
acari
acarid
acaridan
acarids
acarine
acarines
acaroid
acarpous
acarus
acaudal
acaudate
acauline
acaulose
acaulous
accede
acceded
acceder
acceders
accedes
acceding
accent
accented
accentor
accents
accept
accepted
acceptee
accepter
acceptor
accepts
access
accessed
accesses
accident
accidia
accidias
accidie
accidies
acclaim
acclaims
accolade
accord
accorded
accorder
accords
accost
accosted
accosts
account
accounts
accouter
accoutre
accredit
accrete
accreted
accretes
accrual
accruals
accrue
accrued
accrues
accruing
accuracy
accurate
accursed
accurst
accusal
accusals
accusant
accuse
accused
accuser
accusers
accuses
accusing
accustom
ace
aced
acedia
acedias
aceldama
acentric
acequia
acequias
acerate
acerated
acerb
acerbate
acerber
acerbest
acerbic
acerbity
acerola
acerolas
acerose
acerous
acervate
acervuli
aces
acescent
aceta
acetal
acetals
acetamid
acetate
acetated
acetates
acetic
acetify
acetin
acetins
acetone
acetones
acetonic
acetose
acetous
acetoxyl
acetum
acetyl
acetylic
acetyls
ache
ached
achene
achenes
achenial
aches
achier
achiest
achieve
achieved
achiever
achieves
achillea
achiness
aching
achingly
achiote
achiotes
acholia
acholias
achoo
achromat
achromic
achy
acicula
aciculae
acicular
aciculas
aciculum
acid
acidemia
acidhead
acidic
acidify
acidity
acidly
acidness
acidoses
acidosis
acidotic
acids
aciduria
acidy
acierate
aciform
acinar
acing
acini
acinic
acinose
acinous
acinus
ackee
ackees
aclinic
acmatic
acme
acmes
acmic
acne
acned
acnes
acnode
acnodes
acock
acold
acolyte
acolytes
aconite
aconites
aconitic
aconitum
acorn
acorns
acoustic
acquaint
acquest
acquests
acquire
acquired
acquirer
acquires
acquit
acquits
acrasia
acrasias
acrasin
acrasins
acre
acreage
acreages
acred
acres
acrid
acrider
acridest
acridine
acridity
acridly
acrimony
acrobat
acrobats
acrodont
acrogen
acrogens
acrolect
acrolein
acrolith
acromia
acromial
acromion
acronic
acronym
acronyms
acrosome
across
acrostic
acrotic
acrotism
acrylate
acrylic
acrylics
act
acta
actable
acted
actin
actinal
acting
actings
actinia
actiniae
actinian
actinias
actinic
actinide
actinism
actinium
actinoid
actinon
actinons
actins
action
actions
activate
active
actively
actives
activism
activist
activity
activize
actor
actorish
actors
actress
actressy
acts
actual
actually
actuary
actuate
actuated
actuates
actuator
acuate
acuities
acuity
aculeate
aculei
aculeus
acumen
acumens
acutance
acute
acutely
acuter
acutes
acutest
acyclic
acyl
acylate
acylated
acylates
acyloin
acyloins
acyls
ad
adage
adages
adagial
adagio
adagios
adamance
adamancy
adamant
adamants
adamsite
adapt
adapted
adapter
adapters
adapting
adaption
adaptive
adaptor
adaptors
adapts
adaxial
add
addable
addax
addaxes
added
addedly
addend
addenda
addends
addendum
adder
adders
addible
addict
addicted
addicts
adding
addition
additive
additory
addle
addled
addles
addling
address
addrest
adds
adduce
adduced
adducent
adducer
adducers
adduces
adducing
adduct
adducted
adductor
adducts
adeem
adeemed
adeeming
adeems
adenine
adenines
adenitis
adenoid
adenoids
adenoma
adenomas
adenoses
adenosis
adenyl
adenyls
adept
adepter
adeptest
adeptly
adepts
adequacy
adequate
adhere
adhered
adherend
adherent
adherer
adherers
adheres
adhering
adhesion
adhesive
adhibit
adhibits
adieu
adieus
adieux
adios
adipic
adipose
adiposes
adiposis
adipous
adit
adits
adjacent
adjoin
adjoined
adjoins
adjoint
adjoints
adjourn
adjourns
adjudge
adjudged
adjudges
adjunct
adjuncts
adjure
adjured
adjurer
adjurers
adjures
adjuring
adjuror
adjurors
adjust
adjusted
adjuster
adjustor
adjusts
adjutant
adjuvant
adman
admass
admen
admiral
admirals
admire
admired
admirer
admirers
admires
admiring
admit
admits
admitted
admitter
admix
admixed
admixes
admixing
admixt
admonish
adnate
adnation
adnexa
adnexal
adnoun
adnouns
ado
adobe
adobes
adobo
adobos
adonis
adonises
adopt
adopted
adoptee
adoptees
adopter
adopters
adopting
adoption
adoptive
adopts
adorable
adorably
adore
adored
adorer
adorers
adores
adoring
adorn
adorned
adorner
adorners
adorning
adorns
ados
adown
adoze
adrenal
adrenals
adrift
adroit
adroiter
adroitly
ads
adscript
adsorb
adsorbed
adsorber
adsorbs
adularia
adulate
adulated
adulates
adulator
adult
adultery
adultly
adults
adumbral
adunc
aduncate
aduncous
adust
advance
advanced
advancer
advances
advect
advected
advects
advent
advents
adverb
adverbs
adverse
advert
adverted
adverts
advice
advices
advise
advised
advisee
advisees
adviser
advisers
advises
advising
advisor
advisors
advisory
advocacy
advocate
advowson
adynamia
adynamic
adyta
adytum
adz
adze
adzes
adzuki
adzukis
ae
aecia
aecial
aecidia
aecidial
aecidium
aecium
aedes
aedile
aediles
aedine
aegis
aegises
aeneous
aeneus
aeolian
aeon
aeonian
aeonic
aeons
aequorin
aerate
aerated
aerates
aerating
aeration
aerator
aerators
aerial
aerially
aerials
aerie
aeried
aerier
aeries
aeriest
aerified
aerifies
aeriform
aerify
aerily
aero
aerobe
aerobes
aerobia
aerobic
aerobics
aerobium
aeroduct
aerodyne
aerofoil
aerogel
aerogels
aerogram
aerolite
aerolith
aerology
aeronaut
aeronomy
aerosat
aerosats
aerosol
aerosols
aerostat
aerugo
aerugos
aery
aesthete
aestival
aether
aetheric
aethers
afar
afars
afeard
afeared
afebrile
aff
affable
affably
affair
affaire
affaires
affairs
affect
affected
affecter
affects
afferent
affiance
affiant
affiants
affiche
affiches
affinal
affine
affined
affinely
affines
affinity
affirm
affirmed
affirmer
affirms
affix
affixal
affixed
affixer
affixers
affixes
affixial
affixing
afflatus
afflict
afflicts
affluent
afflux
affluxes
afford
afforded
affords
afforest
affray
affrayed
affrayer
affrays
affright
affront
affronts
affusion
afghan
afghani
afghanis
afghans
afield
afire
aflame
afloat
aflutter
afoot
afore
afoul
afraid
afreet
afreets
afresh
afrit
afrits
aft
after
afters
aftertax
aftmost
aftosa
aftosas
ag
aga
again
against
agalloch
agalwood
agama
agamas
agamete
agametes
agamic
agamous
agapae
agapai
agape
agapeic
agar
agaric
agarics
agarose
agaroses
agars
agas
agate
agates
agatize
agatized
agatizes
agatoid
agave
agaves
agaze
age
aged
agedly
agedness
agee
ageing
ageings
ageism
ageisms
ageist
ageists
ageless
agelong
agencies
agency
agenda
agendas
agendum
agendums
agene
agenes
ageneses
agenesia
agenesis
agenetic
agenize
agenized
agenizes
agent
agential
agenting
agentive
agentry
agents
ager
ageratum
agers
ages
aggadic
agger
aggers
aggie
aggies
aggrade
aggraded
aggrades
aggress
aggrieve
aggro
aggros
agha
aghas
aghast
agile
agilely
agility
agin
aging
agings
aginner
aginners
agio
agios
agiotage
agism
agisms
agist
agisted
agisting
agists
agitable
agitate
agitated
agitates
agitato
agitator
agitprop
aglare
agleam
aglee
aglet
aglets
agley
aglimmer
aglitter
aglow
agly
aglycon
aglycone
aglycons
agma
agmas
agminate
agnail
agnails
agnate
agnates
agnatic
agnation
agnize
agnized
agnizes
agnizing
agnomen
agnomens
agnomina
agnosia
agnosias
agnostic
ago
agog
agon
agonal
agone
agones
agonic
agonies
agonise
agonised
agonises
agonist
agonists
agonize
agonized
agonizes
agons
agony
agora
agorae
agoras
agorot
agoroth
agouti
agouties
agoutis
agouty
agrafe
agrafes
agraffe
agraffes
agrapha
agraphia
agraphic
agrarian
agravic
agree
agreed
agreeing
agrees
agrestal
agrestic
agria
agrias
agrimony
agrology
agronomy
aground
agrypnia
ague
aguelike
agues
agueweed
aguish
aguishly
ah
aha
ahchoo
ahead
ahem
ahimsa
ahimsas
ahold
aholds
ahorse
ahoy
ahull
ai
aiblins
aid
aide
aided
aider
aiders
aides
aidful
aiding
aidless
aidman
aidmen
aids
aiglet
aiglets
aigret
aigrets
aigrette
aiguille
aikido
aikidos
ail
ailed
aileron
ailerons
ailing
ailment
ailments
ails
aim
aimed
aimer
aimers
aimful
aimfully
aiming
aimless
aims
ain
ains
ainsell
ainsells
aioli
aiolis
air
airboat
airboats
airborne
airbound
airbrush
airburst
airbus
airbuses
aircheck
aircoach
aircraft
aircrew
aircrews
airdate
airdates
airdrome
airdrop
airdrops
aired
airer
airers
airest
airfare
airfares
airfield
airflow
airflows
airfoil
airfoils
airframe
airglow
airglows
airhead
airheads
airhole
airholes
airier
airiest
airily
airiness
airing
airings
airless
airlift
airlifts
airlike
airline
airliner
airlines
airmail
airmails
airman
airmen
airn
airns
airpark
airparks
airplane
airplay
airplays
airport
airports
airpost
airposts
airpower
airproof
airs
airscape
airscrew
airshed
airsheds
airship
airships
airsick
airspace
airspeed
airstrip
airt
airted
airth
airthed
airthing
airths
airtight
airtime
airtimes
airting
airts
airward
airwave
airwaves
airway
airways
airwise
airwoman
airwomen
airy
ais
aisle
aisled
aisles
aisleway
ait
aitch
aitches
aits
aiver
aivers
ajar
ajee
ajiva
ajivas
ajowan
ajowans
ajuga
ajugas
akee
akees
akela
akelas
akene
akenes
akimbo
akin
akvavit
akvavits
al
ala
alack
alacrity
alae
alameda
alamedas
alamo
alamode
alamodes
alamos
alan
aland
alands
alane
alang
alanin
alanine
alanines
alanins
alans
alant
alants
alanyl
alanyls
alar
alarm
alarmed
alarming
alarmism
alarmist
alarms
alarum
alarumed
alarums
alary
alas
alaska
alaskas
alastor
alastors
alate
alated
alates
alation
alations
alb
alba
albacore
albas
albata
albatas
albedo
albedoes
albedos
albeit
albicore
albinal
albinic
albinism
albino
albinos
albite
albites
albitic
albizia
albizias
albizzia
albs
album
albumen
albumens
albumin
albumins
albumose
albums
alburnum
alcade
alcades
alcahest
alcaic
alcaics
alcaide
alcaides
alcalde
alcaldes
alcayde
alcaydes
alcazar
alcazars
alchemic
alchemy
alchymy
alcid
alcidine
alcids
alcohol
alcohols
alcove
alcoved
alcoves
aldehyde
alder
alderfly
alderman
aldermen
alders
aldol
aldolase
aldols
aldose
aldoses
aldrin
aldrins
ale
aleatory
alec
alecs
alee
alef
alefs
alegar
alegars
alehouse
alembic
alembics
alencon
alencons
aleph
alephs
alert
alerted
alerter
alertest
alerting
alertly
alerts
ales
aleuron
aleurone
aleurons
alevin
alevins
alewife
alewives
alexia
alexias
alexin
alexine
alexines
alexins
alfa
alfaki
alfakis
alfalfa
alfalfas
alfaqui
alfaquin
alfaquis
alfas
alforja
alforjas
alfresco
alga
algae
algal
algaroba
algas
algebra
algebras
algerine
algicide
algid
algidity
algin
alginate
algins
algoid
algology
algor
algorism
algors
algum
algums
alias
aliases
alibi
alibied
alibies
alibiing
alibis
alible
alidad
alidade
alidades
alidads
alien
alienage
alienate
aliened
alienee
alienees
aliener
alieners
aliening
alienism
alienist
alienly
alienor
alienors
aliens
alif
aliform
alifs
alight
alighted
alights
align
aligned
aligner
aligners
aligning
aligns
alike
aliment
aliments
alimony
aline
alined
aliner
aliners
alines
alining
aliped
alipeds
aliquant
aliquot
aliquots
alist
alit
aliunde
alive
aliya
aliyah
aliyahs
aliyas
aliyos
aliyot
alizarin
alkahest
alkali
alkalic
alkalies
alkalify
alkalin
alkaline
alkalis
alkalise
alkalize
alkaloid
alkane
alkanes
alkanet
alkanets
alkene
alkenes
alkies
alkine
alkines
alkoxide
alkoxy
alky
alkyd
alkyds
alkyl
alkylate
alkylic
alkyls
alkyne
alkynes
all
allanite
allay
allayed
allayer
allayers
allaying
allays
allee
allees
allege
alleged
alleger
allegers
alleges
alleging
allegory
allegro
allegros
allele
alleles
allelic
allelism
alleluia
allergen
allergic
allergin
allergy
alley
alleys
alleyway
allheal
allheals
alliable
alliance
allicin
allicins
allied
allies
allium
alliums
allobar
allobars
allocate
allod
allodia
allodial
allodium
allods
allogamy
allonge
allonges
allonym
allonyms
allopath
allot
allots
allotted
allottee
allotter
allotype
allotypy
allover
allovers
allow
allowed
allowing
allows
alloxan
alloxans
alloy
alloyed
alloying
alloys
alls
allseed
allseeds
allspice
allude
alluded
alludes
alluding
allure
allured
allurer
allurers
allures
alluring
allusion
allusive
alluvia
alluvial
alluvion
alluvium
ally
allying
allyl
allylic
allyls
alma
almagest
almah
almahs
almanac
almanacs
almas
alme
almeh
almehs
almemar
almemars
almes
almighty
almner
almners
almond
almonds
almoner
almoners
almonry
almost
alms
almsman
almsmen
almuce
almuces
almud
almude
almudes
almuds
almug
almugs
alnico
alnicoes
alodia
alodial
alodium
aloe
aloes
aloetic
aloft
alogical
aloha
alohas
aloin
aloins
alone
along
aloof
aloofly
alopecia
alopecic
aloud
alow
alp
alpaca
alpacas
alpha
alphabet
alphas
alphorn
alphorns
alphosis
alphyl
alphyls
alpine
alpinely
alpines
alpinism
alpinist
alps
already
alright
als
alsike
alsikes
also
alt
altar
altars
alter
alterant
altered
alterer
alterers
altering
alters
althaea
althaeas
althea
altheas
altho
althorn
althorns
although
altitude
alto
altoist
altoists
altos
altruism
altruist
alts
aludel
aludels
alula
alulae
alular
alum
alumin
alumina
aluminas
alumine
alumines
aluminic
alumins
aluminum
alumna
alumnae
alumni
alumnus
alumroot
alums
alunite
alunites
alveolar
alveoli
alveolus
alvine
alway
always
alyssum
alyssums
am
ama
amadavat
amadou
amadous
amah
amahs
amain
amalgam
amalgams
amandine
amanita
amanitas
amanitin
amaranth
amarelle
amaretti
amaretto
amarna
amas
amass
amassed
amasser
amassers
amasses
amassing
amateur
amateurs
amative
amatol
amatols
amatory
amaze
amazed
amazedly
amazes
amazing
amazon
amazons
ambage
ambages
ambari
ambaries
ambaris
ambary
ambeer
ambeers
amber
amberies
amberina
amberoid
ambers
ambery
ambiance
ambience
ambient
ambients
ambit
ambition
ambits
ambivert
amble
ambled
ambler
amblers
ambles
ambling
ambo
amboina
amboinas
ambones
ambos
amboyna
amboynas
ambries
ambroid
ambroids
ambrosia
ambry
ambsace
ambsaces
ambulant
ambulate
ambush
ambushed
ambusher
ambushes
ameba
amebae
ameban
amebas
amebean
amebic
ameboid
ameer
ameerate
ameers
amelcorn
amen
amenable
amenably
amend
amended
amender
amenders
amending
amends
amenity
amens
ament
amentia
amentias
aments
amerce
amerced
amercer
amercers
amerces
amercing
amesace
amesaces
amethyst
ami
amia
amiable
amiably
amiantus
amias
amicable
amicably
amice
amices
amici
amicus
amid
amidase
amidases
amide
amides
amidic
amidin
amidine
amidines
amidins
amido
amidogen
amidol
amidols
amidone
amidones
amids
amidship
amidst
amie
amies
amiga
amigas
amigo
amigos
amin
amine
amines
aminic
aminity
amino
amins
amir
amirate
amirates
amirs
amis
amiss
amities
amitoses
amitosis
amitotic
amitrole
amity
ammeter
ammeters
ammine
ammines
ammino
ammo
ammocete
ammonal
ammonals
ammonia
ammoniac
ammonias
ammonic
ammonify
ammonite
ammonium
ammono
ammonoid
ammos
amnesia
amnesiac
amnesias
amnesic
amnesics
amnestic
amnesty
amnia
amnic
amnion
amnionic
amnions
amniote
amniotes
amniotic
amoeba
amoebae
amoeban
amoebas
amoebean
amoebic
amoeboid
amok
amoks
amole
amoles
among
amongst
amoral
amorally
amoretti
amoretto
amorini
amorino
amorist
amorists
amoroso
amorous
amort
amortise
amortize
amosite
amosites
amotion
amotions
amount
amounted
amounts
amour
amours
amp
amperage
ampere
amperes
amphibia
amphioxi
amphipod
amphora
amphorae
amphoral
amphoras
ample
ampler
amplest
amplexus
amplify
amply
ampoule
ampoules
amps
ampul
ampule
ampules
ampulla
ampullae
ampullar
ampuls
amputate
amputee
amputees
amreeta
amreetas
amrita
amritas
amtrac
amtrack
amtracks
amtracs
amu
amuck
amucks
amulet
amulets
amus
amusable
amuse
amused
amusedly
amuser
amusers
amuses
amusia
amusias
amusing
amusive
amygdala
amygdale
amygdule
amyl
amylase
amylases
amylene
amylenes
amylic
amylogen
amyloid
amyloids
amylose
amyloses
amyls
amylum
amylums
an
ana
anabaena
anabas
anabases
anabasis
anabatic
anableps
anabolic
anaconda
anadem
anadems
anaemia
anaemias
anaemic
anaerobe
anaglyph
anagoge
anagoges
anagogic
anagogy
anagram
anagrams
anal
analcime
analcite
analecta
analects
analemma
analgia
analgias
anality
anally
analog
analogic
analogs
analogue
analogy
analyse
analysed
analyser
analyses
analysis
analyst
analysts
analytic
analyze
analyzed
analyzer
analyzes
ananke
anankes
anapaest
anapest
anapests
anaphase
anaphor
anaphora
anaphors
anarch
anarchic
anarchs
anarchy
anas
anasarca
anatase
anatases
anathema
anatomic
anatomy
anatoxin
anatto
anattos
ancestor
ancestry
anchor
anchored
anchoret
anchors
anchovy
anchusa
anchusas
anchusin
ancient
ancients
ancilla
ancillae
ancillas
ancon
anconal
ancone
anconeal
ancones
anconoid
ancress
and
andante
andantes
andesite
andesyte
andiron
andirons
androgen
android
androids
ands
ane
anear
aneared
anearing
anears
anecdota
anecdote
anechoic
anele
aneled
aneles
aneling
anemia
anemias
anemic
anemone
anemones
anemoses
anemosis
anenst
anent
anergia
anergias
anergic
anergies
anergy
aneroid
aneroids
anes
anestri
anestrus
anethol
anethole
anethols
aneurin
aneurins
aneurism
aneurysm
anew
anga
angakok
angakoks
angaria
angarias
angaries
angary
angas
angel
angeled
angelic
angelica
angeling
angels
angelus
anger
angered
angering
angerly
angers
angina
anginal
anginas
anginose
anginous
angioma
angiomas
angle
angled
anglepod
angler
anglers
angles
anglice
angling
anglings
angora
angoras
angrier
angriest
angrily
angry
angst
angstrom
angsts
anguine
anguish
angular
angulate
angulose
angulous
anhinga
anhingas
ani
anil
anile
anilin
aniline
anilines
anilins
anility
anils
anima
animal
animalic
animally
animals
animas
animate
animated
animater
animates
animato
animator
anime
animes
animi
animis
animism
animisms
animist
animists
animus
animuses
anion
anionic
anions
anis
anise
aniseed
aniseeds
anises
anisette
anisic
anisole
anisoles
ankerite
ankh
ankhs
ankle
ankled
ankles
anklet
anklets
ankling
ankus
ankuses
ankush
ankushes
ankylose
anlace
anlaces
anlage
anlagen
anlages
anlas
anlases
anna
annal
annalist
annals
annas
annates
annatto
annattos
anneal
annealed
annealer
anneals
annelid
annelids
annex
annexe
annexed
annexes
annexing
annotate
announce
annoy
annoyed
annoyer
annoyers
annoying
annoys
annual
annually
annuals
annuity
annul
annular
annulate
annulet
annulets
annuli
annulled
annulose
annuls
annulus
anoa
anoas
anodal
anodally
anode
anodes
anodic
anodize
anodized
anodizes
anodyne
anodynes
anodynic
anoint
anointed
anointer
anoints
anole
anoles
anolyte
anolytes
anomaly
anomic
anomie
anomies
anomy
anon
anonym
anonyms
anoopsia
anopia
anopias
anopsia
anopsias
anorak
anoraks
anoretic
anorexia
anorexic
anorexy
anorthic
anosmia
anosmias
anosmic
another
anovular
anoxemia
anoxemic
anoxia
anoxias
anoxic
ansa
ansae
ansate
ansated
anserine
anserous
answer
answered
answerer
answers
ant
anta
antacid
antacids
antae
antalgic
antas
antbear
antbears
ante
anteater
antecede
anted
antedate
anteed
antefix
antefixa
anteing
antelope
antenna
antennae
antennal
antennas
antepast
anterior
anteroom
antes
antetype
antevert
anthelia
anthelix
anthem
anthemed
anthemia
anthems
anther
antheral
antherid
anthers
antheses
anthesis
anthill
anthills
anthodia
anthoid
anthrax
anti
antiair
antiar
antiarin
antiars
antiatom
antibias
antibody
antiboss
antibug
antic
anticar
anticity
antick
anticked
anticks
anticly
anticold
antics
anticult
antidora
antidote
antidrug
antifat
antiflu
antifoam
antifur
antigay
antigen
antigene
antigens
antigun
antihero
antijam
antiking
antileak
antileft
antilife
antilock
antilog
antilogs
antilogy
antimale
antiman
antimask
antimere
antimony
anting
antings
antinode
antinomy
antinuke
antiphon
antipill
antipode
antipole
antipope
antiporn
antipot
antipyic
antique
antiqued
antiquer
antiques
antirape
antired
antiriot
antirock
antiroll
antirust
antis
antisag
antisera
antisex
antiship
antiskid
antislip
antismog
antismut
antisnob
antistat
antitank
antitax
antitype
antiwar
antiwear
antiweed
antler
antlered
antlers
antlike
antlion
antlions
antonym
antonyms
antonymy
antra
antral
antre
antres
antrorse
antrum
antrums
ants
antsier
antsiest
antsy
anural
anuran
anurans
anureses
anuresis
anuretic
anuria
anurias
anuric
anurous
anus
anuses
anvil
anviled
anviling
anvilled
anvils
anviltop
anxiety
anxious
any
anybody
anyhow
anymore
anyone
anyplace
anything
anytime
anyway
anyways
anywhere
anywise
aorist
aoristic
aorists
aorta
aortae
aortal
aortas
aortic
aoudad
aoudads
apace
apache
apaches
apagoge
apagoges
apagogic
apanage
apanages
aparejo
aparejos
apart
apatetic
apathies
apathy
apatite
apatites
ape
apeak
aped
apeek
apelike
aper
apercu
apercus
aperient
aperies
aperitif
apers
aperture
apery
apes
apetaly
apex
apexes
aphagia
aphagias
aphanite
aphasia
aphasiac
aphasias
aphasic
aphasics
aphelia
aphelian
aphelion
apheses
aphesis
aphetic
aphid
aphides
aphidian
aphids
aphis
apholate
aphonia
aphonias
aphonic
aphonics
aphorise
aphorism
aphorist
aphorize
aphotic
aphtha
aphthae
aphthous
aphylly
apian
apiarian
apiaries
apiarist
apiary
apical
apically
apicals
apices
apiculi
apiculus
apiece
apimania
aping
apiology
apish
apishly
aplasia
aplasias
aplastic
aplenty
aplite
aplites
aplitic
aplomb
aplombs
apnea
apneal
apneas
apneic
apnoea
apnoeal
apnoeas
apnoeic
apoapsis
apocarp
apocarps
apocarpy
apocope
apocopes
apocopic
apocrine
apod
apodal
apodoses
apodosis
apodous
apods
apogamic
apogamy
apogeal
apogean
apogee
apogees
apogeic
apollo
apollos
apolog
apologal
apologia
apologs
apologue
apology
apolune
apolunes
apomict
apomicts
apomixes
apomixis
apophony
apophyge
apoplexy
aport
apospory
apostacy
apostasy
apostate
apostil
apostils
apostle
apostles
apothece
apothegm
apothem
apothems
appal
appall
appalled
appalls
appals
appanage
apparat
apparats
apparel
apparels
apparent
appeal
appealed
appealer
appeals
appear
appeared
appears
appease
appeased
appeaser
appeases
appel
appellee
appellor
appels
append
appended
appendix
appends
appestat
appetent
appetite
applaud
applauds
applause
apple
apples
applied
applier
appliers
applies
applique
apply
applying
appoint
appoints
appose
apposed
apposer
apposers
apposes
apposing
apposite
appraise
apprise
apprised
appriser
apprises
apprize
apprized
apprizer
apprizes
approach
approval
approve
approved
approver
approves
appulse
appulses
apractic
apraxia
apraxias
apraxic
apres
apricot
apricots
apron
aproned
aproning
aprons
apropos
aprotic
apse
apses
apsidal
apsides
apsis
apt
apter
apteral
apteria
apterium
apterous
apteryx
aptest
aptitude
aptly
aptness
apyrase
apyrases
apyretic
aqua
aquacade
aquae
aquanaut
aquaria
aquarial
aquarian
aquarist
aquarium
aquas
aquatic
aquatics
aquatint
aquatone
aquavit
aquavits
aqueduct
aqueous
aquifer
aquifers
aquiline
aquiver
ar
arabesk
arabesks
arabic
arabica
arabicas
arabize
arabized
arabizes
arable
arables
araceous
arachnid
arak
araks
aramid
aramids
araneid
araneids
arapaima
araroba
ararobas
arb
arbalest
arbalist
arbelest
arbiter
arbiters
arbitral
arbor
arboreal
arbored
arbores
arboreta
arborist
arborize
arborous
arbors
arbour
arboured
arbours
arbs
arbuscle
arbute
arbutean
arbutes
arbutus
arc
arcade
arcaded
arcades
arcadia
arcadian
arcadias
arcading
arcana
arcane
arcanum
arcanums
arcature
arced
arch
archaic
archaise
archaism
archaist
archaize
archduke
arched
archer
archers
archery
arches
archil
archils
archine
archines
arching
archings
archival
archive
archived
archives
archly
archness
archon
archons
archway
archways
arciform
arcing
arcked
arcking
arco
arcs
arcsine
arcsines
arctic
arctics
arcuate
arcuated
arcus
arcuses
ardeb
ardebs
ardency
ardent
ardently
ardor
ardors
ardour
ardours
arduous
are
area
areae
areal
areally
areas
areaway
areaways
areca
arecas
areic
arena
arenas
arenite
arenites
arenose
arenous
areola
areolae
areolar
areolas
areolate
areole
areoles
areology
ares
arete
aretes
arethusa
arf
arfs
argal
argala
argalas
argali
argalis
argals
argent
argental
argentic
argents
argentum
argil
argils
arginase
arginine
argle
argled
argles
argling
argol
argols
argon
argonaut
argons
argosies
argosy
argot
argotic
argots
arguable
arguably
argue
argued
arguer
arguers
argues
argufied
argufier
argufies
argufy
arguing
argument
argus
arguses
argyle
argyles
argyll
argylls
arhat
arhats
aria
arias
arid
arider
aridest
aridity
aridly
aridness
ariel
ariels
arietta
ariettas
ariette
ariettes
aright
aril
ariled
arillate
arillode
arilloid
arils
ariose
ariosi
arioso
ariosos
arise
arisen
arises
arising
arista
aristae
aristas
aristate
aristo
aristos
ark
arkose
arkoses
arkosic
arks
arles
arm
armada
armadas
armagnac
armament
armature
armband
armbands
armchair
armed
armer
armers
armet
armets
armful
armfuls
armhole
armholes
armies
armiger
armigero
armigers
armilla
armillae
armillas
arming
armings
armless
armlet
armlets
armlike
armload
armloads
armlock
armlocks
armoire
armoires
armonica
armor
armored
armorer
armorers
armorial
armories
armoring
armors
armory
armour
armoured
armourer
armours
armoury
armpit
armpits
armrest
armrests
arms
armsful
armure
armures
army
armyworm
arnatto
arnattos
arnica
arnicas
arnotto
arnottos
aroid
aroids
aroint
arointed
aroints
aroma
aromas
aromatic
arose
around
arousal
arousals
arouse
aroused
arouser
arousers
arouses
arousing
aroynt
aroynted
aroynts
arpeggio
arpen
arpens
arpent
arpents
arquebus
arrack
arracks
arraign
arraigns
arrange
arranged
arranger
arranges
arrant
arrantly
arras
arrased
array
arrayal
arrayals
arrayed
arrayer
arrayers
arraying
arrays
arrear
arrears
arrest
arrested
arrestee
arrester
arrestor
arrests
arrhizal
arris
arrises
arrival
arrivals
arrive
arrived
arriver
arrivers
arrives
arriving
arroba
arrobas
arrogant
arrogate
arrow
arrowed
arrowing
arrows
arrowy
arroyo
arroyos
ars
arse
arsenal
arsenals
arsenate
arsenic
arsenics
arsenide
arsenite
arseno
arsenous
arses
arshin
arshins
arsine
arsines
arsino
arsis
arson
arsonist
arsonous
arsons
art
artal
artefact
artel
artels
arterial
arteries
artery
artful
artfully
article
articled
articles
artier
artiest
artifact
artifice
artily
artiness
artisan
artisans
artist
artiste
artistes
artistic
artistry
artists
artless
arts
artsier
artsiest
artsy
artwork
artworks
arty
arugola
arugolas
arugula
arugulas
arum
arums
aruspex
arval
arvo
arvos
aryl
aryls
arythmia
arythmic
as
asana
asanas
asarum
asarums
asbestic
asbestos
asbestus
ascarid
ascarids
ascaris
ascend
ascended
ascender
ascends
ascent
ascents
asceses
ascesis
ascetic
ascetics
asci
ascidia
ascidian
ascidium
ascites
ascitic
ascocarp
ascorbic
ascot
ascots
ascribe
ascribed
ascribes
ascus
asdic
asdics
asea
asepses
asepsis
aseptic
asexual
ash
ashamed
ashcan
ashcans
ashed
ashen
ashes
ashfall
ashfalls
ashier
ashiest
ashiness
ashing
ashlar
ashlared
ashlars
ashler
ashlered
ashlers
ashless
ashman
ashmen
ashore
ashplant
ashram
ashrams
ashtray
ashtrays
ashy
aside
asides
asinine
ask
askance
askant
asked
asker
askers
askeses
askesis
askew
asking
askings
askoi
askos
asks
aslant
asleep
aslope
asocial
asp
asparkle
aspect
aspects
aspen
aspens
asper
asperate
asperges
asperity
aspers
asperse
aspersed
asperser
asperses
aspersor
asphalt
asphalts
aspheric
asphodel
asphyxia
asphyxy
aspic
aspics
aspirant
aspirata
aspirate
aspire
aspired
aspirer
aspirers
aspires
aspirin
aspiring
aspirins
aspis
aspises
aspish
asps
asquint
asrama
asramas
ass
assagai
assagais
assai
assail
assailed
assailer
assails
assais
assassin
assault
assaults
assay
assayed
assayer
assayers
assaying
assays
assegai
assegais
assemble
assembly
assent
assented
assenter
assentor
assents
assert
asserted
asserter
assertor
asserts
asses
assess
assessed
assesses
assessor
asset
assets
asshole
assholes
assign
assignat
assigned
assignee
assigner
assignor
assigns
assist
assisted
assister
assistor
assists
assize
assizes
asslike
assoil
assoiled
assoils
assonant
assort
assorted
assorter
assorts
assuage
assuaged
assuages
assume
assumed
assumer
assumers
assumes
assuming
assure
assured
assureds
assurer
assurers
assures
assuring
assuror
assurors
asswage
asswaged
asswages
astasia
astasias
astatic
astatine
aster
asteria
asterias
asterisk
asterism
astern
asternal
asteroid
asters
asthenia
asthenic
astheny
asthma
asthmas
astigmia
astilbe
astilbes
astir
astomous
astonied
astonies
astonish
astony
astound
astounds
astragal
astral
astrally
astrals
astray
astrict
astricts
astride
astringe
astute
astutely
astylar
asunder
aswarm
aswirl
aswoon
asyla
asylum
asylums
asyndeta
at
atabal
atabals
atactic
ataghan
ataghans
atalaya
atalayas
ataman
atamans
atamasco
atap
ataps
ataraxia
ataraxic
ataraxy
atavic
atavism
atavisms
atavist
atavists
ataxia
ataxias
ataxic
ataxics
ataxies
ataxy
ate
atechnic
atelic
atelier
ateliers
atemoya
atemoyas
ates
athanasy
atheism
atheisms
atheist
atheists
atheling
atheneum
atheroma
athetoid
athirst
athlete
athletes
athletic
athodyd
athodyds
athwart
atilt
atingle
atlantes
atlas
atlases
atlatl
atlatls
atma
atman
atmans
atmas
atoll
atolls
atom
atomic
atomical
atomics
atomies
atomise
atomised
atomiser
atomises
atomism
atomisms
atomist
atomists
atomize
atomized
atomizer
atomizes
atoms
atomy
atonable
atonal
atonally
atone
atoned
atoner
atoners
atones
atonic
atonics
atonies
atoning
atony
atop
atopic
atopies
atopy
atrazine
atremble
atresia
atresias
atria
atrial
atrip
atrium
atriums
atrocity
atrophia
atrophic
atrophy
atropin
atropine
atropins
atropism
att
attaboy
attach
attache
attached
attacher
attaches
attack
attacked
attacker
attacks
attain
attained
attainer
attains
attaint
attaints
attar
attars
attemper
attempt
attempts
attend
attended
attendee
attender
attends
attent
attest
attested
attester
attestor
attests
attic
atticism
atticist
attics
attire
attired
attires
attiring
attitude
attorn
attorned
attorney
attorns
attract
attracts
attrite
attrited
attune
attuned
attunes
attuning
atwain
atween
atwitter
atypic
atypical
aubade
aubades
auberge
auberges
aubretia
aubrieta
auburn
auburns
auction
auctions
aucuba
aucubas
audacity
audad
audads
audial
audible
audibles
audibly
audience
audient
audients
audile
audiles
auding
audings
audio
audios
audit
audited
auditing
audition
auditive
auditor
auditors
auditory
audits
augend
augends
auger
augers
aught
aughts
augite
augites
augitic
augment
augments
augur
augural
augured
augurer
augurers
auguries
auguring
augurs
augury
august
auguster
augustly
auk
auklet
auklets
auks
auld
aulder
auldest
aulic
aunt
aunthood
auntie
aunties
auntlier
auntlike
auntly
aunts
aunty
aura
aurae
aural
aurally
aurar
auras
aurate
aurated
aureate
aurei
aureola
aureolae
aureolas
aureole
aureoled
aureoles
aures
aureus
auric
auricle
auricled
auricles
auricula
auriform
auris
aurist
aurists
aurochs
aurora
aurorae
auroral
auroras
aurorean
aurous
aurum
aurums
ausform
ausforms
auspex
auspice
auspices
austere
austerer
austral
australs
ausubo
ausubos
autacoid
autarchy
autarkic
autarky
autecism
auteur
auteurs
author
authored
authors
autism
autisms
autistic
auto
autobahn
autobus
autocade
autocoid
autocrat
autodyne
autoed
autogamy
autogeny
autogiro
autogyro
autoing
autolyse
autolyze
automan
automata
automate
automen
autonomy
autopsic
autopsy
autos
autosome
autotomy
autotype
autotypy
autumn
autumnal
autumns
autunite
auxeses
auxesis
auxetic
auxetics
auxin
auxinic
auxins
ava
avadavat
avail
availed
availing
avails
avant
avarice
avarices
avast
avatar
avatars
avaunt
ave
avellan
avellane
avenge
avenged
avenger
avengers
avenges
avenging
avens
avenses
aventail
avenue
avenues
aver
average
averaged
averages
averment
averred
averring
avers
averse
aversely
aversion
aversive
avert
averted
averting
averts
aves
avgas
avgases
avgasses
avian
avianize
avians
aviaries
aviarist
aviary
aviate
aviated
aviates
aviating
aviation
aviator
aviators
aviatrix
avicular
avid
avidin
avidins
avidity
avidly
avidness
avifauna
avigator
avion
avionic
avionics
avions
aviso
avisos
avo
avocado
avocados
avocet
avocets
avodire
avodires
avoid
avoided
avoider
avoiders
avoiding
avoids
avos
avoset
avosets
avouch
avouched
avoucher
avouches
avow
avowable
avowably
avowal
avowals
avowed
avowedly
avower
avowers
avowing
avows
avulse
avulsed
avulses
avulsing
avulsion
aw
awa
await
awaited
awaiter
awaiters
awaiting
awaits
awake
awaked
awaken
awakened
awakener
awakens
awakes
awaking
award
awarded
awardee
awardees
awarder
awarders
awarding
awards
aware
awash
away
awayness
awe
aweary
aweather
awed
awee
aweigh
aweing
aweless
awes
awesome
awful
awfuller
awfully
awhile
awhirl
awing
awkward
awl
awless
awls
awlwort
awlworts
awmous
awn
awned
awning
awninged
awnings
awnless
awns
awny
awoke
awoken
awol
awols
awry
ax
axal
axe
axed
axel
axels
axeman
axemen
axenic
axes
axial
axiality
axially
axil
axile
axilla
axillae
axillar
axillars
axillary
axillas
axils
axing
axiology
axiom
axioms
axion
axions
axis
axised
axises
axite
axites
axle
axled
axles
axletree
axlike
axman
axmen
axolotl
axolotls
axon
axonal
axone
axonemal
axoneme
axonemes
axones
axonic
axons
axoplasm
axseed
axseeds
ay
ayah
ayahs
aye
ayes
ayin
ayins
ays
ayurveda
azalea
azaleas
azan
azans
azide
azides
azido
azimuth
azimuths
azine
azines
azlon
azlons
azo
azoic
azole
azoles
azon
azonal
azonic
azons
azote
azoted
azotemia
azotemic
azotes
azoth
azoths
azotic
azotise
azotised
azotises
azotize
azotized
azotizes
azoturia
azure
azures
azurite
azurites
azygos
azygoses
azygous
ba
baa
baaed
baaing
baal
baalim
baalism
baalisms
baals
baas
baases
baaskaap
baba
babas
babassu
babassus
babbitt
babbitts
babble
babbled
babbler
babblers
babbles
babbling
babe
babel
babels
babes
babesia
babesias
babiche
babiches
babied
babies
babirusa
babka
babkas
baboo
babool
babools
baboon
baboons
baboos
babu
babul
babuls
babus
babushka
baby
babyhood
babying
babyish
bacalao
bacalaos
bacca
baccae
baccara
baccaras
baccarat
baccate
baccated
bacchant
bacchic
bacchii
bacchius
bach
bached
bachelor
baches
baching
bacillar
bacilli
bacillus
back
backache
backbeat
backbend
backbit
backbite
backbone
backcast
backchat
backdate
backdoor
backdrop
backed
backer
backers
backfill
backfire
backfit
backfits
backflow
backhand
backhaul
backhoe
backhoes
backing
backings
backland
backlash
backless
backlist
backlit
backlog
backlogs
backmost
backout
backouts
backpack
backrest
backroom
backrush
backs
backsaw
backsaws
backseat
backset
backsets
backside
backslap
backslid
backspin
backstab
backstay
backstop
backup
backups
backward
backwash
backwood
backwrap
backyard
bacon
bacons
bacteria
bacterin
bacula
baculine
baculum
baculums
bad
badass
badassed
badasses
badder
baddest
baddie
baddies
baddy
bade
badge
badged
badger
badgered
badgerly
badgers
badges
badging
badinage
badland
badlands
badly
badman
badmen
badmouth
badness
bads
baff
baffed
baffies
baffing
baffle
baffled
baffler
bafflers
baffles
baffling
baffs
baffy
bag
bagass
bagasse
bagasses
bagel
bagels
bagful
bagfuls
baggage
baggages
bagged
bagger
baggers
baggie
baggier
baggies
baggiest
baggily
bagging
baggings
baggy
baghouse
bagman
bagmen
bagnio
bagnios
bagpipe
bagpiper
bagpipes
bags
bagsful
baguet
baguets
baguette
bagwig
bagwigs
bagworm
bagworms
bah
bahadur
bahadurs
baht
bahts
baidarka
bail
bailable
bailed
bailee
bailees
bailer
bailers
bailey
baileys
bailie
bailies
bailiff
bailiffs
bailing
bailment
bailor
bailors
bailout
bailouts
bails
bailsman
bailsmen
bairn
bairnish
bairnly
bairns
bait
baited
baiter
baiters
baith
baiting
baits
baiza
baizas
baize
baizes
bake
baked
bakemeat
baker
bakeries
bakers
bakery
bakes
bakeshop
baking
bakings
baklava
baklavas
baklawa
baklawas
bakshish
bal
balance
balanced
balancer
balances
balas
balases
balata
balatas
balboa
balboas
balcony
bald
balded
balder
baldest
baldhead
baldies
balding
baldish
baldly
baldness
baldpate
baldric
baldrick
baldrics
balds
baldy
bale
baled
baleen
baleens
balefire
baleful
baler
balers
bales
baling
balisaur
balk
balked
balker
balkers
balkier
balkiest
balkily
balking
balkline
balks
balky
ball
ballad
ballade
ballades
balladic
balladry
ballads
ballast
ballasts
balled
baller
ballers
ballet
balletic
ballets
ballgame
ballhawk
ballies
balling
ballista
ballon
ballonet
ballonne
ballons
balloon
balloons
ballot
balloted
balloter
ballots
ballpark
ballroom
balls
ballsier
ballsy
ballute
ballutes
bally
ballyhoo
ballyrag
balm
balmier
balmiest
balmily
balmlike
balmoral
balms
balmy
balneal
baloney
baloneys
bals
balsa
balsam
balsamed
balsamic
balsams
balsas
baluster
bam
bambini
bambino
bambinos
bamboo
bamboos
bammed
bamming
bams
ban
banal
banality
banalize
banally
banana
bananas
banausic
banco
bancos
band
bandage
bandaged
bandager
bandages
bandana
bandanas
bandanna
bandbox
bandeau
bandeaus
bandeaux
banded
bander
banderol
banders
bandied
bandies
banding
bandit
banditry
bandits
banditti
bandog
bandogs
bandora
bandoras
bandore
bandores
bands
bandsman
bandsmen
bandy
bandying
bane
baned
baneful
banes
bang
banged
banger
bangers
banging
bangkok
bangkoks
bangle
bangles
bangs
bangtail
bani
banian
banians
baning
banish
banished
banisher
banishes
banister
banjax
banjaxed
banjaxes
banjo
banjoes
banjoist
banjos
bank
bankable
bankbook
bankcard
banked
banker
bankerly
bankers
banking
bankings
banknote
bankroll
bankrupt
banks
banksia
banksias
bankside
banned
banner
bannered
banneret
bannerol
banners
bannet
bannets
banning
bannock
bannocks
banns
banquet
banquets
bans
banshee
banshees
banshie
banshies
bantam
bantams
banteng
bantengs
banter
bantered
banterer
banters
banties
bantling
banty
banyan
banyans
banzai
banzais
baobab
baobabs
bap
baps
baptise
baptised
baptises
baptisia
baptism
baptisms
baptist
baptists
baptize
baptized
baptizer
baptizes
bar
barathea
barb
barbal
barbaric
barbasco
barbate
barbe
barbecue
barbed
barbel
barbell
barbells
barbels
barbeque
barber
barbered
barberry
barbers
barbes
barbet
barbets
barbette
barbican
barbicel
barbing
barbital
barbless
barbs
barbule
barbules
barbut
barbuts
barbwire
barchan
barchans
bard
barde
barded
bardes
bardic
barding
bards
bare
bareback
bareboat
bared
barefit
barefoot
barege
bareges
barehead
barely
bareness
barer
bares
baresark
barest
barf
barfed
barfing
barflies
barfly
barfs
bargain
bargains
barge
barged
bargee
bargees
bargello
bargeman
bargemen
barges
barghest
barging
barguest
barhop
barhops
baric
barilla
barillas
baring
barite
barites
baritone
barium
bariums
bark
barked
barkeep
barkeeps
barker
barkers
barkier
barkiest
barking
barkless
barks
barky
barleduc
barless
barley
barleys
barlow
barlows
barm
barmaid
barmaids
barman
barmen
barmie
barmier
barmiest
barms
barmy
barn
barnacle
barnier
barniest
barnlike
barns
barny
barnyard
barogram
baron
baronage
baroness
baronet
baronets
barong
barongs
baronial
baronies
baronne
baronnes
barons
barony
baroque
baroques
barouche
barque
barques
barrable
barrack
barracks
barrage
barraged
barrages
barranca
barranco
barrater
barrator
barratry
barre
barred
barrel
barreled
barrels
barren
barrener
barrenly
barrens
barres
barret
barretor
barretry
barrets
barrette
barrier
barriers
barring
barrio
barrios
barroom
barrooms
barrow
barrows
bars
barstool
bartend
bartends
barter
bartered
barterer
barters
bartisan
bartizan
barware
barwares
barye
baryes
baryon
baryonic
baryons
baryta
barytas
baryte
barytes
barytic
barytone
bas
basal
basally
basalt
basaltes
basaltic
basalts
bascule
bascules
base
baseball
baseborn
based
baseless
baseline
basely
baseman
basemen
basement
baseness
basenji
basenjis
baser
bases
basest
bash
bashaw
bashaws
bashed
basher
bashers
bashes
bashful
bashing
bashlyk
bashlyks
basic
basicity
basics
basidia
basidial
basidium
basified
basifier
basifies
basify
basil
basilar
basilary
basilic
basilica
basilisk
basils
basin
basinal
basined
basinet
basinets
basinful
basing
basins
basion
basions
basis
bask
basked
basket
basketry
baskets
basking
basks
basmati
basmatis
basophil
basque
basques
bass
basses
basset
basseted
bassets
bassett
bassetts
bassi
bassinet
bassist
bassists
bassly
bassness
basso
bassoon
bassoons
bassos
basswood
bassy
bast
bastard
bastards
bastardy
baste
basted
baster
basters
bastes
bastile
bastiles
bastille
basting
bastings
bastion
bastions
basts
bat
batboy
batboys
batch
batched
batcher
batchers
batches
batching
bate
bateau
bateaux
bated
bates
batfish
batfowl
batfowls
bath
bathe
bathed
bather
bathers
bathes
bathetic
bathing
bathless
bathmat
bathmats
bathos
bathoses
bathrobe
bathroom
baths
bathtub
bathtubs
bathyal
batik
batiks
bating
batiste
batistes
batlike
batman
batmen
baton
batons
bats
batsman
batsmen
batt
battalia
batteau
batteaux
batted
batten
battened
battener
battens
batter
battered
batterie
batters
battery
battier
battiest
battik
battiks
batting
battings
battle
battled
battler
battlers
battles
battling
batts
battu
battue
battues
batty
batwing
baubee
baubees
bauble
baubles
baud
baudekin
baudrons
bauds
bauhinia
baulk
baulked
baulkier
baulking
baulks
baulky
bausond
bauxite
bauxites
bauxitic
bawbee
bawbees
bawcock
bawcocks
bawd
bawdier
bawdies
bawdiest
bawdily
bawdric
bawdrics
bawdries
bawdry
bawds
bawdy
bawl
bawled
bawler
bawlers
bawling
bawls
bawsunt
bawtie
bawties
bawty
bay
bayadeer
bayadere
bayamo
bayamos
bayard
bayards
bayberry
bayed
baying
bayman
baymen
bayonet
bayonets
bayou
bayous
bays
baywood
baywoods
bazaar
bazaars
bazar
bazars
bazoo
bazooka
bazookas
bazooms
bazoos
bdellium
be
beach
beachboy
beached
beaches
beachier
beaching
beachy
beacon
beaconed
beacons
bead
beaded
beadier
beadiest
beadily
beading
beadings
beadle
beadles
beadlike
beadman
beadmen
beadroll
beads
beadsman
beadsmen
beadwork
beady
beagle
beagles
beak
beaked
beaker
beakers
beakier
beakiest
beakless
beaklike
beaks
beaky
beam
beamed
beamier
beamiest
beamily
beaming
beamish
beamless
beamlike
beams
beamy
bean
beanbag
beanbags
beanball
beaned
beanery
beanie
beanies
beaning
beanlike
beano
beanos
beanpole
beans
bear
bearable
bearably
bearcat
bearcats
beard
bearded
bearding
beards
bearer
bearers
bearhug
bearhugs
bearing
bearings
bearish
bearlike
bears
bearskin
bearwood
beast
beastie
beasties
beastly
beasts
beat
beatable
beaten
beater
beaters
beatific
beatify
beating
beatings
beatless
beatnik
beatniks
beats
beau
beaucoup
beauish
beaus
beaut
beauties
beautify
beauts
beauty
beaux
beaver
beavered
beavers
bebeeru
bebeerus
beblood
bebloods
bebop
bebopper
bebops
becalm
becalmed
becalms
became
becap
becapped
becaps
becarpet
because
bechalk
bechalks
bechamel
bechance
becharm
becharms
beck
becked
becket
beckets
becking
beckon
beckoned
beckoner
beckons
becks
beclamor
beclasp
beclasps
becloak
becloaks
beclog
beclogs
beclothe
becloud
beclouds
beclown
beclowns
become
becomes
becoming
becoward
becrawl
becrawls
becrime
becrimed
becrimes
becrowd
becrowds
becrust
becrusts
becudgel
becurse
becursed
becurses
becurst
bed
bedabble
bedamn
bedamned
bedamns
bedarken
bedaub
bedaubed
bedaubs
bedazzle
bedbug
bedbugs
bedchair
bedcover
beddable
bedded
bedder
bedders
bedding
beddings
bedeafen
bedeck
bedecked
bedecks
bedel
bedell
bedells
bedels
bedeman
bedemen
bedesman
bedesmen
bedevil
bedevils
bedew
bedewed
bedewing
bedews
bedfast
bedframe
bedgown
bedgowns
bediaper
bedight
bedights
bedim
bedimmed
bedimple
bedims
bedirty
bedizen
bedizens
bedlam
bedlamp
bedlamps
bedlams
bedless
bedlike
bedmaker
bedmate
bedmates
bedotted
bedouin
bedouins
bedpan
bedpans
bedplate
bedpost
bedposts
bedquilt
bedrail
bedrails
bedrape
bedraped
bedrapes
bedrench
bedrid
bedrivel
bedrock
bedrocks
bedroll
bedrolls
bedroom
bedrooms
bedrug
bedrugs
beds
bedsheet
bedside
bedsides
bedsit
bedsits
bedsonia
bedsore
bedsores
bedstand
bedstead
bedstraw
bedtick
bedticks
bedtime
bedtimes
bedu
beduin
beduins
bedumb
bedumbed
bedumbs
bedunce
bedunced
bedunces
bedward
bedwards
bedwarf
bedwarfs
bee
beebee
beebees
beebread
beech
beechen
beeches
beechier
beechnut
beechy
beef
beefalo
beefalos
beefcake
beefed
beefier
beefiest
beefily
beefing
beefless
beefs
beefwood
beefy
beehive
beehives
beelike
beeline
beelined
beelines
been
beep
beeped
beeper
beepers
beeping
beeps
beer
beerier
beeriest
beers
beery
bees
beeswax
beeswing
beet
beetle
beetled
beetler
beetlers
beetles
beetling
beetroot
beets
beeves
beeyard
beeyards
beezer
beezers
befall
befallen
befalls
befell
befinger
befit
befits
befitted
beflag
beflags
beflea
befleaed
befleas
befleck
beflecks
beflower
befog
befogged
befogs
befool
befooled
befools
before
befoul
befouled
befouler
befouls
befret
befrets
befriend
befringe
befuddle
beg
begall
begalled
begalls
began
begat
begaze
begazed
begazes
begazing
beget
begets
begetter
beggar
beggared
beggarly
beggars
beggary
begged
begging
begin
beginner
begins
begird
begirded
begirdle
begirds
begirt
beglad
beglads
beglamor
begloom
beglooms
begone
begonia
begonias
begorah
begorra
begorrah
begot
begotten
begrim
begrime
begrimed
begrimes
begrims
begroan
begroans
begrudge
begs
beguile
beguiled
beguiler
beguiles
beguine
beguines
begulf
begulfed
begulfs
begum
begums
begun
behalf
behalves
behave
behaved
behaver
behavers
behaves
behaving
behavior
behead
beheaded
beheads
beheld
behemoth
behest
behests
behind
behinds
behold
beholden
beholder
beholds
behoof
behoove
behooved
behooves
behove
behoved
behoves
behoving
behowl
behowled
behowls
beige
beiges
beignet
beignets
beigy
being
beings
bejabers
bejeezus
bejesus
bejewel
bejewels
bejumble
bekiss
bekissed
bekisses
beknight
beknot
beknots
bel
belabor
belabors
belabour
belaced
beladied
beladies
belady
belated
belaud
belauded
belauds
belay
belayed
belaying
belays
belch
belched
belcher
belchers
belches
belching
beldam
beldame
beldames
beldams
beleap
beleaped
beleaps
beleapt
belfried
belfries
belfry
belga
belgas
belie
belied
belief
beliefs
belier
beliers
belies
believe
believed
believer
believes
belike
beliquor
belittle
belive
bell
bellbird
bellboy
bellboys
belle
belled
belleek
belleeks
belles
bellhop
bellhops
bellied
bellies
belling
bellman
bellmen
bellow
bellowed
bellower
bellows
bellpull
bells
bellwort
belly
bellyful
bellying
belong
belonged
belongs
beloved
beloveds
below
belows
bels
belt
belted
belter
belters
belting
beltings
beltless
beltline
belts
beltway
beltways
beluga
belugas
belying
bema
bemadam
bemadams
bemadden
bemas
bemata
bemean
bemeaned
bemeans
bemingle
bemire
bemired
bemires
bemiring
bemist
bemisted
bemists
bemix
bemixed
bemixes
bemixing
bemixt
bemoan
bemoaned
bemoans
bemock
bemocked
bemocks
bemuddle
bemurmur
bemuse
bemused
bemuses
bemusing
bemuzzle
ben
bename
benamed
benames
benaming
bench
benched
bencher
benchers
benches
benching
bend
bendable
benday
bendayed
bendays
bended
bendee
bendees
bender
benders
bending
bends
bendways
bendwise
bendy
bendys
bene
beneath
benedick
benedict
benefic
benefice
benefit
benefits
benempt
benes
benign
benignly
benison
benisons
benjamin
benne
bennes
bennet
bennets
benni
bennies
bennis
benny
benomyl
benomyls
bens
bent
benthal
benthic
benthos
bents
bentwood
benumb
benumbed
benumbs
benzal
benzene
benzenes
benzidin
benzin
benzine
benzines
benzins
benzoate
benzoic
benzoin
benzoins
benzol
benzole
benzoles
benzols
benzoyl
benzoyls
benzyl
benzylic
benzyls
bepaint
bepaints
bepimple
bequeath
bequest
bequests
berake
beraked
berakes
beraking
berascal
berate
berated
berates
berating
berberin
berberis
berceuse
berdache
bereave
bereaved
bereaver
bereaves
bereft
beret
berets
beretta
berettas
berg
bergamot
bergere
bergeres
bergs
berhyme
berhymed
berhymes
beriberi
berime
berimed
berimes
beriming
beringed
berlin
berline
berlines
berlins
berm
berme
bermes
berms
bermudas
bernicle
berobed
berouged
berretta
berried
berries
berry
berrying
berseem
berseems
berserk
berserks
berth
bertha
berthas
berthed
berthing
berths
beryl
beryline
beryls
bescorch
bescour
bescours
bescreen
beseech
beseem
beseemed
beseems
beset
besets
besetter
beshadow
beshame
beshamed
beshames
beshiver
beshout
beshouts
beshrew
beshrews
beshroud
beside
besides
besiege
besieged
besieger
besieges
beslaved
beslime
beslimed
beslimes
besmear
besmears
besmile
besmiled
besmiles
besmirch
besmoke
besmoked
besmokes
besmooth
besmudge
besmut
besmuts
besnow
besnowed
besnows
besom
besoms
besoothe
besot
besots
besotted
besought
bespake
bespeak
bespeaks
bespoke
bespoken
bespouse
bespread
besprent
best
bestead
besteads
bested
bestial
bestiary
besting
bestir
bestirs
bestow
bestowal
bestowed
bestows
bestrew
bestrewn
bestrews
bestrid
bestride
bestrode
bestrow
bestrown
bestrows
bests
bestud
bestuds
beswarm
beswarms
bet
beta
betaine
betaines
betake
betaken
betakes
betaking
betas
betatron
betatter
betaxed
betel
betelnut
betels
beth
bethank
bethanks
bethel
bethels
bethesda
bethink
bethinks
bethorn
bethorns
beths
bethump
bethumps
betide
betided
betides
betiding
betime
betimes
betise
betises
betoken
betokens
beton
betonies
betons
betony
betook
betray
betrayal
betrayed
betrayer
betrays
betroth
betroths
bets
betta
bettas
betted
better
bettered
betters
betting
bettor
bettors
between
betwixt
beuncled
bevatron
bevel
beveled
beveler
bevelers
beveling
bevelled
beveller
bevels
beverage
bevies
bevomit
bevomits
bevor
bevors
bevy
bewail
bewailed
bewailer
bewails
beware
bewared
bewares
bewaring
beweary
beweep
beweeps
bewept
bewig
bewigged
bewigs
bewilder
bewinged
bewitch
beworm
bewormed
beworms
beworry
bewrap
bewraps
bewrapt
bewray
bewrayed
bewrayer
bewrays
bey
beylic
beylics
beylik
beyliks
beyond
beyonds
beys
bezant
bezants
bezazz
bezazzes
bezel
bezels
bezil
bezils
bezique
beziques
bezoar
bezoars
bezzant
bezzants
bhakta
bhaktas
bhakti
bhaktis
bhang
bhangs
bharal
bharals
bheestie
bheesty
bhistie
bhisties
bhoot
bhoots
bhut
bhuts
bi
biacetyl
biali
bialis
bialy
bialys
biannual
bias
biased
biasedly
biases
biasing
biasness
biassed
biasses
biassing
biathlon
biaxal
biaxial
bib
bibasic
bibb
bibbed
bibber
bibbers
bibbery
bibbing
bibbs
bibcock
bibcocks
bibelot
bibelots
bible
bibles
bibless
biblical
biblike
biblist
biblists
bibs
bibulous
bicarb
bicarbs
bicaudal
bice
biceps
bicepses
bices
bichrome
bicker
bickered
bickerer
bickers
bicolor
bicolors
bicolour
biconvex
bicorn
bicorne
bicornes
bicron
bicrons
bicuspid
bicycle
bicycled
bicycler
bicycles
bicyclic
bid
bidarka
bidarkas
bidarkee
biddable
biddably
bidden
bidder
bidders
biddies
bidding
biddings
biddy
bide
bided
bidental
bider
biders
bides
bidet
bidets
biding
bids
bield
bielded
bielding
bields
biennale
biennia
biennial
biennium
bier
biers
biface
bifaces
bifacial
biff
biffed
biffies
biffin
biffing
biffins
biffs
biffy
bifid
bifidity
bifidly
bifilar
biflex
bifocal
bifocals
bifold
biforate
biforked
biform
biformed
big
bigamies
bigamist
bigamous
bigamy
bigarade
bigaroon
bigeminy
bigeye
bigeyes
bigfeet
bigfoot
bigfoots
bigger
biggest
biggety
biggie
biggies
biggin
bigging
biggings
biggins
biggish
biggity
bighead
bigheads
bighorn
bighorns
bight
bighted
bighting
bights
bigly
bigmouth
bigness
bignonia
bigot
bigoted
bigotry
bigots
bigs
bigwig
bigwigs
bihourly
bijou
bijous
bijoux
bijugate
bijugous
bike
biked
biker
bikers
bikes
bikeway
bikeways
bikie
bikies
biking
bikini
bikinied
bikinis
bilabial
bilander
bilayer
bilayers
bilberry
bilbo
bilboa
bilboas
bilboes
bilbos
bile
biles
bilge
bilged
bilges
bilgier
bilgiest
bilging
bilgy
biliary
bilinear
bilious
bilk
bilked
bilker
bilkers
bilking
bilks
bill
billable
billbug
billbugs
billed
biller
billers
billet
billeted
billeter
billets
billfish
billfold
billhead
billhook
billiard
billie
billies
billing
billings
billion
billions
billon
billons
billow
billowed
billows
billowy
bills
billy
billycan
bilobate
bilobed
bilsted
bilsteds
biltong
biltongs
bima
bimah
bimahs
bimanous
bimanual
bimas
bimbo
bimboes
bimbos
bimensal
bimester
bimetal
bimetals
bimethyl
bimodal
bimorph
bimorphs
bin
binal
binaries
binary
binate
binately
binaural
bind
bindable
binder
binders
bindery
bindi
binding
bindings
bindis
bindle
bindles
binds
bindweed
bine
bines
binge
binged
bingeing
binger
bingers
binges
binging
bingo
bingos
binit
binits
binnacle
binned
binning
binocle
binocles
binocs
binomial
bins
bint
bints
bio
bioassay
biochip
biochips
biocidal
biocide
biocides
bioclean
biocycle
bioethic
biogas
biogases
biogen
biogenic
biogens
biogeny
bioherm
bioherms
biologic
biology
biolyses
biolysis
biolytic
biomass
biome
biomes
biometry
bionic
bionics
bionomic
bionomy
biont
biontic
bionts
biopic
biopics
bioplasm
biopsic
biopsied
biopsies
biopsy
bioptic
bios
bioscope
bioscopy
biota
biotas
biotech
biotechs
biotic
biotical
biotics
biotin
biotins
biotite
biotites
biotitic
biotope
biotopes
biotoxin
biotron
biotrons
biotype
biotypes
biotypic
biovular
bipack
bipacks
biparous
biparted
biparty
biped
bipedal
bipeds
biphasic
biphenyl
biplane
biplanes
bipod
bipods
bipolar
biracial
biradial
biramose
biramous
birch
birched
birchen
birches
birching
bird
birdbath
birdcage
birdcall
birded
birder
birders
birdfarm
birdie
birdied
birdies
birding
birdings
birdlike
birdlime
birdman
birdmen
birds
birdseed
birdseye
birdshot
birdsong
bireme
biremes
biretta
birettas
birk
birkie
birkies
birks
birl
birle
birled
birler
birlers
birles
birling
birlings
birls
birr
birred
birretta
birring
birrotch
birrs
birse
birses
birth
birthday
birthed
birthing
births
bis
biscuit
biscuits
bise
bisect
bisected
bisector
bisects
bises
bisexual
bishop
bishoped
bishops
bisk
bisks
bismuth
bismuths
bisnaga
bisnagas
bison
bisons
bisque
bisques
bistate
bister
bistered
bisters
bistort
bistorts
bistoury
bistre
bistred
bistres
bistro
bistroic
bistros
bit
bitable
bitch
bitched
bitchery
bitches
bitchier
bitchily
bitching
bitchy
bite
biteable
biter
biters
bites
bitewing
biting
bitingly
bits
bitstock
bitsy
bitt
bitted
bitten
bitter
bittered
bitterer
bitterly
bittern
bitterns
bitters
bittier
bittiest
bitting
bittings
bittock
bittocks
bitts
bitty
bitumen
bitumens
biunique
bivalent
bivalve
bivalved
bivalves
bivinyl
bivinyls
bivouac
bivouacs
biweekly
biyearly
biz
bizarre
bizarres
bize
bizes
biznaga
biznagas
bizonal
bizone
bizones
bizzes
blab
blabbed
blabber
blabbers
blabbing
blabby
blabs
black
blackboy
blackcap
blacked
blacken
blackens
blacker
blackest
blackfin
blackfly
blackgum
blacking
blackish
blackleg
blackly
blackout
blacks
blacktop
bladder
bladders
bladdery
blade
bladed
blades
blae
blah
blahs
blain
blains
blam
blamable
blamably
blame
blamed
blameful
blamer
blamers
blames
blaming
blams
blanch
blanched
blancher
blanches
bland
blander
blandest
blandish
blandly
blank
blanked
blanker
blankest
blanket
blankets
blanking
blankly
blanks
blare
blared
blares
blaring
blarney
blarneys
blase
blast
blasted
blastema
blaster
blasters
blastie
blastier
blasties
blasting
blastoff
blastoma
blasts
blastula
blasty
blat
blatancy
blatant
blate
blather
blathers
blats
blatted
blatter
blatters
blatting
blaubok
blauboks
blaw
blawed
blawing
blawn
blaws
blaze
blazed
blazer
blazers
blazes
blazing
blazon
blazoned
blazoner
blazonry
blazons
bleach
bleached
bleacher
bleaches
bleak
bleaker
bleakest
bleakish
bleakly
bleaks
blear
bleared
blearier
blearily
blearing
blears
bleary
bleat
bleated
bleater
bleaters
bleating
bleats
bleb
blebby
blebs
bled
bleed
bleeder
bleeders
bleeding
bleeds
bleep
bleeped
bleeping
bleeps
blellum
blellums
blemish
blench
blenched
blencher
blenches
blend
blende
blended
blender
blenders
blendes
blending
blends
blennies
blenny
blent
blesbok
blesboks
blesbuck
bless
blessed
blesser
blessers
blesses
blessing
blest
blet
blether
blethers
blets
blew
blight
blighted
blighter
blights
blighty
blimey
blimp
blimpish
blimps
blimy
blin
blind
blindage
blinded
blinder
blinders
blindest
blinding
blindly
blinds
blini
blinis
blink
blinkard
blinked
blinker
blinkers
blinking
blinks
blintz
blintze
blintzes
blip
blipped
blipping
blips
bliss
blissed
blisses
blissful
blissing
blister
blisters
blistery
blite
blites
blithe
blithely
blither
blithers
blithest
blitz
blitzed
blitzes
blitzing
blizzard
bloat
bloated
bloater
bloaters
bloating
bloats
blob
blobbed
blobbing
blobs
bloc
block
blockade
blockage
blocked
blocker
blockers
blockier
blocking
blockish
blocks
blocky
blocs
bloke
blokes
blond
blonde
blonder
blondes
blondest
blondish
blonds
blood
blooded
bloodfin
bloodied
bloodier
bloodies
bloodily
blooding
bloodred
bloods
bloody
blooey
blooie
bloom
bloomed
bloomer
bloomers
bloomery
bloomier
blooming
blooms
bloomy
bloop
blooped
blooper
bloopers
blooping
bloops
blossom
blossoms
blossomy
blot
blotch
blotched
blotches
blotchy
blotless
blots
blotted
blotter
blotters
blottier
blotting
blotto
blotty
blouse
bloused
blouses
blousier
blousily
blousing
blouson
blousons
blousy
bloviate
blow
blowback
blowball
blowby
blowbys
blowdown
blowed
blower
blowers
blowfish
blowfly
blowgun
blowguns
blowhard
blowhole
blowier
blowiest
blowing
blowjob
blowjobs
blown
blowoff
blowoffs
blowout
blowouts
blowpipe
blows
blowsed
blowsier
blowsily
blowsy
blowtube
blowup
blowups
blowy
blowzed
blowzier
blowzily
blowzy
blub
blubbed
blubber
blubbers
blubbery
blubbing
blubs
blucher
bluchers
bludgeon
bludger
bludgers
blue
blueball
bluebell
bluebill
bluebird
bluebook
bluecap
bluecaps
bluecoat
blued
bluefin
bluefins
bluefish
bluegill
bluegum
bluegums
bluehead
blueing
blueings
blueish
bluejack
bluejay
bluejays
blueline
bluely
blueness
bluenose
bluer
blues
bluesier
bluesman
bluesmen
bluest
bluestem
bluesy
bluet
bluetick
bluets
blueweed
bluewood
bluey
blueys
bluff
bluffed
bluffer
bluffers
bluffest
bluffing
bluffly
bluffs
bluing
bluings
bluish
blume
blumed
blumes
bluming
blunder
blunders
blunge
blunged
blunger
blungers
blunges
blunging
blunt
blunted
blunter
bluntest
blunting
bluntly
blunts
blur
blurb
blurbed
blurbing
blurbs
blurred
blurrier
blurrily
blurring
blurry
blurs
blurt
blurted
blurter
blurters
blurting
blurts
blush
blushed
blusher
blushers
blushes
blushful
blushing
bluster
blusters
blustery
blype
blypes
bo
boa
boar
board
boarded
boarder
boarders
boarding
boardman
boardmen
boards
boarfish
boarish
boars
boart
boarts
boas
boast
boasted
boaster
boasters
boastful
boasting
boasts
boat
boatable
boatbill
boated
boatel
boatels
boater
boaters
boatful
boatfuls
boathook
boating
boatings
boatlike
boatload
boatman
boatmen
boats
boatsman
boatsmen
boatyard
bob
bobbed
bobber
bobbers
bobbery
bobbies
bobbin
bobbinet
bobbing
bobbins
bobble
bobbled
bobbles
bobbling
bobby
bobcat
bobcats
bobeche
bobeches
bobolink
bobs
bobsled
bobsleds
bobstay
bobstays
bobtail
bobtails
bobwhite
bocaccio
bocce
bocces
bocci
boccia
boccias
boccie
boccies
boccis
boche
boches
bock
bocks
bod
bode
boded
bodega
bodegas
bodement
bodes
bodhran
bodhrans
bodice
bodices
bodied
bodies
bodiless
bodily
boding
bodingly
bodings
bodkin
bodkins
bods
body
bodying
bodysuit
bodysurf
bodywork
boehmite
boff
boffin
boffins
boffo
boffola
boffolas
boffos
boffs
bog
bogan
bogans
bogbean
bogbeans
bogey
bogeyed
bogeying
bogeyman
bogeymen
bogeys
bogged
boggier
boggiest
bogging
boggish
boggle
boggled
boggler
bogglers
boggles
boggling
boggy
bogie
bogies
bogle
bogles
bogs
bogus
bogwood
bogwoods
bogy
bogyism
bogyisms
bogyman
bogymen
bohea
boheas
bohemia
bohemian
bohemias
bohunk
bohunks
boil
boilable
boiled
boiler
boilers
boiling
boiloff
boiloffs
boils
boing
boiserie
boite
boites
bola
bolar
bolas
bolases
bold
bolder
boldest
boldface
boldly
boldness
bolds
bole
bolero
boleros
boles
bolete
boletes
boleti
boletus
bolide
bolides
bolivar
bolivars
bolivia
bolivias
boll
bollard
bollards
bolled
bolling
bollix
bollixed
bollixes
bollocks
bollox
bolloxed
bolloxes
bolls
bollworm
bolo
bologna
bolognas
boloney
boloneys
bolos
bolshie
bolshies
bolshy
bolson
bolsons
bolster
bolsters
bolt
bolted
bolter
bolters
bolthead
bolthole
bolting
boltonia
boltrope
bolts
bolus
boluses
bomb
bombard
bombards
bombast
bombasts
bombax
bombe
bombed
bomber
bombers
bombes
bombesin
bombing
bombings
bombload
bombs
bombycid
bombyx
bombyxes
bonaci
bonacis
bonanza
bonanzas
bonbon
bonbons
bond
bondable
bondage
bondages
bonded
bonder
bonders
bonding
bondings
bondmaid
bondman
bondmen
bonds
bondsman
bondsmen
bonduc
bonducs
bone
boned
bonefish
bonehead
boneless
bonemeal
boner
boners
bones
boneset
bonesets
boney
boneyard
bonfire
bonfires
bong
bonged
bonging
bongo
bongoes
bongoist
bongos
bongs
bonhomie
bonier
boniest
boniface
boniness
boning
bonita
bonitas
bonito
bonitoes
bonitos
bonk
bonked
bonkers
bonking
bonks
bonne
bonnes
bonnet
bonneted
bonnets
bonnie
bonnier
bonniest
bonnily
bonnock
bonnocks
bonny
bonsai
bonspell
bonspiel
bontebok
bonus
bonuses
bony
bonze
bonzer
bonzes
boo
boob
boobed
boobie
boobies
boobing
boobish
booboo
booboos
boobs
booby
boodle
boodled
boodler
boodlers
boodles
boodling
booed
booger
boogers
boogey
boogeyed
boogeys
boogie
boogied
boogies
boogy
boogying
boogyman
boogymen
boohoo
boohooed
boohoos
booing
book
bookable
bookcase
booked
bookend
bookends
booker
bookers
bookful
bookfuls
bookie
bookies
booking
bookings
bookish
booklet
booklets
booklice
booklore
bookman
bookmark
bookmen
bookrack
bookrest
books
bookshop
bookworm
boom
boombox
boomed
boomer
boomers
boomier
boomiest
booming
boomkin
boomkins
boomlet
boomlets
booms
boomtown
boomy
boon
boondock
boonies
boons
boor
boorish
boors
boos
boost
boosted
booster
boosters
boosting
boosts
boot
bootable
booted
bootee
bootees
bootery
booth
booths
bootie
booties
booting
bootjack
bootlace
bootleg
bootlegs
bootless
bootlick
boots
booty
booze
boozed
boozer
boozers
boozes
boozier
booziest
boozily
boozing
boozy
bop
bopeep
bopeeps
bopped
bopper
boppers
bopping
bops
bora
boraces
boracic
boracite
borage
borages
boral
borals
borane
boranes
boras
borate
borated
borates
borating
borax
boraxes
bordeaux
bordel
bordello
bordels
border
bordered
borderer
borders
bordure
bordures
bore
boreal
borecole
bored
boredom
boredoms
boreen
boreens
borehole
borer
borers
bores
boresome
boric
boride
borides
boring
boringly
borings
born
borne
borneol
borneols
bornite
bornites
boron
boronic
borons
borough
boroughs
borrow
borrowed
borrower
borrows
borsch
borsches
borscht
borschts
borsht
borshts
borstal
borstals
bort
borts
borty
bortz
bortzes
borzoi
borzois
bos
boscage
boscages
boschbok
bosh
boshbok
boshboks
boshes
boshvark
bosk
boskage
boskages
bosker
bosket
boskets
boskier
boskiest
bosks
bosky
bosom
bosomed
bosoming
bosoms
bosomy
boson
bosons
bosque
bosques
bosquet
bosquets
boss
bossdom
bossdoms
bossed
bosses
bossier
bossies
bossiest
bossily
bossing
bossism
bossisms
bossy
boston
bostons
bosun
bosuns
bot
bota
botanic
botanica
botanies
botanise
botanist
botanize
botany
botas
botch
botched
botcher
botchers
botchery
botches
botchier
botchily
botching
botchy
botel
botels
botflies
botfly
both
bother
bothered
bothers
bothies
bothria
bothrium
bothy
botonee
botonnee
botryoid
botryose
botrytis
bots
bott
bottle
bottled
bottler
bottlers
bottles
bottling
bottom
bottomed
bottomer
bottomry
bottoms
botts
botulin
botulins
botulism
boubou
boubous
bouchee
bouchees
boucle
boucles
boudoir
boudoirs
bouffant
bouffe
bouffes
bough
boughed
boughpot
boughs
bought
boughten
bougie
bougies
bouillon
boulder
boulders
bouldery
boule
boules
boulle
boulles
bounce
bounced
bouncer
bouncers
bounces
bouncier
bouncily
bouncing
bouncy
bound
boundary
bounded
bounden
bounder
bounders
bounding
bounds
bountied
bounties
bounty
bouquet
bouquets
bourbon
bourbons
bourdon
bourdons
bourg
bourgeon
bourgs
bourn
bourne
bournes
bourns
bourree
bourrees
bourride
bourse
bourses
bourtree
bouse
boused
bouses
bousing
bousouki
bousy
bout
boutique
bouton
boutons
bouts
bouvier
bouviers
bouzouki
bovid
bovids
bovine
bovinely
bovines
bovinity
bow
bowed
bowel
boweled
boweling
bowelled
bowels
bower
bowered
boweries
bowering
bowers
bowery
bowfin
bowfins
bowfront
bowhead
bowheads
bowing
bowingly
bowings
bowknot
bowknots
bowl
bowlder
bowlders
bowled
bowleg
bowlegs
bowler
bowlers
bowless
bowlful
bowlfuls
bowlike
bowline
bowlines
bowling
bowlings
bowllike
bowls
bowman
bowmen
bowpot
bowpots
bows
bowse
bowsed
bowses
bowshot
bowshots
bowsing
bowsprit
bowwow
bowwowed
bowwows
bowyer
bowyers
box
boxberry
boxboard
boxcar
boxcars
boxed
boxer
boxers
boxes
boxfish
boxful
boxfuls
boxhaul
boxhauls
boxier
boxiest
boxiness
boxing
boxings
boxlike
boxthorn
boxwood
boxwoods
boxy
boy
boyar
boyard
boyards
boyarism
boyars
boychick
boychik
boychiks
boycott
boycotts
boyhood
boyhoods
boyish
boyishly
boyla
boylas
boyo
boyos
boys
bozo
bozos
bra
brabble
brabbled
brabbler
brabbles
brace
braced
bracelet
bracer
bracero
braceros
bracers
braces
brach
braches
brachet
brachets
brachia
brachial
brachium
brachs
bracing
bracings
braciola
braciole
bracken
brackens
bracket
brackets
brackish
braconid
bract
bracteal
bracted
bractlet
bracts
brad
bradawl
bradawls
bradded
bradding
bradoon
bradoons
brads
brae
braes
brag
braggart
bragged
bragger
braggers
braggest
braggier
bragging
braggy
brags
brahma
brahmas
braid
braided
braider
braiders
braiding
braids
brail
brailed
brailing
braille
brailled
brailles
brails
brain
brained
brainier
brainily
braining
brainish
brainpan
brains
brainy
braise
braised
braises
braising
braize
braizes
brake
brakeage
braked
brakeman
brakemen
brakes
brakier
brakiest
braking
braky
braless
bramble
brambled
brambles
brambly
bran
branch
branched
branches
branchia
branchy
brand
branded
brander
branders
brandied
brandies
branding
brandish
brands
brandy
brank
branks
branned
branner
branners
brannier
branning
branny
brans
brant
brantail
brants
bras
brash
brasher
brashes
brashest
brashier
brashly
brashy
brasier
brasiers
brasil
brasilin
brasils
brass
brassage
brassard
brassart
brassed
brasses
brassica
brassie
brassier
brassies
brassily
brassing
brassish
brassy
brat
brats
brattice
brattier
brattish
brattle
brattled
brattles
bratty
braunite
brava
bravado
bravados
bravas
brave
braved
bravely
braver
bravers
bravery
braves
bravest
bravi
braving
bravo
bravoed
bravoes
bravoing
bravos
bravura
bravuras
bravure
braw
brawer
brawest
brawl
brawled
brawler
brawlers
brawlie
brawlier
brawling
brawls
brawly
brawn
brawnier
brawnily
brawns
brawny
braws
braxies
braxy
bray
brayed
brayer
brayers
braying
brays
braza
brazas
braze
brazed
brazen
brazened
brazenly
brazens
brazer
brazers
brazes
brazier
braziers
brazil
brazilin
brazils
brazing
breach
breached
breacher
breaches
bread
breadbox
breaded
breading
breadnut
breads
breadth
breadths
bready
break
breakage
breaker
breakers
breaking
breakout
breaks
breakup
breakups
bream
breamed
breaming
breams
breast
breasted
breasts
breath
breathe
breathed
breather
breathes
breaths
breathy
breccia
breccial
breccias
brecham
brechams
brechan
brechans
bred
brede
bredes
bree
breech
breeched
breeches
breed
breeder
breeders
breeding
breeds
breeks
brees
breeze
breezed
breezes
breezier
breezily
breezing
breezy
bregma
bregmata
bregmate
bren
brens
brent
brents
brethren
breve
breves
brevet
brevetcy
breveted
brevets
breviary
brevier
breviers
brevity
brew
brewage
brewages
brewed
brewer
brewers
brewery
brewing
brewings
brewis
brewises
brews
briar
briard
briards
briars
briary
bribable
bribe
bribed
bribee
bribees
briber
bribers
bribery
bribes
bribing
brick
brickbat
bricked
brickier
bricking
brickle
brickles
bricks
bricky
bricole
bricoles
bridal
bridally
bridals
bride
brides
bridge
bridged
bridges
bridging
bridle
bridled
bridler
bridlers
bridles
bridling
bridoon
bridoons
brie
brief
briefed
briefer
briefers
briefest
briefing
briefly
briefs
brier
briers
briery
bries
brig
brigade
brigaded
brigades
brigand
brigands
bright
brighten
brighter
brightly
brights
brigs
brill
brills
brim
brimful
brimfull
brimless
brimmed
brimmer
brimmers
brimming
brims
brin
brinded
brindle
brindled
brindles
brine
brined
briner
briners
brines
bring
bringer
bringers
bringing
brings
brinier
brinies
briniest
brining
brinish
brink
brinks
brins
briny
brio
brioche
brioches
brionies
briony
brios
briquet
briquets
bris
brisance
brisant
brisk
brisked
brisker
briskest
brisket
briskets
brisking
briskly
brisks
brisling
brisses
bristle
bristled
bristles
bristly
bristol
bristols
brit
britches
brits
britska
britskas
britt
brittle
brittled
brittler
brittles
brittly
britts
britzka
britzkas
britzska
bro
broach
broached
broacher
broaches
broad
broadax
broadaxe
broaden
broadens
broader
broadest
broadish
broadly
broads
brocade
brocaded
brocades
brocatel
broccoli
broche
brochure
brock
brockage
brocket
brockets
brocks
brocoli
brocolis
brogan
brogans
brogue
broguery
brogues
broguish
broider
broiders
broidery
broil
broiled
broiler
broilers
broiling
broils
brokage
brokages
broke
broken
brokenly
broker
brokered
brokers
broking
brokings
brollies
brolly
bromal
bromals
bromate
bromated
bromates
brome
bromelin
bromes
bromic
bromid
bromide
bromides
bromidic
bromids
bromin
bromine
bromines
bromins
bromism
bromisms
bromize
bromized
bromizes
bromo
bromos
bronc
bronchi
bronchia
broncho
bronchos
bronchus
bronco
broncos
broncs
bronze
bronzed
bronzer
bronzers
bronzes
bronzier
bronzing
bronzy
broo
brooch
brooches
brood
brooded
brooder
brooders
broodier
broodily
brooding
broods
broody
brook
brooked
brookie
brookies
brooking
brookite
brooklet
brooks
broom
broomed
broomier
brooming
brooms
broomy
broos
bros
brose
broses
brosy
broth
brothel
brothels
brother
brothers
broths
brothy
brougham
brought
brouhaha
brow
browband
browbeat
browed
browless
brown
browned
browner
brownest
brownie
brownier
brownies
browning
brownish
brownout
browns
browny
brows
browse
browsed
browser
browsers
browses
browsing
brr
brrr
brucella
brucin
brucine
brucines
brucins
brugh
brughs
bruin
bruins
bruise
bruised
bruiser
bruisers
bruises
bruising
bruit
bruited
bruiter
bruiters
bruiting
bruits
brulot
brulots
brulyie
brulyies
brulzie
brulzies
brumal
brumbies
brumby
brume
brumes
brumous
brunch
brunched
brunches
brunet
brunets
brunette
brunizem
brunt
brunts
brush
brushed
brusher
brushers
brushes
brushier
brushing
brushoff
brushup
brushups
brushy
brusk
brusker
bruskest
brusque
brusquer
brut
brutal
brutally
brute
bruted
brutely
brutes
brutify
bruting
brutish
brutism
brutisms
bruxism
bruxisms
bryology
bryonies
bryony
bryozoan
bub
bubal
bubale
bubales
bubaline
bubalis
bubals
bubbies
bubble
bubbled
bubbler
bubblers
bubbles
bubblier
bubblies
bubbling
bubbly
bubby
bubinga
bubingas
bubo
buboed
buboes
bubonic
bubs
buccal
buccally
buck
buckaroo
buckayro
buckbean
bucked
buckeen
buckeens
bucker
buckeroo
buckers
bucket
bucketed
buckets
buckeye
buckeyes
bucking
buckish
buckle
buckled
buckler
bucklers
buckles
buckling
bucko
buckoes
buckra
buckram
buckrams
buckras
bucks
bucksaw
bucksaws
buckshee
buckshot
buckskin
bucktail
bucolic
bucolics
bud
budded
budder
budders
buddied
buddies
budding
buddings
buddle
buddleia
buddles
buddy
buddying
budge
budged
budger
budgers
budges
budget
budgeted
budgeter
budgets
budgie
budgies
budging
budless
budlike
buds
budworm
budworms
buff
buffable
buffalo
buffalos
buffed
buffer
buffered
buffers
buffet
buffeted
buffeter
buffets
buffi
buffier
buffiest
buffing
buffo
buffoon
buffoons
buffos
buffs
buffy
bug
bugaboo
bugaboos
bugbane
bugbanes
bugbear
bugbears
bugeye
bugeyes
bugged
bugger
buggered
buggers
buggery
buggier
buggies
buggiest
bugging
buggy
bughouse
bugle
bugled
bugler
buglers
bugles
bugling
bugloss
bugs
bugseed
bugseeds
bugsha
bugshas
buhl
buhls
buhlwork
buhr
buhrs
build
builded
builder
builders
building
builds
buildup
buildups
built
buirdly
bulb
bulbar
bulbed
bulbel
bulbels
bulbil
bulbils
bulblet
bulblets
bulbous
bulbs
bulbul
bulbuls
bulge
bulged
bulger
bulgers
bulges
bulgier
bulgiest
bulging
bulgur
bulgurs
bulgy
bulimia
bulimiac
bulimias
bulimic
bulimics
bulk
bulkage
bulkages
bulked
bulkhead
bulkier
bulkiest
bulkily
bulking
bulks
bulky
bull
bulla
bullace
bullaces
bullae
bullate
bullbat
bullbats
bulldog
bulldogs
bulldoze
bulled
bullet
bulleted
bulletin
bullets
bullfrog
bullhead
bullhorn
bullied
bullier
bullies
bulliest
bulling
bullion
bullions
bullish
bullneck
bullnose
bullock
bullocks
bullocky
bullous
bullpen
bullpens
bullpout
bullring
bullrush
bulls
bullshit
bullshot
bullweed
bullwhip
bully
bullyboy
bullying
bullyrag
bulrush
bulwark
bulwarks
bum
bumble
bumbled
bumbler
bumblers
bumbles
bumbling
bumboat
bumboats
bumf
bumfs
bumkin
bumkins
bummed
bummer
bummers
bummest
bumming
bump
bumped
bumper
bumpered
bumpers
bumph
bumphs
bumpier
bumpiest
bumpily
bumping
bumpkin
bumpkins
bumps
bumpy
bums
bun
bunch
bunched
bunches
bunchier
bunchily
bunching
bunchy
bunco
buncoed
buncoing
buncombe
buncos
bund
bundist
bundists
bundle
bundled
bundler
bundlers
bundles
bundling
bunds
bundt
bundts
bung
bungalow
bunged
bungee
bungees
bunghole
bunging
bungle
bungled
bungler
bunglers
bungles
bungling
bungs
bunion
bunions
bunk
bunked
bunker
bunkered
bunkers
bunking
bunkmate
bunko
bunkoed
bunkoing
bunkos
bunks
bunkum
bunkums
bunn
bunnies
bunns
bunny
bunraku
bunrakus
buns
bunt
bunted
bunter
bunters
bunting
buntings
buntline
bunts
bunya
bunyas
buoy
buoyage
buoyages
buoyance
buoyancy
buoyant
buoyed
buoying
buoys
buppie
buppies
buqsha
buqshas
bur
bura
buran
burans
buras
burble
burbled
burbler
burblers
burbles
burblier
burbling
burbly
burbot
burbots
burbs
burd
burden
burdened
burdener
burdens
burdie
burdies
burdock
burdocks
burds
bureau
bureaus
bureaux
buret
burets
burette
burettes
burg
burgage
burgages
burgee
burgees
burgeon
burgeons
burger
burgers
burgess
burgh
burghal
burgher
burghers
burghs
burglar
burglars
burglary
burgle
burgled
burgles
burgling
burgonet
burgoo
burgoos
burgout
burgouts
burgrave
burgs
burgundy
burial
burials
buried
burier
buriers
buries
burin
burins
burke
burked
burker
burkers
burkes
burking
burkite
burkites
burl
burlap
burlaps
burled
burler
burlers
burlesk
burlesks
burley
burleys
burlier
burliest
burlily
burling
burls
burly
burn
burnable
burned
burner
burners
burnet
burnets
burnie
burnies
burning
burnings
burnish
burnoose
burnous
burnout
burnouts
burns
burnt
burp
burped
burping
burps
burr
burred
burrer
burrers
burrier
burriest
burring
burrito
burritos
burro
burros
burrow
burrowed
burrower
burrows
burrs
burry
burs
bursa
bursae
bursal
bursar
bursars
bursary
bursas
bursate
burse
burseed
burseeds
bursera
burses
bursitis
burst
bursted
burster
bursters
bursting
burstone
bursts
burthen
burthens
burton
burtons
burweed
burweeds
bury
burying
bus
busbar
busbars
busbies
busboy
busboys
busby
bused
buses
bush
bushbuck
bushed
bushel
busheled
busheler
bushels
busher
bushers
bushes
bushfire
bushgoat
bushido
bushidos
bushier
bushiest
bushily
bushing
bushings
bushland
bushless
bushlike
bushman
bushmen
bushpig
bushpigs
bushtit
bushtits
bushwa
bushwah
bushwahs
bushwas
bushy
busied
busier
busies
busiest
busily
business
busing
busings
busk
busked
busker
buskers
buskin
buskined
busking
buskins
busks
busload
busloads
busman
busmen
buss
bussed
busses
bussing
bussings
bust
bustard
bustards
busted
buster
busters
bustic
bustics
bustier
bustiers
bustiest
busting
bustle
bustled
bustles
bustline
bustling
busts
busty
busulfan
busy
busybody
busying
busyness
busywork
but
butane
butanes
butanol
butanols
butanone
butch
butcher
butchers
butchery
butches
bute
butene
butenes
buteo
buteos
butle
butled
butler
butlers
butlery
butles
butling
buts
butt
buttals
butte
butted
butter
buttered
butters
buttery
buttes
butties
butting
buttock
buttocks
button
buttoned
buttoner
buttons
buttony
buttress
butts
butty
butut
bututs
butyl
butylate
butylene
butyls
butyral
butyrals
butyrate
butyric
butyrin
butyrins
butyrous
butyryl
butyryls
buxom
buxomer
buxomest
buxomly
buy
buyable
buyback
buybacks
buyer
buyers
buying
buyout
buyouts
buys
buzuki
buzukia
buzukis
buzz
buzzard
buzzards
buzzed
buzzer
buzzers
buzzes
buzzing
buzzwig
buzzwigs
buzzword
bwana
bwanas
by
bye
byelaw
byelaws
byes
bygone
bygones
bylaw
bylaws
byline
bylined
byliner
byliners
bylines
bylining
byname
bynames
bypass
bypassed
bypasses
bypast
bypath
bypaths
byplay
byplays
byre
byres
byrl
byrled
byrling
byrls
byrnie
byrnies
byroad
byroads
bys
byssi
byssus
byssuses
bystreet
bytalk
bytalks
byte
bytes
byway
byways
byword
bywords
bywork
byworks
byzant
byzants
cab
cabal
cabala
cabalas
cabalism
cabalist
caballed
cabals
cabana
cabanas
cabaret
cabarets
cabbage
cabbaged
cabbages
cabbala
cabbalah
cabbalas
cabbed
cabbie
cabbies
cabbing
cabby
caber
cabernet
cabers
cabestro
cabezon
cabezone
cabezons
cabildo
cabildos
cabin
cabined
cabinet
cabinets
cabining
cabins
cable
cabled
cables
cablet
cablets
cableway
cabling
cabman
cabmen
cabob
cabobs
caboched
cabochon
cabomba
cabombas
caboodle
caboose
cabooses
caboshed
cabotage
cabresta
cabresto
cabretta
cabrilla
cabriole
cabs
cabstand
caca
cacao
cacaos
cacas
cachalot
cache
cached
cachepot
caches
cachet
cacheted
cachets
cachexia
cachexic
cachexy
caching
cachou
cachous
cachucha
cacique
caciques
cackle
cackled
cackler
cacklers
cackles
cackling
cacodyl
cacodyls
cacomixl
cacti
cactoid
cactus
cactuses
cad
cadaster
cadastre
cadaver
cadavers
caddice
caddices
caddie
caddied
caddies
caddis
caddises
caddish
caddy
caddying
cade
cadelle
cadelles
cadence
cadenced
cadences
cadency
cadent
cadenza
cadenzas
cades
cadet
cadets
cadge
cadged
cadger
cadgers
cadges
cadging
cadgy
cadi
cadis
cadmic
cadmium
cadmiums
cadre
cadres
cads
caducean
caducei
caduceus
caducity
caducous
caeca
caecal
caecally
caecum
caeoma
caeomas
caesar
caesars
caesium
caesiums
caestus
caesura
caesurae
caesural
caesuras
caesuric
cafe
cafes
caff
caffein
caffeine
caffeins
caffs
caftan
caftans
cage
caged
cageful
cagefuls
cageling
cager
cagers
cages
cagey
cagier
cagiest
cagily
caginess
caging
cagy
cahier
cahiers
cahoot
cahoots
cahow
cahows
caid
caids
caiman
caimans
cain
cains
caique
caiques
caird
cairds
cairn
cairned
cairns
cairny
caisson
caissons
caitiff
caitiffs
cajaput
cajaputs
cajeput
cajeputs
cajole
cajoled
cajoler
cajolers
cajolery
cajoles
cajoling
cajon
cajones
cajuput
cajuputs
cake
caked
cakes
cakewalk
cakey
cakier
cakiest
caking
caky
calabash
caladium
calamar
calamari
calamars
calamary
calami
calamine
calamint
calamite
calamity
calamus
calando
calash
calashes
calathi
calathos
calathus
calcanea
calcanei
calcar
calcaria
calcars
calceate
calces
calcic
calcific
calcify
calcine
calcined
calcines
calcite
calcites
calcitic
calcium
calciums
calcspar
calctufa
calctuff
calculi
calculus
caldaria
caldera
calderas
caldron
caldrons
caleche
caleches
calendal
calendar
calender
calends
calesa
calesas
calf
calflike
calfs
calfskin
caliber
calibers
calibre
calibred
calibres
calices
caliche
caliches
calicle
calicles
calico
calicoes
calicos
calif
califate
califs
calipash
calipee
calipees
caliper
calipers
caliph
caliphal
caliphs
calisaya
calix
calk
calked
calker
calkers
calkin
calking
calkins
calks
call
calla
callable
callaloo
callan
callans
callant
callants
callas
callback
callboy
callboys
called
caller
callers
callet
callets
calling
callings
calliope
callipee
calliper
callose
calloses
callous
callow
callower
calls
callus
callused
calluses
calm
calmed
calmer
calmest
calming
calmly
calmness
calms
calo
calomel
calomels
caloric
calorics
calorie
calories
calorize
calory
calotte
calottes
calotype
caloyer
caloyers
calpac
calpack
calpacks
calpacs
calque
calqued
calques
calquing
calthrop
caltrap
caltraps
caltrop
caltrops
calumet
calumets
calumny
calutron
calvados
calvaria
calvary
calve
calved
calves
calving
calx
calxes
calycate
calyceal
calyces
calycine
calycle
calycles
calyculi
calypso
calypsos
calypter
calyptra
calyx
calyxes
calzone
calzones
cam
camail
camailed
camails
camas
camases
camass
camasses
camber
cambered
cambers
cambia
cambial
cambism
cambisms
cambist
cambists
cambium
cambiums
cambogia
cambric
cambrics
came
camel
cameleer
camelia
camelias
camellia
camels
cameo
cameoed
cameoing
cameos
camera
camerae
cameral
cameras
cames
camion
camions
camisa
camisade
camisado
camisas
camise
camises
camisia
camisias
camisole
camlet
camlets
camomile
camorra
camorras
camp
campagna
campagne
campaign
camped
camper
campers
campfire
camphene
camphine
camphire
camphol
camphols
camphor
camphors
campi
campier
campiest
campily
camping
campings
campion
campions
campo
campong
campongs
camporee
campos
camps
campsite
campus
campused
campuses
campy
cams
camshaft
can
canaille
canakin
canakins
canal
canaled
canaling
canalise
canalize
canalled
canaller
canals
canape
canapes
canard
canards
canaries
canary
canasta
canastas
cancan
cancans
cancel
canceled
canceler
cancels
cancer
cancers
cancha
canchas
cancroid
candela
candelas
candent
candid
candida
candidas
candider
candidly
candids
candied
candies
candle
candled
candler
candlers
candles
candling
candor
candors
candour
candours
candy
candying
cane
caned
canella
canellas
canephor
caner
caners
canes
caneware
canfield
canful
canfuls
cangue
cangues
canid
canids
canikin
canikins
canine
canines
caning
caninity
canister
canities
canker
cankered
cankers
canna
cannabic
cannabin
cannabis
cannas
canned
cannel
cannelon
cannels
canner
canners
cannery
cannibal
cannie
cannier
canniest
cannikin
cannily
canning
cannings
cannoli
cannon
cannoned
cannonry
cannons
cannot
cannula
cannulae
cannular
cannulas
canny
canoe
canoed
canoeing
canoeist
canoes
canola
canon
canoness
canonic
canonise
canonist
canonize
canonry
canons
canoodle
canopied
canopies
canopy
canorous
cans
cansful
canso
cansos
canst
cant
cantala
cantalas
cantata
cantatas
cantdog
cantdogs
canted
canteen
canteens
canter
cantered
canters
canthal
canthi
canthus
cantic
canticle
cantina
cantinas
canting
cantle
cantles
canto
canton
cantonal
cantoned
cantons
cantor
cantors
cantos
cantraip
cantrap
cantraps
cantrip
cantrips
cants
cantus
canty
canula
canulae
canulas
canulate
canvas
canvased
canvaser
canvases
canvass
canyon
canyons
canzona
canzonas
canzone
canzones
canzonet
canzoni
cap
capable
capabler
capably
capacity
cape
caped
capelan
capelans
capelet
capelets
capelin
capelins
caper
capered
caperer
caperers
capering
capers
capes
capeskin
capework
capful
capfuls
caph
caphs
capias
capiases
capita
capital
capitals
capitate
capitol
capitols
capitula
capless
caplet
caplets
caplin
caplins
capmaker
capo
capon
caponata
caponier
caponize
capons
caporal
caporals
capos
capote
capotes
capouch
capped
capper
cappers
capping
cappings
capric
capricci
caprice
caprices
caprifig
caprine
capriole
capris
caprock
caprocks
caps
capsicin
capsicum
capsid
capsidal
capsids
capsize
capsized
capsizes
capsomer
capstan
capstans
capstone
capsular
capsule
capsuled
capsules
captain
captains
captan
captans
caption
captions
captious
captive
captives
captor
captors
capture
captured
capturer
captures
capuche
capuched
capuches
capuchin
caput
capybara
car
carabao
carabaos
carabid
carabids
carabin
carabine
carabins
caracal
caracals
caracara
carack
caracks
caracol
caracole
caracols
caracul
caraculs
carafe
carafes
caragana
carageen
caramba
caramel
caramels
carangid
carapace
carapax
carassow
carat
carate
carates
carats
caravan
caravans
caravel
caravels
caraway
caraways
carb
carbamic
carbamyl
carbarn
carbarns
carbaryl
carbide
carbides
carbine
carbines
carbinol
carbo
carbolic
carbon
carbonic
carbons
carbonyl
carbora
carboras
carbos
carboxyl
carboy
carboyed
carboys
carbs
carburet
carcajou
carcanet
carcase
carcases
carcass
carcel
carcels
card
cardamom
cardamon
cardamum
cardcase
carded
carder
carders
cardia
cardiac
cardiacs
cardiae
cardias
cardigan
cardinal
carding
cardings
cardioid
carditic
carditis
cardoon
cardoons
cards
care
cared
careen
careened
careener
careens
career
careered
careerer
careers
carefree
careful
careless
carer
carers
cares
caress
caressed
caresser
caresses
caret
caretake
caretook
carets
careworn
carex
carfare
carfares
carful
carfuls
cargo
cargoes
cargos
carhop
carhops
caribe
caribes
caribou
caribous
carices
caried
caries
carillon
carina
carinae
carinal
carinas
carinate
caring
carioca
cariocas
cariole
carioles
carious
caritas
cark
carked
carking
carks
carl
carle
carles
carless
carlin
carline
carlines
carling
carlings
carlins
carlish
carload
carloads
carls
carmaker
carman
carmen
carmine
carmines
carn
carnage
carnages
carnal
carnally
carnauba
carnet
carnets
carney
carneys
carnie
carnies
carnify
carnival
carns
carny
caroach
carob
carobs
caroch
caroche
caroches
carol
caroled
caroler
carolers
caroli
caroling
carolled
caroller
carols
carolus
carom
caromed
caroming
caroms
carotene
carotid
carotids
carotin
carotins
carousal
carouse
caroused
carousel
carouser
carouses
carp
carpal
carpale
carpalia
carpals
carped
carpel
carpels
carper
carpers
carpet
carpeted
carpets
carpi
carping
carpings
carpool
carpools
carport
carports
carps
carpus
carr
carrack
carracks
carrel
carrell
carrells
carrels
carriage
carried
carrier
carriers
carries
carriole
carrion
carrions
carritch
carroch
carrom
carromed
carroms
carrot
carrotin
carrots
carroty
carrs
carry
carryall
carrying
carryon
carryons
carryout
cars
carse
carses
carsick
cart
cartable
cartage
cartages
carte
carted
cartel
cartels
carter
carters
cartes
carting
cartload
carton
cartoned
cartons
cartoon
cartoons
cartoony
cartop
cartouch
carts
caruncle
carve
carved
carvel
carvels
carven
carver
carvers
carves
carving
carvings
carwash
caryatic
caryatid
caryotin
casa
casaba
casabas
casas
casava
casavas
casbah
casbahs
cascabel
cascable
cascade
cascaded
cascades
cascara
cascaras
case
casease
caseases
caseate
caseated
caseates
casebook
cased
casefied
casefies
casefy
caseic
casein
caseins
caseload
casemate
casement
caseose
caseoses
caseous
casern
caserne
casernes
caserns
cases
casette
casettes
casework
caseworm
cash
cashable
cashaw
cashaws
cashbook
cashbox
cashed
cashes
cashew
cashews
cashier
cashiers
cashing
cashless
cashmere
cashoo
cashoos
casimere
casimire
casing
casings
casini
casino
casinos
casita
casitas
cask
casked
casket
casketed
caskets
casking
casks
casky
casque
casqued
casques
cassaba
cassabas
cassata
cassatas
cassava
cassavas
cassette
cassia
cassias
cassino
cassinos
cassis
cassises
cassock
cassocks
cast
castable
castanet
castaway
caste
casteism
caster
casters
castes
casting
castings
castle
castled
castles
castling
castoff
castoffs
castor
castors
castrate
castrati
castrato
casts
casual
casually
casuals
casualty
casuist
casuists
casus
cat
catacomb
catalase
catalo
cataloes
catalog
catalogs
catalos
catalpa
catalpas
catalyst
catalyze
catamite
catapult
cataract
catarrh
catarrhs
catawba
catawbas
catbird
catbirds
catboat
catboats
catbrier
catcall
catcalls
catch
catchall
catcher
catchers
catches
catchfly
catchier
catching
catchup
catchups
catchy
catclaw
catclaws
cate
catechin
catechol
catechu
catechus
category
catena
catenae
catenary
catenas
catenate
catenoid
cater
cateran
caterans
catered
caterer
caterers
cateress
catering
caters
cates
catface
catfaces
catfall
catfalls
catfight
catfish
catgut
catguts
cathead
catheads
cathect
cathects
cathedra
catheter
cathexes
cathexis
cathodal
cathode
cathodes
cathodic
catholic
cathouse
cation
cationic
cations
catkin
catkins
catlike
catlin
catling
catlings
catlins
catmint
catmints
catnap
catnaper
catnaps
catnip
catnips
cats
catspaw
catspaws
catsup
catsups
cattail
cattails
cattalo
cattalos
catted
cattery
cattie
cattier
catties
cattiest
cattily
catting
cattish
cattle
cattleya
catty
catwalk
catwalks
caucus
caucused
caucuses
caudad
caudal
caudally
caudate
caudated
caudates
caudex
caudexes
caudices
caudillo
caudle
caudles
caught
caul
cauld
cauldron
caulds
caules
caulicle
cauline
caulis
caulk
caulked
caulker
caulkers
caulking
caulks
cauls
causable
causal
causally
causals
cause
caused
causer
causerie
causers
causes
causeway
causey
causeys
causing
caustic
caustics
cautery
caution
cautions
cautious
cavalero
cavalier
cavalla
cavallas
cavally
cavalry
cavatina
cavatine
cave
caveat
caveated
caveator
caveats
caved
cavefish
cavelike
caveman
cavemen
caver
cavern
caverned
caverns
cavers
caves
cavetti
cavetto
cavettos
caviar
caviare
caviares
caviars
cavicorn
cavie
cavies
cavil
caviled
caviler
cavilers
caviling
cavilled
caviller
cavils
caving
cavings
cavitary
cavitate
cavitied
cavities
cavity
cavort
cavorted
cavorter
cavorts
cavy
caw
cawed
cawing
caws
cay
cayenne
cayenned
cayennes
cayman
caymans
cays
cayuse
cayuses
cazique
caziques
cease
ceased
ceases
ceasing
cebid
cebids
ceboid
ceboids
ceca
cecal
cecally
cecum
cedar
cedarn
cedars
cede
ceded
ceder
ceders
cedes
cedi
cedilla
cedillas
ceding
cedis
cedula
cedulas
cee
cees
ceiba
ceibas
ceil
ceiled
ceiler
ceilers
ceiling
ceilings
ceils
ceinture
cel
celadon
celadons
celeb
celebs
celeriac
celeries
celerity
celery
celesta
celestas
celeste
celestes
celiac
celiacs
celibacy
celibate
cell
cella
cellae
cellar
cellared
cellarer
cellaret
cellars
celled
celli
celling
cellist
cellists
cellmate
cello
cellos
cells
cellular
cellule
cellules
celom
celomata
celoms
celosia
celosias
cels
celt
celts
cembali
cembalo
cembalos
cement
cementa
cemented
cementer
cements
cementum
cemetery
cenacle
cenacles
cenobite
cenotaph
cenote
cenotes
cense
censed
censer
censers
censes
censing
censor
censored
censors
censual
censure
censured
censurer
censures
census
censused
censuses
cent
cental
centals
centare
centares
centaur
centaurs
centaury
centavo
centavos
center
centered
centers
centeses
centesis
centiare
centile
centiles
centime
centimes
centimo
centimos
centner
centners
cento
centones
centos
centra
central
centrals
centre
centred
centres
centric
centring
centrism
centrist
centroid
centrum
centrums
cents
centum
centums
centuple
century
ceorl
ceorlish
ceorls
cep
cepe
cepes
cephalad
cephalic
cephalin
cepheid
cepheids
ceps
ceramal
ceramals
ceramic
ceramics
ceramist
cerastes
cerate
cerated
cerates
ceratin
ceratins
ceratoid
cercaria
cerci
cercis
cercises
cercus
cere
cereal
cereals
cerebra
cerebral
cerebric
cerebrum
cered
cerement
ceremony
ceres
cereus
cereuses
ceria
cerias
ceric
cering
ceriph
ceriphs
cerise
cerises
cerite
cerites
cerium
ceriums
cermet
cermets
cernuous
cero
ceros
cerotic
cerotype
cerous
certain
certes
certify
cerulean
cerumen
cerumens
ceruse
ceruses
cerusite
cervelas
cervelat
cervical
cervices
cervid
cervine
cervix
cervixes
cesarean
cesarian
cesium
cesiums
cess
cessed
cesses
cessing
cession
cessions
cesspit
cesspits
cesspool
cesta
cestas
cesti
cestode
cestodes
cestoi
cestoid
cestoids
cestos
cestus
cestuses
cesura
cesurae
cesuras
cetacean
cetane
cetanes
cete
cetes
cetology
ceviche
ceviches
chablis
chabouk
chabouks
chabuk
chabuks
chacma
chacmas
chaconne
chad
chadar
chadarim
chadars
chadless
chador
chadors
chadri
chads
chaeta
chaetae
chaetal
chafe
chafed
chafer
chafers
chafes
chaff
chaffed
chaffer
chaffers
chaffier
chaffing
chaffs
chaffy
chafing
chagrin
chagrins
chain
chaine
chained
chaines
chaining
chainman
chainmen
chains
chainsaw
chair
chaired
chairing
chairman
chairmen
chairs
chaise
chaises
chakra
chakras
chalah
chalahs
chalaza
chalazae
chalazal
chalazas
chalazia
chalcid
chalcids
chaldron
chaleh
chalehs
chalet
chalets
chalice
chaliced
chalices
chalk
chalked
chalkier
chalking
chalks
chalky
challa
challah
challahs
challas
challie
challies
challis
challot
challoth
chally
chalone
chalones
chalot
chaloth
chalutz
cham
chamade
chamades
chamber
chambers
chambray
chamfer
chamfers
chamfron
chamise
chamises
chamiso
chamisos
chammied
chammies
chammy
chamois
chamoix
champ
champac
champacs
champak
champaks
champed
champer
champers
champing
champion
champs
champy
chams
chance
chanced
chancel
chancels
chancery
chances
chancier
chancily
chancing
chancre
chancres
chancy
chandler
chanfron
chang
change
changed
changer
changers
changes
changing
changs
channel
channels
chanson
chansons
chant
chantage
chanted
chanter
chanters
chantey
chanteys
chanties
chanting
chantor
chantors
chantry
chants
chanty
chao
chaos
chaoses
chaotic
chap
chapati
chapatis
chapatti
chapbook
chape
chapeau
chapeaus
chapeaux
chapel
chapels
chaperon
chapes
chapiter
chaplain
chaplet
chaplets
chapman
chapmen
chappati
chapped
chapping
chaps
chapt
chapter
chapters
chaqueta
char
characid
characin
charade
charades
charas
charases
charcoal
chard
chards
chare
chared
chares
charge
charged
charger
chargers
charges
charging
charier
chariest
charily
charing
chariot
chariots
charism
charisma
charisms
charity
chark
charka
charkas
charked
charkha
charkhas
charking
charks
charlady
charley
charleys
charlie
charlies
charlock
charm
charmed
charmer
charmers
charming
charms
charnel
charnels
charpai
charpais
charpoy
charpoys
charqui
charquid
charquis
charr
charred
charrier
charring
charro
charros
charrs
charry
chars
chart
charted
charter
charters
charting
chartist
charts
chary
chase
chased
chaser
chasers
chases
chasing
chasings
chasm
chasmal
chasmed
chasmic
chasms
chasmy
chasse
chassed
chasses
chasseur
chassis
chaste
chastely
chasten
chastens
chaster
chastest
chastise
chastity
chasuble
chat
chatchka
chatchke
chateau
chateaus
chateaux
chats
chatted
chattel
chattels
chatter
chatters
chattery
chattier
chattily
chatting
chatty
chaufer
chaufers
chauffer
chaunt
chaunted
chaunter
chaunts
chausses
chaw
chawed
chawer
chawers
chawing
chaws
chay
chayote
chayotes
chays
chazan
chazanim
chazans
chazzan
chazzans
chazzen
chazzens
cheap
cheapen
cheapens
cheaper
cheapest
cheapie
cheapies
cheapish
cheaply
cheapo
cheapos
cheaps
cheat
cheated
cheater
cheaters
cheating
cheats
chebec
chebecs
chechako
check
checked
checker
checkers
checking
checkoff
checkout
checkrow
checks
checkup
checkups
cheddar
cheddars
cheddite
cheder
cheders
chedite
chedites
cheek
cheeked
cheekful
cheekier
cheekily
cheeking
cheeks
cheeky
cheep
cheeped
cheeper
cheepers
cheeping
cheeps
cheer
cheered
cheerer
cheerers
cheerful
cheerier
cheerily
cheering
cheerio
cheerios
cheerled
cheerly
cheero
cheeros
cheers
cheery
cheese
cheesed
cheeses
cheesier
cheesily
cheesing
cheesy
cheetah
cheetahs
chef
chefdom
chefdoms
cheffed
cheffing
chefs
chegoe
chegoes
chela
chelae
chelas
chelate
chelated
chelates
chelator
cheliped
cheloid
cheloids
chemic
chemical
chemics
chemise
chemises
chemism
chemisms
chemist
chemists
chemo
chemos
chemurgy
chenille
chenopod
cheque
chequer
chequers
cheques
cherish
cheroot
cheroots
cherries
cherry
chert
chertier
cherts
cherty
cherub
cherubic
cherubim
cherubs
chervil
chervils
chess
chesses
chessman
chessmen
chest
chested
chestful
chestier
chestnut
chests
chesty
chetah
chetahs
cheth
cheths
chetrum
chetrums
chevalet
cheveron
chevied
chevies
cheviot
cheviots
chevre
chevres
chevron
chevrons
chevy
chevying
chew
chewable
chewed
chewer
chewers
chewier
chewiest
chewing
chewink
chewinks
chews
chewy
chez
chi
chia
chiao
chias
chiasm
chiasma
chiasmal
chiasmas
chiasmi
chiasmic
chiasms
chiasmus
chiastic
chiaus
chiauses
chibouk
chibouks
chic
chicane
chicaned
chicaner
chicanes
chicano
chicanos
chiccory
chicer
chicest
chichi
chichis
chick
chickee
chickees
chicken
chickens
chickory
chickpea
chicks
chicle
chicles
chicly
chicness
chico
chicory
chicos
chics
chid
chidden
chide
chided
chider
chiders
chides
chiding
chief
chiefdom
chiefer
chiefest
chiefly
chiefs
chiel
chield
chields
chiels
chiffon
chiffons
chigetai
chigger
chiggers
chignon
chignons
chigoe
chigoes
child
childbed
childe
childes
childing
childish
childly
children
chile
chiles
chili
chiliad
chiliads
chiliasm
chiliast
chilidog
chilies
chill
chilled
chiller
chillers
chillest
chilli
chillier
chillies
chillily
chilling
chills
chillum
chillums
chilly
chilopod
chimaera
chimar
chimars
chimb
chimbley
chimbly
chimbs
chime
chimed
chimer
chimera
chimeras
chimere
chimeres
chimeric
chimers
chimes
chiming
chimla
chimlas
chimley
chimleys
chimney
chimneys
chimp
chimps
chin
china
chinas
chinbone
chinch
chinches
chinchy
chine
chined
chines
chining
chink
chinked
chinkier
chinking
chinks
chinky
chinless
chinned
chinning
chino
chinone
chinones
chinook
chinooks
chinos
chins
chints
chintses
chintz
chintzes
chintzy
chip
chipmuck
chipmunk
chipped
chipper
chippers
chippie
chippier
chippies
chipping
chippy
chips
chiral
chirk
chirked
chirker
chirkest
chirking
chirks
chirm
chirmed
chirming
chirms
chiro
chiros
chirp
chirped
chirper
chirpers
chirpier
chirpily
chirping
chirps
chirpy
chirr
chirre
chirred
chirres
chirring
chirrs
chirrup
chirrups
chirrupy
chis
chisel
chiseled
chiseler
chisels
chit
chital
chitchat
chitin
chitins
chitlin
chitling
chitlins
chiton
chitons
chitosan
chits
chitter
chitters
chitties
chitty
chivalry
chivaree
chivari
chive
chives
chivied
chivies
chivvied
chivvies
chivvy
chivy
chivying
chlamys
chloasma
chloral
chlorals
chlorate
chlordan
chloric
chlorid
chloride
chlorids
chlorin
chlorine
chlorins
chlorite
chlorous
choana
choanae
chock
chocked
chockful
chocking
chocks
choice
choicely
choicer
choices
choicest
choir
choirboy
choired
choiring
choirs
choke
choked
choker
chokers
chokes
chokey
chokier
chokiest
choking
choky
cholate
cholates
cholent
cholents
choler
cholera
choleras
choleric
cholers
choline
cholines
cholla
chollas
cholo
cholos
chomp
chomped
chomper
chompers
chomping
chomps
chon
chook
chooks
choose
chooser
choosers
chooses
choosey
choosier
choosing
choosy
chop
chopin
chopine
chopines
chopins
chopped
chopper
choppers
choppier
choppily
chopping
choppy
chops
choragi
choragic
choragus
choral
chorale
chorales
chorally
chorals
chord
chordal
chordate
chorded
chording
chords
chore
chorea
choreal
choreas
chored
choregi
choregus
choreic
choreman
choremen
choreoid
chores
chorial
choriamb
choric
chorine
chorines
choring
chorioid
chorion
chorions
chorizo
chorizos
choroid
choroids
chortle
chortled
chortler
chortles
chorus
chorused
choruses
chose
chosen
choses
chott
chotts
chough
choughs
chouse
choused
chouser
chousers
chouses
choush
choushes
chousing
chow
chowchow
chowder
chowders
chowed
chowing
chows
chowse
chowsed
chowses
chowsing
chowtime
chresard
chrism
chrisma
chrismal
chrismon
chrisms
chrisom
chrisoms
christen
christie
christy
chroma
chromas
chromate
chrome
chromed
chromes
chromic
chromide
chroming
chromite
chromium
chromize
chromo
chromos
chromous
chromyl
chromyls
chronaxy
chronic
chronics
chronon
chronons
chthonic
chub
chubasco
chubbier
chubbily
chubby
chubs
chuck
chucked
chuckies
chucking
chuckle
chuckled
chuckler
chuckles
chucks
chucky
chuddah
chuddahs
chuddar
chuddars
chudder
chudders
chufa
chufas
chuff
chuffed
chuffer
chuffest
chuffier
chuffing
chuffs
chuffy
chug
chugalug
chugged
chugger
chuggers
chugging
chugs
chukar
chukars
chukka
chukkar
chukkars
chukkas
chukker
chukkers
chum
chummed
chummier
chummily
chumming
chummy
chump
chumped
chumping
chumps
chums
chumship
chunk
chunked
chunkier
chunkily
chunking
chunks
chunky
chunter
chunters
church
churched
churches
churchly
churchy
churl
churlish
churls
churn
churned
churner
churners
churning
churns
churr
churred
churring
churrs
chute
chuted
chutes
chuting
chutist
chutists
chutnee
chutnees
chutney
chutneys
chutzpa
chutzpah
chutzpas
chyle
chyles
chylous
chyme
chymes
chymic
chymics
chymist
chymists
chymosin
chymous
ciao
cibol
cibols
ciboria
ciborium
ciboule
ciboules
cicada
cicadae
cicadas
cicala
cicalas
cicale
cicatrix
cicelies
cicely
cicero
cicerone
ciceroni
ciceros
cichlid
cichlids
cicisbei
cicisbeo
cicoree
cicorees
cider
ciders
cigar
cigaret
cigarets
cigars
cilantro
cilia
ciliary
ciliate
ciliated
ciliates
cilice
cilices
cilium
cimbalom
cimex
cimices
cinch
cinched
cinches
cinching
cinchona
cincture
cinder
cindered
cinders
cindery
cine
cineast
cineaste
cineasts
cinema
cinemas
cineol
cineole
cineoles
cineols
cinerary
cinerin
cinerins
cines
cingula
cingulum
cinnabar
cinnamic
cinnamon
cinnamyl
cinquain
cinque
cinques
cion
cions
cioppino
cipher
ciphered
ciphers
ciphony
cipolin
cipolins
circa
circle
circled
circler
circlers
circles
circlet
circlets
circling
circuit
circuits
circuity
circular
circus
circuses
circusy
cire
cires
cirque
cirques
cirrate
cirri
cirriped
cirrose
cirrous
cirrus
cirsoid
cis
cisco
ciscoes
ciscos
cislunar
cissies
cissoid
cissoids
cissy
cist
cistern
cisterna
cisterns
cistron
cistrons
cists
cistus
cistuses
citable
citadel
citadels
citation
citator
citators
citatory
cite
citeable
cited
citer
citers
cites
cithara
citharas
cither
cithern
citherns
cithers
cithren
cithrens
citied
cities
citified
citifies
citify
citing
citizen
citizens
citola
citolas
citole
citoles
citral
citrals
citrate
citrated
citrates
citreous
citric
citrin
citrine
citrines
citrinin
citrins
citron
citrons
citrous
citrus
citruses
citrusy
cittern
citterns
city
cityfied
cityward
citywide
civet
civets
civic
civicism
civics
civie
civies
civil
civilian
civilise
civility
civilize
civilly
civism
civisms
civvies
civvy
clabber
clabbers
clach
clachan
clachans
clachs
clack
clacked
clacker
clackers
clacking
clacks
clad
cladding
clade
clades
cladist
cladists
cladode
cladodes
clads
clag
clagged
clagging
clags
claim
claimant
claimed
claimer
claimers
claiming
claims
clam
clamant
clambake
clamber
clambers
clammed
clammer
clammers
clammier
clammily
clamming
clammy
clamor
clamored
clamorer
clamors
clamour
clamours
clamp
clamped
clamper
clampers
clamping
clamps
clams
clamworm
clan
clang
clanged
clanger
clangers
clanging
clangor
clangors
clangour
clangs
clank
clanked
clanking
clanks
clannish
clans
clansman
clansmen
clap
clapped
clapper
clappers
clapping
claps
clapt
claptrap
claque
claquer
claquers
claques
claqueur
clarence
claret
clarets
claries
clarify
clarinet
clarion
clarions
clarity
clarkia
clarkias
claro
claroes
claros
clary
clash
clashed
clasher
clashers
clashes
clashing
clasp
clasped
clasper
claspers
clasping
clasps
claspt
class
classed
classer
classers
classes
classic
classico
classics
classier
classify
classily
classing
classis
classism
classist
classy
clast
clastic
clastics
clasts
clatter
clatters
clattery
claucht
claught
claughts
clausal
clause
clauses
claustra
clavate
clave
claver
clavered
clavers
claves
clavi
clavicle
clavier
claviers
clavus
claw
clawed
clawer
clawers
clawing
clawless
clawlike
claws
claxon
claxons
clay
claybank
clayed
clayey
clayier
clayiest
claying
clayish
claylike
claymore
claypan
claypans
clays
clayware
clean
cleaned
cleaner
cleaners
cleanest
cleaning
cleanly
cleans
cleanse
cleansed
cleanser
cleanses
cleanup
cleanups
clear
cleared
clearer
clearers
clearest
clearing
clearly
clears
cleat
cleated
cleating
cleats
cleavage
cleave
cleaved
cleaver
cleavers
cleaves
cleaving
cleek
cleeked
cleeking
cleeks
clef
clefs
cleft
clefted
clefting
clefts
cleidoic
clematis
clemency
clement
clench
clenched
clencher
clenches
cleome
cleomes
clepe
cleped
clepes
cleping
clept
clergies
clergy
cleric
clerical
clerics
clerid
clerids
clerihew
clerisy
clerk
clerkdom
clerked
clerking
clerkish
clerkly
clerks
cleveite
clever
cleverer
cleverly
clevis
clevises
clew
clewed
clewing
clews
cliche
cliched
cliches
click
clicked
clicker
clickers
clicking
clicks
client
cliental
clients
cliff
cliffier
cliffs
cliffy
clift
clifts
climatal
climate
climates
climatic
climax
climaxed
climaxes
climb
climbed
climber
climbers
climbing
climbs
clime
climes
clinal
clinally
clinch
clinched
clincher
clinches
cline
clines
cling
clinged
clinger
clingers
clingier
clinging
clings
clingy
clinic
clinical
clinics
clink
clinked
clinker
clinkers
clinking
clinks
clip
clipped
clipper
clippers
clipping
clips
clipt
clique
cliqued
cliques
cliquey
cliquier
cliquing
cliquish
cliquy
clitella
clitic
clitics
clitoral
clitoric
clitoris
clivers
clivia
clivias
cloaca
cloacae
cloacal
cloacas
cloak
cloaked
cloaking
cloaks
clobber
clobbers
clochard
cloche
cloches
clock
clocked
clocker
clockers
clocking
clocks
clod
cloddier
cloddish
cloddy
clodpate
clodpole
clodpoll
clods
clog
clogged
clogger
cloggers
cloggier
clogging
cloggy
clogs
cloister
clomb
clomp
clomped
clomping
clomps
clon
clonal
clonally
clone
cloned
cloner
cloners
clones
clonic
cloning
clonings
clonism
clonisms
clonk
clonked
clonking
clonks
clons
clonus
clonuses
cloot
cloots
clop
clopped
clopping
clops
cloque
cloques
closable
close
closed
closely
closeout
closer
closers
closes
closest
closet
closeted
closets
closing
closings
closure
closured
closures
clot
cloth
clothe
clothed
clothes
clothier
clothing
cloths
clots
clotted
clotting
clotty
cloture
clotured
clotures
cloud
clouded
cloudier
cloudily
clouding
cloudlet
clouds
cloudy
clough
cloughs
clour
cloured
clouring
clours
clout
clouted
clouter
clouters
clouting
clouts
clove
cloven
clover
clovers
cloves
clowder
clowders
clown
clowned
clownery
clowning
clownish
clowns
cloy
cloyed
cloying
cloys
cloze
clozes
club
clubable
clubbed
clubber
clubbers
clubbier
clubbing
clubbish
clubby
clubfeet
clubfoot
clubhand
clubhaul
clubman
clubmen
clubroom
clubroot
clubs
cluck
clucked
clucking
clucks
clue
clued
clueing
clueless
clues
cluing
clumber
clumbers
clump
clumped
clumpier
clumping
clumpish
clumps
clumpy
clumsier
clumsily
clumsy
clung
clunk
clunked
clunker
clunkers
clunkier
clunking
clunks
clunky
clupeid
clupeids
clupeoid
cluster
clusters
clustery
clutch
clutched
clutches
clutchy
clutter
clutters
cluttery
clypeal
clypeate
clypei
clypeus
clyster
clysters
coach
coached
coacher
coachers
coaches
coaching
coachman
coachmen
coact
coacted
coacting
coaction
coactive
coactor
coactors
coacts
coadmire
coadmit
coadmits
coaeval
coaevals
coagency
coagent
coagents
coagula
coagulum
coal
coala
coalas
coalbin
coalbins
coalbox
coaled
coaler
coalers
coalesce
coalfish
coalhole
coalier
coaliest
coalify
coaling
coalless
coalpit
coalpits
coals
coalsack
coalshed
coaly
coalyard
coaming
coamings
coanchor
coannex
coappear
coapt
coapted
coapting
coapts
coarse
coarsely
coarsen
coarsens
coarser
coarsest
coassist
coassume
coast
coastal
coasted
coaster
coasters
coasting
coasts
coat
coated
coatee
coatees
coater
coaters
coati
coating
coatings
coatis
coatless
coatrack
coatroom
coats
coattail
coattend
coattest
coauthor
coax
coaxal
coaxed
coaxer
coaxers
coaxes
coaxial
coaxing
cob
cobalt
cobaltic
cobalts
cobb
cobber
cobbers
cobbier
cobbiest
cobble
cobbled
cobbler
cobblers
cobbles
cobbling
cobbs
cobby
cobia
cobias
coble
cobles
cobnut
cobnuts
cobra
cobras
cobs
cobweb
cobwebby
cobwebs
coca
cocain
cocaine
cocaines
cocains
cocas
coccal
cocci
coccic
coccid
coccidia
coccids
coccoid
coccoids
coccous
coccus
coccyges
coccyx
coccyxes
cochair
cochairs
cochin
cochins
cochlea
cochleae
cochlear
cochleas
cocinera
cock
cockade
cockaded
cockades
cockapoo
cockatoo
cockbill
cockboat
cockcrow
cocked
cocker
cockered
cockerel
cockers
cockeye
cockeyed
cockeyes
cockier
cockiest
cockily
cocking
cockish
cockle
cockled
cockles
cocklike
cockling
cockloft
cockney
cockneys
cockpit
cockpits
cocks
cockshut
cockshy
cockspur
cocksure
cocktail
cockup
cockups
cocky
coco
cocoa
cocoanut
cocoas
cocobola
cocobolo
cocomat
cocomats
coconut
coconuts
cocoon
cocooned
cocoons
cocos
cocotte
cocottes
cocoyam
cocoyams
cocreate
cod
coda
codable
codas
codded
codder
codders
codding
coddle
coddled
coddler
coddlers
coddles
coddling
code
codebook
codebtor
codec
codecs
coded
codeia
codeias
codein
codeina
codeinas
codeine
codeines
codeins
codeless
coden
codens
coder
coderive
coders
codes
codesign
codex
codfish
codger
codgers
codices
codicil
codicils
codified
codifier
codifies
codify
coding
codirect
codlin
codling
codlings
codlins
codon
codons
codpiece
codrive
codriven
codriver
codrives
codrove
cods
coed
coedit
coedited
coeditor
coedits
coeds
coeffect
coeliac
coelom
coelome
coelomes
coelomic
coeloms
coembody
coemploy
coempt
coempted
coempts
coenact
coenacts
coenamor
coendure
coenure
coenures
coenuri
coenurus
coenzyme
coequal
coequals
coequate
coerce
coerced
coercer
coercers
coerces
coercing
coercion
coercive
coerect
coerects
coesite
coesites
coeval
coevally
coevals
coevolve
coexert
coexerts
coexist
coexists
coextend
cofactor
coff
coffee
coffees
coffer
coffered
coffers
coffin
coffined
coffing
coffins
coffle
coffled
coffles
coffling
coffret
coffrets
coffs
cofound
cofounds
coft
cog
cogency
cogent
cogently
cogged
cogging
cogitate
cogito
cogitos
cognac
cognacs
cognate
cognates
cognise
cognised
cognises
cognize
cognized
cognizer
cognizes
cognomen
cognovit
cogon
cogons
cogs
cogway
cogways
cogwheel
cohabit
cohabits
cohead
coheaded
coheads
coheir
coheirs
cohere
cohered
coherent
coherer
coherers
coheres
cohering
cohesion
cohesive
coho
cohobate
cohog
cohogs
coholder
cohort
cohorts
cohos
cohosh
cohoshes
cohost
cohosted
cohosts
cohune
cohunes
coif
coifed
coiffe
coiffed
coiffes
coiffeur
coiffing
coiffure
coifing
coifs
coign
coigne
coigned
coignes
coigning
coigns
coil
coiled
coiler
coilers
coiling
coils
coin
coinable
coinage
coinages
coincide
coined
coiner
coiners
coinfer
coinfers
coinhere
coining
coinmate
coins
coinsure
cointer
cointers
coinvent
coir
coirs
coistrel
coistril
coital
coitally
coition
coitions
coitus
coituses
cojoin
cojoined
cojoins
coke
coked
cokehead
cokes
coking
col
cola
colander
colas
cold
coldcock
colder
coldest
coldish
coldly
coldness
colds
cole
colead
coleader
coleads
coled
coles
coleseed
coleslaw
colessee
colessor
coleus
coleuses
colewort
colic
colicin
colicine
colicins
colicky
colics
colies
coliform
colin
colinear
colins
coliseum
colistin
colitic
colitis
collage
collaged
collagen
collages
collapse
collar
collard
collards
collared
collaret
collars
collate
collated
collates
collator
collect
collects
colleen
colleens
college
colleger
colleges
collegia
collet
colleted
collets
collide
collided
collider
collides
collie
collied
collier
colliers
colliery
collies
collins
collogue
colloid
colloids
collop
collops
colloquy
collude
colluded
colluder
colludes
colluvia
colly
collying
collyria
colobi
coloboma
colobus
colocate
colog
cologne
cologned
colognes
cologs
colon
colone
colonel
colonels
colones
coloni
colonial
colonic
colonics
colonies
colonise
colonist
colonize
colons
colonus
colony
colophon
color
colorado
colorant
colored
coloreds
colorer
colorers
colorful
coloring
colorism
colorist
colorize
colorman
colormen
colors
colossal
colossi
colossus
colotomy
colour
coloured
colourer
colours
colpitis
cols
colt
colter
colters
coltish
colts
colubrid
colugo
colugos
columbic
columel
columels
column
columnal
columnar
columned
columns
colure
colures
coly
colza
colzas
coma
comade
comae
comake
comaker
comakers
comakes
comaking
comal
comanage
comas
comate
comates
comatic
comatik
comatiks
comatose
comatula
comb
combat
combated
combater
combats
combe
combed
comber
combers
combes
combine
combined
combiner
combines
combing
combings
comblike
combo
combos
combs
combust
combusts
come
comeback
comedian
comedic
comedies
comedo
comedos
comedown
comedy
comelier
comelily
comely
comember
comer
comers
comes
comet
cometary
cometh
comether
cometic
comets
comfier
comfiest
comfit
comfits
comfort
comforts
comfrey
comfreys
comfy
comic
comical
comics
coming
comingle
comings
comitia
comitial
comities
comity
comix
comma
command
commando
commands
commas
commata
commence
commend
commends
comment
comments
commerce
commie
commies
commit
commits
commix
commixed
commixes
commixt
commode
commodes
common
commoner
commonly
commons
commove
commoved
commoves
communal
commune
communed
communes
commute
commuted
commuter
commutes
commy
comose
comous
comp
compact
compacts
compadre
company
compare
compared
comparer
compares
compart
comparts
compass
comped
compeer
compeers
compel
compels
compend
compends
compere
compered
comperes
compete
competed
competes
compile
compiled
compiler
compiles
comping
complain
compleat
complect
complete
complex
complice
complied
complier
complies
complin
compline
complins
complot
complots
comply
compo
compone
compony
comport
comports
compos
compose
composed
composer
composes
compost
composts
compote
compotes
compound
compress
comprise
comprize
comps
compt
compted
compting
compts
compute
computed
computer
computes
comrade
comrades
comsymp
comsymps
comte
comtes
con
conation
conative
conatus
concave
concaved
concaves
conceal
conceals
concede
conceded
conceder
concedes
conceit
conceits
conceive
concent
concents
concept
concepts
concern
concerns
concert
concerti
concerto
concerts
conch
concha
conchae
conchal
conches
conchie
conchies
conchoid
conchs
conchy
concise
conciser
conclave
conclude
concoct
concocts
concord
concords
concrete
concur
concurs
concuss
condemn
condemns
condense
condign
condo
condoes
condole
condoled
condoler
condoles
condom
condoms
condone
condoned
condoner
condones
condor
condores
condors
condos
conduce
conduced
conducer
conduces
conduct
conducts
conduit
conduits
condylar
condyle
condyles
cone
coned
conelrad
conenose
conepate
conepatl
cones
coney
coneys
confab
confabs
confect
confects
confer
conferee
confers
conferva
confess
confetti
confetto
confide
confided
confider
confides
confine
confined
confiner
confines
confirm
confirms
confit
confits
conflate
conflict
conflux
confocal
conform
conforms
confound
confrere
confront
confuse
confused
confuses
confute
confuted
confuter
confutes
conga
congaed
congaing
congas
conge
congeal
congeals
congee
congeed
congees
congener
conger
congers
conges
congest
congests
congii
congius
conglobe
congo
congoes
congos
congou
congous
congrats
congress
coni
conic
conical
conicity
conics
conidia
conidial
conidian
conidium
conies
conifer
conifers
coniine
coniines
conin
conine
conines
coning
conins
conioses
coniosis
conium
coniums
conjoin
conjoins
conjoint
conjugal
conjunct
conjure
conjured
conjurer
conjures
conjuror
conk
conked
conker
conkers
conking
conks
conky
conn
connate
connect
connects
conned
conner
conners
conning
connive
connived
conniver
connives
connote
connoted
connotes
conns
conodont
conoid
conoidal
conoids
conquer
conquers
conquest
conquian
cons
consent
consents
conserve
consider
consign
consigns
consist
consists
consol
console
consoled
consoler
consoles
consols
consomme
consort
consorts
conspire
constant
construe
consul
consular
consuls
consult
consults
consume
consumed
consumer
consumes
contact
contacts
contagia
contain
contains
conte
contemn
contemns
contempt
contend
contends
content
contents
contes
contest
contests
context
contexts
continua
continue
continuo
conto
contort
contorts
contos
contour
contours
contra
contract
contrail
contrary
contras
contrast
contrite
contrive
control
controls
contuse
contused
contuses
conus
convect
convects
convene
convened
convener
convenes
convenor
convent
convents
converge
converse
convert
converts
convex
convexes
convexly
convey
conveyed
conveyer
conveyor
conveys
convict
convicts
convince
convoke
convoked
convoker
convokes
convolve
convoy
convoyed
convoys
convulse
cony
coo
cooch
cooches
coocoo
cooed
cooee
cooeed
cooeeing
cooees
cooer
cooers
cooey
cooeyed
cooeying
cooeys
coof
coofs
cooing
cooingly
cook
cookable
cookbook
cooked
cooker
cookers
cookery
cookey
cookeys
cookie
cookies
cooking
cookings
cookless
cookout
cookouts
cooks
cookshop
cooktop
cooktops
cookware
cooky
cool
coolant
coolants
cooldown
cooled
cooler
coolers
coolest
coolie
coolies
cooling
coolish
coolly
coolness
cools
coolth
coolths
cooly
coomb
coombe
coombes
coombs
coon
cooncan
cooncans
coons
coonskin
coontie
coonties
coop
cooped
cooper
coopered
coopers
coopery
cooping
coops
coopt
coopted
coopting
cooption
coopts
coos
coot
cooter
cooters
cootie
cooties
coots
cop
copaiba
copaibas
copal
copalm
copalms
copals
coparent
copastor
copatron
cope
copeck
copecks
coped
copemate
copen
copens
copepod
copepods
coper
copers
copes
copied
copier
copiers
copies
copihue
copihues
copilot
copilots
coping
copings
copious
coplanar
coplot
coplots
copped
copper
copperah
copperas
coppered
coppers
coppery
coppice
coppiced
coppices
copping
coppra
coppras
copra
coprah
coprahs
copras
copremia
copremic
coprince
cops
copse
copses
copter
copters
copula
copulae
copular
copulas
copulate
copurify
copy
copybook
copyboy
copyboys
copycat
copycats
copydesk
copyedit
copyhold
copying
copyist
copyists
copyread
coquet
coquetry
coquets
coquette
coquille
coquina
coquinas
coquito
coquitos
cor
coracle
coracles
coracoid
coral
corals
coranto
corantos
corban
corbans
corbeil
corbeils
corbel
corbeled
corbels
corbie
corbies
corbina
corbinas
corby
cord
cordage
cordages
cordate
corded
cordelle
corder
corders
cordial
cordials
cording
cordings
cordite
cordites
cordless
cordlike
cordoba
cordobas
cordon
cordoned
cordons
cordovan
cords
corduroy
cordwain
cordwood
core
cored
coredeem
coreign
coreigns
corelate
coreless
coremia
coremium
corer
corers
cores
corf
corgi
corgis
coria
coring
corium
cork
corkage
corkages
corked
corker
corkers
corkier
corkiest
corking
corklike
corks
corkwood
corky
corm
cormel
cormels
cormlike
cormoid
cormous
corms
corn
cornball
corncake
corncob
corncobs
corncrib
cornea
corneal
corneas
corned
cornel
cornels
corneous
corner
cornered
corners
cornet
cornetcy
cornets
cornfed
cornhusk
cornice
corniced
cornices
corniche
cornicle
cornier
corniest
cornily
corning
cornmeal
cornpone
cornrow
cornrows
corns
cornu
cornua
cornual
cornus
cornuses
cornute
cornuted
cornuto
cornutos
corny
corodies
corody
corolla
corollas
corona
coronach
coronae
coronal
coronals
coronary
coronas
coronate
coronel
coronels
coroner
coroners
coronet
coronets
coronoid
corotate
corpora
corporal
corps
corpse
corpses
corpsman
corpsmen
corpus
corrade
corraded
corrades
corral
corrals
correct
corrects
corrida
corridas
corridor
corrie
corries
corrival
corrode
corroded
corrodes
corrody
corrupt
corrupts
corsac
corsacs
corsage
corsages
corsair
corsairs
corse
corselet
corses
corset
corseted
corsetry
corsets
corslet
corslets
cortege
corteges
cortex
cortexes
cortical
cortices
cortin
cortins
cortisol
coruler
corulers
corundum
corvee
corvees
corves
corvet
corvets
corvette
corvina
corvinas
corvine
cory
corybant
corymb
corymbed
corymbs
coryphee
coryza
coryzal
coryzas
cos
coscript
cosec
cosecant
cosecs
coses
coset
cosets
cosey
coseys
cosh
coshed
cosher
coshered
coshers
coshes
coshing
cosie
cosied
cosier
cosies
cosiest
cosign
cosigned
cosigner
cosigns
cosily
cosine
cosines
cosiness
cosmetic
cosmic
cosmical
cosmism
cosmisms
cosmist
cosmists
cosmos
cosmoses
coss
cossack
cossacks
cosset
cosseted
cossets
cost
costa
costae
costal
costar
costard
costards
costars
costate
costed
coster
costers
costing
costive
costless
costlier
costly
costmary
costrel
costrels
costs
costume
costumed
costumer
costumes
costumey
cosy
cosying
cot
cotan
cotans
cote
coteau
coteaux
coted
cotenant
coterie
coteries
cotes
cothurn
cothurni
cothurns
cotidal
cotillon
coting
cotquean
cots
cotta
cottae
cottage
cottager
cottages
cottagey
cottar
cottars
cottas
cotter
cottered
cotters
cottier
cottiers
cotton
cottoned
cottons
cottony
cotyloid
cotype
cotypes
couch
couchant
couched
coucher
couchers
couches
couching
coude
cougar
cougars
cough
coughed
cougher
coughers
coughing
coughs
could
couldest
couldst
coulee
coulees
coulis
coulises
coulisse
couloir
couloirs
coulomb
coulombs
coulter
coulters
coumaric
coumarin
coumarou
council
councils
counsel
counsels
count
counted
counter
counters
countess
countian
counties
counting
country
counts
county
coup
coupe
couped
coupes
couping
couple
coupled
coupler
couplers
couples
couplet
couplets
coupling
coupon
coupons
coups
courage
courages
courant
courante
couranto
courants
courier
couriers
courlan
courlans
course
coursed
courser
coursers
courses
coursing
court
courted
courter
courters
courtesy
courtier
courting
courtly
courts
couscous
cousin
cousinly
cousinry
cousins
couteau
couteaux
couter
couters
couth
couther
couthest
couthie
couthier
couths
couture
coutures
couvade
couvades
covalent
cove
coved
coven
covenant
covens
cover
coverage
coverall
covered
coverer
coverers
covering
coverlet
coverlid
covers
covert
covertly
coverts
coverup
coverups
coves
covet
coveted
coveter
coveters
coveting
covetous
covets
covey
coveys
covin
coving
covings
covins
cow
cowage
cowages
coward
cowardly
cowards
cowbane
cowbanes
cowbell
cowbells
cowberry
cowbind
cowbinds
cowbird
cowbirds
cowboy
cowboys
cowed
cowedly
cower
cowered
cowering
cowers
cowfish
cowflap
cowflaps
cowflop
cowflops
cowgirl
cowgirls
cowhage
cowhages
cowhand
cowhands
cowherb
cowherbs
cowherd
cowherds
cowhide
cowhided
cowhides
cowier
cowiest
cowing
cowinner
cowl
cowled
cowlick
cowlicks
cowling
cowlings
cowls
cowman
cowmen
coworker
cowpat
cowpats
cowpea
cowpeas
cowpie
cowpies
cowplop
cowplops
cowpoke
cowpokes
cowpox
cowpoxes
cowrie
cowries
cowrite
cowrites
cowrote
cowry
cows
cowshed
cowsheds
cowskin
cowskins
cowslip
cowslips
cowy
cox
coxa
coxae
coxal
coxalgia
coxalgic
coxalgy
coxcomb
coxcombs
coxed
coxes
coxing
coxitis
coxswain
coy
coydog
coydogs
coyed
coyer
coyest
coying
coyish
coyly
coyness
coyote
coyotes
coypou
coypous
coypu
coypus
coys
coz
cozen
cozenage
cozened
cozener
cozeners
cozening
cozens
cozes
cozey
cozeys
cozie
cozied
cozier
cozies
coziest
cozily
coziness
cozy
cozying
cozzes
craal
craaled
craaling
craals
crab
crabbed
crabber
crabbers
crabbier
crabbily
crabbing
crabby
crabmeat
crabs
crabwise
crack
cracked
cracker
crackers
cracking
crackle
crackled
crackles
crackly
cracknel
crackpot
cracks
crackup
crackups
cracky
cradle
cradled
cradler
cradlers
cradles
cradling
craft
crafted
craftier
craftily
crafting
crafts
crafty
crag
cragged
craggier
craggily
craggy
crags
cragsman
cragsmen
crake
crakes
cram
crambe
crambes
crambo
cramboes
crambos
crammed
crammer
crammers
cramming
cramoisy
cramp
cramped
cramping
crampit
crampits
crampon
crampons
crampoon
cramps
crams
cranch
cranched
cranches
crane
craned
cranes
crania
cranial
craniate
craning
cranium
craniums
crank
cranked
cranker
crankest
crankier
crankily
cranking
crankish
crankle
crankled
crankles
crankly
crankous
crankpin
cranks
cranky
crannied
crannies
crannog
crannoge
crannogs
cranny
crap
crape
craped
crapes
craping
crapped
crapper
crappers
crappie
crappier
crappies
crapping
crappy
craps
crases
crash
crashed
crasher
crashers
crashes
crashing
crasis
crass
crasser
crassest
crassly
cratch
cratches
crate
crated
crater
cratered
craters
crates
crating
craton
cratonic
cratons
craunch
cravat
cravats
crave
craved
craven
cravened
cravenly
cravens
craver
cravers
craves
craving
cravings
craw
crawdad
crawdads
crawfish
crawl
crawled
crawler
crawlers
crawlier
crawling
crawls
crawlway
crawly
craws
crayfish
crayon
crayoned
crayons
craze
crazed
crazes
crazier
crazies
craziest
crazily
crazing
crazy
creak
creaked
creakier
creakily
creaking
creaks
creaky
cream
creamed
creamer
creamers
creamery
creamier
creamily
creaming
creams
creamy
crease
creased
creaser
creasers
creases
creasier
creasing
creasy
create
created
creates
creatin
creatine
creating
creatins
creation
creative
creator
creators
creature
creche
creches
credal
credence
credenda
credent
credenza
credible
credibly
credit
credited
creditor
credits
credo
credos
creed
creedal
creeds
creek
creeks
creel
creeled
creeling
creels
creep
creepage
creeper
creepers
creepie
creepier
creepies
creepily
creeping
creeps
creepy
creese
creeses
creesh
creeshed
creeshes
cremains
cremate
cremated
cremates
cremator
creme
cremes
crenate
crenated
crenel
creneled
crenelle
crenels
creodont
creole
creoles
creolise
creolize
creosol
creosols
creosote
crepe
creped
crepes
crepey
crepier
crepiest
creping
crepon
crepons
crept
crepy
crescent
crescive
cresol
cresols
cress
cresses
cresset
cressets
crest
crestal
crested
cresting
crests
cresyl
cresylic
cresyls
cretic
cretics
cretin
cretins
cretonne
crevalle
crevasse
crevice
creviced
crevices
crew
crewed
crewel
crewels
crewing
crewless
crewman
crewmate
crewmen
crewneck
crews
crib
cribbage
cribbed
cribber
cribbers
cribbing
cribbled
cribrous
cribs
cribwork
cricetid
crick
cricked
cricket
crickets
crickey
cricking
cricks
cricoid
cricoids
cried
crier
criers
cries
crikey
crime
crimes
criminal
crimmer
crimmers
crimp
crimped
crimper
crimpers
crimpier
crimping
crimple
crimpled
crimples
crimps
crimpy
crimson
crimsons
cringe
cringed
cringer
cringers
cringes
cringing
cringle
cringles
crinite
crinites
crinkle
crinkled
crinkles
crinkly
crinoid
crinoids
crinum
crinums
criollo
criollos
cripe
cripes
cripple
crippled
crippler
cripples
cris
crises
crisic
crisis
crisp
crispate
crisped
crispen
crispens
crisper
crispers
crispest
crispier
crispily
crisping
crisply
crisps
crispy
crissa
crissal
crissum
crista
cristae
cristate
criteria
critic
critical
critics
critique
critter
critters
crittur
critturs
croak
croaked
croaker
croakers
croakier
croakily
croaking
croaks
croaky
croc
crocein
croceine
croceins
crochet
crochets
croci
crocine
crock
crocked
crockery
crocket
crockets
crocking
crocks
crocoite
crocs
crocus
crocuses
croft
crofter
crofters
crofts
crojik
crojiks
cromlech
crone
crones
cronies
crony
cronyism
crook
crooked
crookery
crooking
crooks
croon
crooned
crooner
crooners
crooning
croons
crop
cropland
cropless
cropped
cropper
croppers
croppie
croppies
cropping
crops
croquet
croquets
croquis
crore
crores
crosier
crosiers
cross
crossarm
crossbar
crossbow
crosscut
crosse
crossed
crosser
crossers
crosses
crossest
crossing
crosslet
crossly
crosstie
crossway
crotch
crotched
crotches
crotchet
croton
crotons
crouch
crouched
crouches
croup
croupe
croupes
croupier
croupily
croupous
croups
croupy
crouse
crousely
crouton
croutons
crow
crowbar
crowbars
crowd
crowded
crowder
crowders
crowdie
crowdies
crowding
crowds
crowdy
crowed
crower
crowers
crowfeet
crowfoot
crowing
crown
crowned
crowner
crowners
crownet
crownets
crowning
crowns
crows
crowstep
croze
crozer
crozers
crozes
crozier
croziers
cruces
crucial
crucian
crucians
cruciate
crucible
crucifer
crucifix
crucify
cruck
crucks
crud
crudded
cruddier
crudding
cruddy
crude
crudely
cruder
crudes
crudest
crudites
crudity
cruds
cruel
crueler
cruelest
crueller
cruelly
cruelty
cruet
cruets
cruise
cruised
cruiser
cruisers
cruises
cruising
cruller
crullers
crumb
crumbed
crumber
crumbers
crumbier
crumbing
crumble
crumbled
crumbles
crumbly
crumbs
crumbum
crumbums
crumby
crumhorn
crummie
crummier
crummies
crummy
crump
crumped
crumpet
crumpets
crumping
crumple
crumpled
crumples
crumply
crumps
crunch
crunched
cruncher
crunches
crunchy
crunodal
crunode
crunodes
cruor
cruors
crupper
cruppers
crura
crural
crus
crusade
crusaded
crusader
crusades
crusado
crusados
cruse
cruses
cruset
crusets
crush
crushed
crusher
crushers
crushes
crushing
crusily
crust
crustal
crusted
crustier
crustily
crusting
crustose
crusts
crusty
crutch
crutched
crutches
crux
cruxes
cruzado
cruzados
cruzeiro
crwth
crwths
cry
crybaby
crying
cryingly
cryogen
cryogens
cryogeny
cryolite
cryonic
cryonics
cryostat
cryotron
crypt
cryptal
cryptic
crypto
cryptos
crypts
crystal
crystals
ctenidia
ctenoid
cub
cubage
cubages
cubature
cubbies
cubbish
cubby
cube
cubeb
cubebs
cubed
cuber
cubers
cubes
cubic
cubical
cubicity
cubicle
cubicles
cubicly
cubics
cubicula
cubiform
cubing
cubism
cubisms
cubist
cubistic
cubists
cubit
cubital
cubits
cuboid
cuboidal
cuboids
cubs
cuckold
cuckolds
cuckoo
cuckooed
cuckoos
cucumber
cucurbit
cud
cudbear
cudbears
cuddie
cuddies
cuddle
cuddled
cuddler
cuddlers
cuddles
cuddlier
cuddling
cuddly
cuddy
cudgel
cudgeled
cudgeler
cudgels
cuds
cudweed
cudweeds
cue
cued
cueing
cues
cuesta
cuestas
cuff
cuffed
cuffing
cuffless
cuffs
cuif
cuifs
cuing
cuirass
cuish
cuishes
cuisine
cuisines
cuisse
cuisses
cuittle
cuittled
cuittles
cuke
cukes
culch
culches
culet
culets
culex
culices
culicid
culicids
culicine
culinary
cull
cullay
cullays
culled
culler
cullers
cullet
cullets
cullied
cullies
culling
cullion
cullions
cullis
cullises
culls
cully
cullying
culm
culmed
culming
culms
culotte
culottes
culpa
culpable
culpably
culpae
culprit
culprits
cult
cultch
cultches
culti
cultic
cultigen
cultish
cultism
cultisms
cultist
cultists
cultivar
cultlike
cultrate
cults
cultural
culture
cultured
cultures
cultus
cultuses
culver
culverin
culvers
culvert
culverts
cum
cumarin
cumarins
cumber
cumbered
cumberer
cumbers
cumbrous
cumin
cumins
cummer
cummers
cummin
cummins
cumquat
cumquats
cumshaw
cumshaws
cumulate
cumuli
cumulous
cumulus
cundum
cundums
cuneal
cuneate
cuneated
cuneatic
cuniform
cunner
cunners
cunning
cunnings
cunt
cunts
cup
cupboard
cupcake
cupcakes
cupel
cupeled
cupeler
cupelers
cupeling
cupelled
cupeller
cupels
cupful
cupfuls
cupid
cupidity
cupids
cuplike
cupola
cupolaed
cupolas
cuppa
cuppas
cupped
cupper
cuppers
cuppier
cuppiest
cupping
cuppings
cuppy
cupreous
cupric
cuprite
cuprites
cuprous
cuprum
cuprums
cups
cupsful
cupula
cupulae
cupular
cupulate
cupule
cupules
cur
curable
curably
curacao
curacaos
curacies
curacoa
curacoas
curacy
curagh
curaghs
curara
curaras
curare
curares
curari
curarine
curaris
curarize
curassow
curate
curated
curates
curating
curative
curator
curators
curb
curbable
curbed
curber
curbers
curbing
curbings
curbs
curbside
curch
curches
curculio
curcuma
curcumas
curd
curded
curdier
curdiest
curding
curdle
curdled
curdler
curdlers
curdles
curdling
curds
curdy
cure
cured
cureless
curer
curers
cures
curet
curets
curette
curetted
curettes
curf
curfew
curfews
curfs
curia
curiae
curial
curie
curies
curing
curio
curios
curiosa
curious
curite
curites
curium
curiums
curl
curled
curler
curlers
curlew
curlews
curlicue
curlier
curliest
curlily
curling
curlings
curls
curly
curlycue
curn
curns
curr
currach
currachs
curragh
curraghs
curran
currans
currant
currants
curred
currency
current
currents
curricle
currie
curried
currier
curriers
curriery
curries
curring
currish
currs
curry
currying
curs
curse
cursed
curseder
cursedly
curser
cursers
curses
cursing
cursive
cursives
cursor
cursors
cursory
curst
curt
curtail
curtails
curtain
curtains
curtal
curtalax
curtals
curtate
curter
curtest
curtesy
curtly
curtness
curtsey
curtseys
curtsied
curtsies
curtsy
curule
curve
curved
curvedly
curves
curvet
curveted
curvets
curvey
curvier
curviest
curving
curvy
cuscus
cuscuses
cusec
cusecs
cushat
cushats
cushaw
cushaws
cushier
cushiest
cushily
cushion
cushions
cushiony
cushy
cusk
cusks
cusp
cuspate
cuspated
cusped
cuspid
cuspidal
cuspides
cuspidor
cuspids
cuspis
cusps
cuss
cussed
cussedly
cusser
cussers
cusses
cussing
cusso
cussos
cussword
custard
custards
custardy
custodes
custody
custom
customer
customs
custos
custumal
cut
cutaway
cutaways
cutback
cutbacks
cutbank
cutbanks
cutch
cutchery
cutches
cutdown
cutdowns
cute
cutely
cuteness
cuter
cutes
cutesie
cutesier
cutest
cutesy
cutey
cuteys
cutgrass
cuticle
cuticles
cuticula
cutie
cuties
cutin
cutinise
cutinize
cutins
cutis
cutises
cutlas
cutlases
cutlass
cutler
cutlers
cutlery
cutlet
cutlets
cutline
cutlines
cutoff
cutoffs
cutout
cutouts
cutover
cutovers
cutpurse
cuts
cuttable
cuttage
cuttages
cutter
cutters
cutties
cutting
cuttings
cuttle
cuttled
cuttles
cuttling
cutty
cutup
cutups
cutwater
cutwork
cutworks
cutworm
cutworms
cuvette
cuvettes
cwm
cwms
cyan
cyanamid
cyanate
cyanates
cyanic
cyanid
cyanide
cyanided
cyanides
cyanids
cyanin
cyanine
cyanines
cyanins
cyanite
cyanites
cyanitic
cyano
cyanogen
cyanosed
cyanoses
cyanosis
cyanotic
cyans
cyborg
cyborgs
cycad
cycads
cycas
cycases
cycasin
cycasins
cyclamen
cyclase
cyclases
cycle
cyclecar
cycled
cycler
cyclers
cyclery
cycles
cyclic
cyclical
cyclicly
cycling
cyclings
cyclist
cyclists
cyclitol
cyclize
cyclized
cyclizes
cyclo
cycloid
cycloids
cyclonal
cyclone
cyclones
cyclonic
cyclops
cyclos
cycloses
cyclosis
cyder
cyders
cyeses
cyesis
cygnet
cygnets
cylices
cylinder
cylix
cyma
cymae
cymar
cymars
cymas
cymatia
cymatium
cymbal
cymbaler
cymbalom
cymbals
cymbidia
cymbling
cyme
cymene
cymenes
cymes
cymlin
cymling
cymlings
cymlins
cymogene
cymoid
cymol
cymols
cymose
cymosely
cymous
cynic
cynical
cynicism
cynics
cynosure
cypher
cyphered
cyphers
cypres
cypreses
cypress
cyprian
cyprians
cyprinid
cyprus
cypruses
cypsela
cypselae
cyst
cystein
cysteine
cysteins
cystic
cystine
cystines
cystitis
cystoid
cystoids
cysts
cytaster
cytidine
cytogeny
cytokine
cytology
cyton
cytons
cytosine
cytosol
cytosols
czar
czardas
czardom
czardoms
czarevna
czarina
czarinas
czarism
czarisms
czarist
czarists
czaritza
czars
dab
dabbed
dabber
dabbers
dabbing
dabble
dabbled
dabbler
dabblers
dabbles
dabbling
dabchick
dabs
dabster
dabsters
dace
daces
dacha
dachas
dacker
dackered
dackers
dacoit
dacoits
dacoity
dactyl
dactyli
dactylic
dactyls
dactylus
dad
dada
dadaism
dadaisms
dadaist
dadaists
dadas
daddies
daddle
daddled
daddles
daddling
daddy
dado
dadoed
dadoes
dadoing
dados
dads
daedal
daemon
daemonic
daemons
daff
daffed
daffier
daffiest
daffily
daffing
daffodil
daffs
daffy
daft
dafter
daftest
daftly
daftness
dag
dagga
daggas
dagger
daggered
daggers
daggle
daggled
daggles
daggling
daglock
daglocks
dago
dagoba
dagobas
dagoes
dagos
dags
dagwood
dagwoods
dah
dahabeah
dahabiah
dahabieh
dahabiya
dahl
dahlia
dahlias
dahls
dahoon
dahoons
dahs
daiker
daikered
daikers
daikon
daikons
dailies
daily
daimen
daimio
daimios
daimon
daimones
daimonic
daimons
daimyo
daimyos
daintier
dainties
daintily
dainty
daiquiri
dairies
dairy
dairying
dairyman
dairymen
dais
daises
daishiki
daisied
daisies
daisy
dak
dakerhen
dakoit
dakoits
dakoity
daks
dal
dalapon
dalapons
dalasi
dalasis
dale
daledh
daledhs
dales
dalesman
dalesmen
daleth
daleths
dalles
dallied
dallier
dalliers
dallies
dally
dallying
dalmatic
dals
dalton
daltonic
daltons
dam
damage
damaged
damager
damagers
damages
damaging
daman
damans
damar
damars
damask
damasked
damasks
dame
dames
damewort
dammar
dammars
dammed
dammer
dammers
damming
damn
damnable
damnably
damndest
damned
damneder
damner
damners
damnify
damning
damns
damosel
damosels
damozel
damozels
damp
damped
dampen
dampened
dampener
dampens
damper
dampers
dampest
damping
dampings
dampish
damply
dampness
damps
dams
damsel
damsels
damson
damsons
dance
danced
dancer
dancers
dances
dancing
dander
dandered
danders
dandier
dandies
dandiest
dandify
dandily
dandle
dandled
dandler
dandlers
dandles
dandling
dandriff
dandruff
dandy
dandyish
dandyism
danegeld
daneweed
danewort
dang
danged
danger
dangered
dangers
danging
dangle
dangled
dangler
danglers
dangles
dangling
dangs
danio
danios
danish
dank
danker
dankest
dankly
dankness
danseur
danseurs
danseuse
dap
daphne
daphnes
daphnia
daphnias
dapped
dapper
dapperer
dapperly
dapping
dapple
dappled
dapples
dappling
daps
dapsone
dapsones
darb
darbies
darbs
dare
dared
dareful
darer
darers
dares
daresay
daric
darics
daring
daringly
darings
dariole
darioles
dark
darked
darken
darkened
darkener
darkens
darker
darkest
darkey
darkeys
darkie
darkies
darking
darkish
darkle
darkled
darkles
darklier
darkling
darkly
darkness
darkroom
darks
darksome
darky
darling
darlings
darn
darndest
darned
darneder
darnel
darnels
darner
darners
darning
darnings
darns
darshan
darshans
dart
darted
darter
darters
darting
dartle
dartled
dartles
dartling
darts
dash
dashed
dasheen
dasheens
dasher
dashers
dashes
dashi
dashier
dashiest
dashiki
dashikis
dashing
dashis
dashpot
dashpots
dashy
dassie
dassies
dastard
dastards
dasyure
dasyures
data
databank
database
datable
dataries
datary
datcha
datchas
date
dateable
dated
datedly
dateless
dateline
dater
daters
dates
dating
datival
dative
datively
datives
dato
datos
datto
dattos
datum
datums
datura
daturas
daturic
daub
daube
daubed
dauber
daubers
daubery
daubes
daubier
daubiest
daubing
daubries
daubry
daubs
dauby
daughter
daunder
daunders
daunt
daunted
daunter
daunters
daunting
daunts
dauphin
dauphine
dauphins
daut
dauted
dautie
dauties
dauting
dauts
daven
davened
davening
davens
davies
davit
davits
davy
daw
dawdle
dawdled
dawdler
dawdlers
dawdles
dawdling
dawed
dawen
dawing
dawk
dawks
dawn
dawned
dawning
dawnlike
dawns
daws
dawt
dawted
dawtie
dawties
dawting
dawts
day
daybed
daybeds
daybook
daybooks
daybreak
daydream
dayflies
dayfly
dayglow
dayglows
daylight
daylily
daylit
daylong
daymare
daymares
dayroom
dayrooms
days
dayside
daysides
daysman
daysmen
daystar
daystars
daytime
daytimes
daywork
dayworks
daze
dazed
dazedly
dazes
dazing
dazzle
dazzled
dazzler
dazzlers
dazzles
dazzling
de
deacon
deaconed
deaconry
deacons
dead
deadbeat
deadbolt
deaden
deadened
deadener
deadens
deader
deadest
deadeye
deadeyes
deadfall
deadhead
deadlier
deadlift
deadline
deadlock
deadly
deadness
deadpan
deadpans
deads
deadwood
deaerate
deaf
deafen
deafened
deafens
deafer
deafest
deafish
deafly
deafness
deair
deaired
deairing
deairs
deal
dealate
dealated
dealates
dealer
dealers
dealfish
dealing
dealings
deals
dealt
dean
deaned
deanery
deaning
deans
deanship
dear
dearer
dearest
dearie
dearies
dearly
dearness
dears
dearth
dearths
deary
deash
deashed
deashes
deashing
deasil
death
deathbed
deathcup
deathful
deathly
deaths
deathy
deave
deaved
deaves
deaving
deb
debacle
debacles
debar
debark
debarked
debarks
debarred
debars
debase
debased
debaser
debasers
debases
debasing
debate
debated
debater
debaters
debates
debating
debauch
debeak
debeaked
debeaks
debility
debit
debited
debiting
debits
debonair
debone
deboned
deboner
deboners
debones
deboning
debouch
debouche
debride
debrided
debrides
debrief
debriefs
debris
debruise
debs
debt
debtless
debtor
debtors
debts
debug
debugged
debugger
debugs
debunk
debunked
debunker
debunks
debut
debutant
debuted
debuting
debuts
debye
debyes
decadal
decade
decadent
decades
decaf
decafs
decagon
decagons
decagram
decal
decalog
decalogs
decals
decamp
decamped
decamps
decanal
decane
decanes
decant
decanted
decanter
decants
decapod
decapods
decare
decares
decay
decayed
decayer
decayers
decaying
decays
decease
deceased
deceases
decedent
deceit
deceits
deceive
deceived
deceiver
deceives
decemvir
decenary
decency
decennia
decent
decenter
decently
decentre
decern
decerned
decerns
deciare
deciares
decibel
decibels
decide
decided
decider
deciders
decides
deciding
decidua
deciduae
decidual
deciduas
decigram
decile
deciles
decimal
decimals
decimate
decipher
decision
decisive
deck
decked
deckel
deckels
decker
deckers
deckhand
decking
deckings
deckle
deckles
decks
declaim
declaims
declare
declared
declarer
declares
declass
declasse
declaw
declawed
declaws
decline
declined
decliner
declines
deco
decoct
decocted
decocts
decode
decoded
decoder
decoders
decodes
decoding
decolor
decolors
decolour
decor
decorate
decorous
decors
decorum
decorums
decos
decouple
decoy
decoyed
decoyer
decoyers
decoying
decoys
decrease
decree
decreed
decreer
decreers
decrees
decrepit
decretal
decrial
decrials
decried
decrier
decriers
decries
decrown
decrowns
decry
decrying
decrypt
decrypts
decuman
decuple
decupled
decuples
decuries
decurion
decurve
decurved
decurves
decury
dedal
dedans
dedicate
deduce
deduced
deduces
deducing
deduct
deducted
deducts
dee
deed
deeded
deedier
deediest
deeding
deedless
deeds
deedy
deejay
deejays
deem
deemed
deeming
deems
deemster
deep
deepen
deepened
deepener
deepens
deeper
deepest
deeply
deepness
deeps
deer
deerfly
deerlike
deers
deerskin
deerweed
deeryard
dees
deet
deets
deewan
deewans
deface
defaced
defacer
defacers
defaces
defacing
defame
defamed
defamer
defamers
defames
defaming
defang
defanged
defangs
defat
defats
defatted
default
defaults
defeat
defeated
defeater
defeats
defecate
defect
defected
defector
defects
defence
defences
defend
defended
defender
defends
defense
defensed
defenses
defer
deferent
deferral
deferred
deferrer
defers
defi
defiance
defiant
deficit
deficits
defied
defier
defiers
defies
defilade
defile
defiled
defiler
defilers
defiles
defiling
define
defined
definer
definers
defines
defining
definite
defis
deflate
deflated
deflater
deflates
deflator
deflea
defleaed
defleas
deflect
deflects
deflexed
deflower
defoam
defoamed
defoamer
defoams
defocus
defog
defogged
defogger
defogs
deforce
deforced
deforces
deforest
deform
deformed
deformer
deforms
defraud
defrauds
defray
defrayal
defrayed
defrayer
defrays
defrock
defrocks
defrost
defrosts
deft
defter
deftest
deftly
deftness
defunct
defund
defunded
defunds
defuse
defused
defuses
defusing
defuze
defuzed
defuzes
defuzing
defy
defying
degage
degame
degames
degami
degamis
degas
degases
degassed
degasser
degasses
degauss
degerm
degermed
degerms
deglaze
deglazed
deglazes
degrade
degraded
degrader
degrades
degrease
degree
degreed
degrees
degum
degummed
degums
degust
degusted
degusts
dehisce
dehisced
dehisces
dehorn
dehorned
dehorner
dehorns
dehort
dehorted
dehorts
deice
deiced
deicer
deicers
deices
deicidal
deicide
deicides
deicing
deictic
deific
deifical
deified
deifier
deifiers
deifies
deiform
deify
deifying
deign
deigned
deigning
deigns
deil
deils
deionize
deism
deisms
deist
deistic
deists
deities
deity
deixis
deixises
deject
dejecta
dejected
dejects
dejeuner
dekagram
dekare
dekares
deke
deked
dekes
deking
dekko
dekkos
del
delaine
delaines
delate
delated
delates
delating
delation
delator
delators
delay
delayed
delayer
delayers
delaying
delays
dele
delead
deleaded
deleads
deleave
deleaved
deleaves
deled
delegacy
delegate
deleing
deles
delete
deleted
deletes
deleting
deletion
delf
delfs
delft
delfts
deli
delicacy
delicate
delict
delicts
delight
delights
delime
delimed
delimes
deliming
delimit
delimits
deliria
delirium
delis
delist
delisted
delists
deliver
delivers
delivery
dell
dellies
dells
delly
delouse
deloused
delouser
delouses
delphic
dels
delta
deltaic
deltas
deltic
deltoid
deltoids
delude
deluded
deluder
deluders
deludes
deluding
deluge
deluged
deluges
deluging
delusion
delusive
delusory
deluster
deluxe
delve
delved
delver
delvers
delves
delving
demagog
demagogs
demagogy
demand
demanded
demander
demands
demarche
demark
demarked
demarks
demast
demasted
demasts
deme
demean
demeaned
demeanor
demeans
dement
demented
dementia
dements
demerara
demerge
demerged
demerger
demerges
demerit
demerits
demersal
demes
demesne
demesnes
demeton
demetons
demies
demigod
demigods
demijohn
demilune
demirep
demireps
demise
demised
demises
demising
demit
demits
demitted
demiurge
demivolt
demo
demob
demobbed
demobs
democrat
demode
demoded
demolish
demon
demoness
demoniac
demonian
demonic
demonise
demonism
demonist
demonize
demons
demos
demoses
demote
demoted
demotes
demotic
demotics
demoting
demotion
demotist
demount
demounts
dempster
demur
demure
demurely
demurer
demurest
demurral
demurred
demurrer
demurs
demy
den
denarii
denarius
denary
denature
denazify
dendrite
dendroid
dendron
dendrons
dene
denes
dengue
dengues
deniable
deniably
denial
denials
denied
denier
deniers
denies
denim
denims
denizen
denizens
denned
denning
denote
denoted
denotes
denoting
denotive
denounce
dens
dense
densely
denser
densest
densify
density
dent
dental
dentalia
dentally
dentals
dentate
dentated
dented
denticle
dentil
dentiled
dentils
dentin
dentinal
dentine
dentines
denting
dentins
dentist
dentists
dentoid
dents
dentural
denture
dentures
denudate
denude
denuded
denuder
denuders
denudes
denuding
deny
denying
deodand
deodands
deodar
deodara
deodaras
deodars
deontic
deorbit
deorbits
deoxy
depaint
depaints
depart
departed
departee
departs
depend
depended
depends
deperm
depermed
deperms
depict
depicted
depicter
depictor
depicts
depilate
deplane
deplaned
deplanes
deplete
depleted
depletes
deplore
deplored
deplorer
deplores
deploy
deployed
deploys
deplume
deplumed
deplumes
depolish
depone
deponed
deponent
depones
deponing
deport
deported
deportee
deports
deposal
deposals
depose
deposed
deposer
deposers
deposes
deposing
deposit
deposits
depot
depots
deprave
depraved
depraver
depraves
depress
deprival
deprive
deprived
depriver
deprives
depside
depsides
depth
depths
depurate
depute
deputed
deputes
deputies
deputing
deputize
deputy
deraign
deraigns
derail
derailed
derails
derange
deranged
deranges
derat
derate
derated
derates
derating
derats
deratted
deray
derays
derbies
derby
dere
derelict
deride
derided
derider
deriders
derides
deriding
deringer
derision
derisive
derisory
derivate
derive
derived
deriver
derivers
derives
deriving
derm
derma
dermal
dermas
dermic
dermis
dermises
dermoid
dermoids
derms
dernier
derogate
derrick
derricks
derriere
derries
derris
derrises
derry
dervish
desalt
desalted
desalter
desalts
desand
desanded
desands
descant
descants
descend
descends
descent
descents
describe
descried
descrier
descries
descry
deselect
desert
deserted
deserter
desertic
deserts
deserve
deserved
deserver
deserves
desex
desexed
desexes
desexing
design
designed
designee
designer
designs
desilver
desinent
desire
desired
desirer
desirers
desires
desiring
desirous
desist
desisted
desists
desk
deskman
deskmen
desks
desktop
desktops
desman
desmans
desmid
desmids
desmoid
desmoids
desolate
desorb
desorbed
desorbs
desoxy
despair
despairs
despatch
despise
despised
despiser
despises
despite
despited
despites
despoil
despoils
despond
desponds
despot
despotic
despots
dessert
desserts
destain
destains
destine
destined
destines
destiny
destrier
destroy
destroys
destruct
desugar
desugars
desulfur
detach
detached
detacher
detaches
detail
detailed
detailer
details
detain
detained
detainee
detainer
detains
detassel
detect
detected
detecter
detector
detects
detent
detente
detentes
detents
deter
deterge
deterged
deterger
deterges
deterred
deterrer
deters
detest
detested
detester
detests
dethrone
detick
deticked
deticker
deticks
detinue
detinues
detonate
detour
detoured
detours
detox
detoxed
detoxes
detoxify
detoxing
detract
detracts
detrain
detrains
detrital
detritus
detrude
detruded
detrudes
deuce
deuced
deucedly
deuces
deucing
deuteric
deuteron
deutzia
deutzias
dev
deva
devalue
devalued
devalues
devas
devein
deveined
deveins
devel
develed
develing
develop
develope
develops
devels
deverbal
devest
devested
devests
deviance
deviancy
deviant
deviants
deviate
deviated
deviates
deviator
device
devices
devil
deviled
deviling
devilish
devilkin
devilled
devilry
devils
deviltry
devious
devisal
devisals
devise
devised
devisee
devisees
deviser
devisers
devises
devising
devisor
devisors
devoice
devoiced
devoices
devoid
devoir
devoirs
devolve
devolved
devolves
devon
devons
devote
devoted
devotee
devotees
devotes
devoting
devotion
devour
devoured
devourer
devours
devout
devouter
devoutly
devs
dew
dewan
dewans
dewar
dewars
dewater
dewaters
dewax
dewaxed
dewaxes
dewaxing
dewberry
dewclaw
dewclaws
dewdrop
dewdrops
dewed
dewfall
dewfalls
dewier
dewiest
dewily
dewiness
dewing
dewlap
dewlaps
dewless
dewool
dewooled
dewools
deworm
dewormed
dewormer
deworms
dews
dewy
dex
dexes
dexie
dexies
dexter
dextral
dextran
dextrans
dextrin
dextrine
dextrins
dextro
dextrose
dextrous
dexy
dey
deys
dezinc
dezinced
dezincs
dhak
dhaks
dhal
dhals
dharma
dharmas
dharmic
dharna
dharnas
dhobi
dhobis
dhole
dholes
dhoolies
dhooly
dhoora
dhooras
dhooti
dhootie
dhooties
dhootis
dhoti
dhotis
dhourra
dhourras
dhow
dhows
dhurna
dhurnas
dhurrie
dhurries
dhuti
dhutis
diabase
diabases
diabasic
diabetes
diabetic
diablery
diabolic
diabolo
diabolos
diacetyl
diacid
diacidic
diacids
diaconal
diadem
diademed
diadems
diagnose
diagonal
diagram
diagrams
diagraph
dial
dialect
dialects
dialed
dialer
dialers
dialing
dialings
dialist
dialists
diallage
dialled
diallel
dialler
diallers
dialling
diallist
dialog
dialoged
dialoger
dialogic
dialogs
dialogue
dials
dialyse
dialysed
dialyser
dialyses
dialysis
dialytic
dialyze
dialyzed
dialyzer
dialyzes
diamante
diameter
diamide
diamides
diamin
diamine
diamines
diamins
diamond
diamonds
dianthus
diapason
diapause
diaper
diapered
diapers
diaphone
diaphony
diapir
diapiric
diapirs
diapsid
diarchic
diarchy
diaries
diarist
diarists
diarrhea
diary
diaspora
diaspore
diastase
diastem
diastema
diastems
diaster
diasters
diastole
diastral
diatom
diatomic
diatoms
diatonic
diatribe
diatron
diatrons
diazepam
diazin
diazine
diazines
diazinon
diazins
diazo
diazole
diazoles
dib
dibasic
dibbed
dibber
dibbers
dibbing
dibble
dibbled
dibbler
dibblers
dibbles
dibbling
dibbuk
dibbukim
dibbuks
dibs
dicast
dicastic
dicasts
dice
diced
dicentra
dicer
dicers
dices
dicey
dichasia
dichotic
dichroic
dicier
diciest
dicing
dick
dicked
dickens
dicker
dickered
dickers
dickey
dickeys
dickie
dickier
dickies
dickiest
dicking
dicks
dicky
dicliny
dicot
dicots
dicotyl
dicotyls
dicrotal
dicrotic
dicta
dictate
dictated
dictates
dictator
dictier
dictiest
diction
dictions
dictum
dictums
dicty
dicyclic
dicycly
did
didact
didactic
didacts
didactyl
didapper
diddle
diddled
diddler
diddlers
diddles
diddley
diddleys
diddlies
diddling
diddly
didie
didies
dido
didoes
didos
didst
didy
didymium
didymous
didynamy
die
dieback
diebacks
diecious
died
diehard
diehards
dieing
diel
dieldrin
diemaker
diene
dienes
diereses
dieresis
dieretic
dies
diesel
dieseled
diesels
dieses
diesis
diester
diesters
diestock
diestrum
diestrus
diet
dietary
dieted
dieter
dieters
dietetic
diether
diethers
dieting
diets
differ
differed
differs
diffract
diffuse
diffused
diffuser
diffuses
diffusor
dig
digamies
digamist
digamma
digammas
digamous
digamy
digest
digested
digester
digestor
digests
digged
digger
diggers
digging
diggings
dight
dighted
dighting
dights
digit
digital
digitals
digitate
digitize
digits
diglot
diglots
dignify
dignity
digoxin
digoxins
digraph
digraphs
digress
digs
dihedral
dihedron
dihybrid
dihydric
dikdik
dikdiks
dike
diked
diker
dikers
dikes
dikey
diking
diktat
diktats
dilatant
dilatate
dilate
dilated
dilater
dilaters
dilates
dilating
dilation
dilative
dilator
dilators
dilatory
dildo
dildoe
dildoes
dildos
dilemma
dilemmas
dilemmic
diligent
dill
dilled
dillies
dills
dilly
diluent
diluents
dilute
diluted
diluter
diluters
dilutes
diluting
dilution
dilutive
dilutor
dilutors
diluvia
diluvial
diluvian
diluvion
diluvium
dim
dime
dimer
dimeric
dimerism
dimerize
dimerous
dimers
dimes
dimeter
dimeters
dimethyl
dimetric
diminish
dimities
dimity
dimly
dimmable
dimmed
dimmer
dimmers
dimmest
dimming
dimness
dimorph
dimorphs
dimout
dimouts
dimple
dimpled
dimples
dimplier
dimpling
dimply
dims
dimwit
dimwits
din
dinar
dinars
dindle
dindled
dindles
dindling
dine
dined
diner
dineric
dinero
dineros
diners
dines
dinette
dinettes
ding
dingbat
dingbats
dingdong
dinge
dinged
dinger
dingers
dinges
dingey
dingeys
dinghies
dinghy
dingier
dingies
dingiest
dingily
dinging
dingle
dingles
dingo
dingoes
dings
dingus
dinguses
dingy
dining
dinitro
dink
dinked
dinkey
dinkeys
dinkier
dinkies
dinkiest
dinking
dinkly
dinks
dinkum
dinkums
dinky
dinned
dinner
dinners
dinning
dinosaur
dins
dint
dinted
dinting
dints
diobol
diobolon
diobols
diocesan
diocese
dioceses
diode
diodes
dioecies
dioecism
dioecy
dioicous
diol
diolefin
diols
diopside
dioptase
diopter
diopters
dioptral
dioptre
dioptres
dioptric
diorama
dioramas
dioramic
diorite
diorites
dioritic
dioxan
dioxane
dioxanes
dioxans
dioxid
dioxide
dioxides
dioxids
dioxin
dioxins
dip
diphase
diphasic
diphenyl
diplegia
diplex
diplexer
diploe
diploes
diploic
diploid
diploids
diploidy
diploma
diplomas
diplomat
diplont
diplonts
diplopia
diplopic
diplopod
diploses
diplosis
dipnet
dipnets
dipnoan
dipnoans
dipodic
dipodies
dipody
dipolar
dipole
dipoles
dippable
dipped
dipper
dippers
dippier
dippiest
dipping
dippy
dips
dipsades
dipsas
dipso
dipsos
dipstick
dipt
diptera
dipteral
dipteran
dipteron
diptyca
diptycas
diptych
diptychs
diquat
diquats
dirdum
dirdums
dire
direct
directed
directer
directly
director
directs
direful
direly
direness
direr
direst
dirge
dirgeful
dirges
dirham
dirhams
diriment
dirk
dirked
dirking
dirks
dirl
dirled
dirling
dirls
dirndl
dirndls
dirt
dirtbag
dirtbags
dirtied
dirtier
dirties
dirtiest
dirtily
dirts
dirty
dirtying
dis
disable
disabled
disables
disabuse
disagree
disallow
disannul
disarm
disarmed
disarmer
disarms
disarray
disaster
disavow
disavows
disband
disbands
disbar
disbars
disbosom
disbound
disbowel
disbud
disbuds
disburse
disc
discant
discants
discard
discards
discase
discased
discases
disced
discept
discepts
discern
discerns
disci
discing
disciple
disclaim
disclike
disclose
disco
discoed
discoid
discoids
discoing
discolor
discord
discords
discos
discount
discover
discreet
discrete
discrown
discs
discus
discuses
discuss
disdain
disdains
disease
diseased
diseases
disendow
diseuse
diseuses
disfavor
disfrock
disgorge
disgrace
disguise
disgust
disgusts
dish
dished
dishelm
dishelms
disherit
dishes
dishevel
dishful
dishfuls
dishier
dishiest
dishing
dishlike
dishonor
dishpan
dishpans
dishrag
dishrags
dishware
dishy
disinter
disject
disjects
disjoin
disjoins
disjoint
disjunct
disk
disked
diskette
disking
disklike
disks
dislike
disliked
disliker
dislikes
dislimn
dislimns
dislodge
disloyal
dismal
dismaler
dismally
dismals
dismast
dismasts
dismay
dismayed
dismays
disme
dismes
dismiss
dismount
disobey
disobeys
disomic
disorder
disown
disowned
disowns
dispart
disparts
dispatch
dispel
dispels
dispend
dispends
dispense
disperse
dispirit
displace
displant
display
displays
displode
displume
disport
disports
disposal
dispose
disposed
disposer
disposes
dispread
disprize
disproof
disprove
dispute
disputed
disputer
disputes
disquiet
disrate
disrated
disrates
disrobe
disrobed
disrober
disrobes
disroot
disroots
disrupt
disrupts
diss
dissave
dissaved
dissaves
disseat
disseats
dissect
dissects
dissed
disseise
disseize
dissent
dissents
dissert
disserts
disserve
disses
dissever
dissing
dissolve
dissuade
distaff
distaffs
distain
distains
distal
distally
distance
distant
distaste
distaves
distend
distends
distent
distich
distichs
distil
distill
distills
distils
distinct
distome
distomes
distort
distorts
distract
distrain
distrait
distress
district
distrust
disturb
disturbs
disulfid
disunion
disunite
disunity
disuse
disused
disuses
disusing
disvalue
disyoke
disyoked
disyokes
dit
dita
ditas
ditch
ditched
ditcher
ditchers
ditches
ditching
dite
dites
ditheism
ditheist
dither
dithered
ditherer
dithers
dithery
dithiol
dits
ditsier
ditsiest
ditsy
dittany
ditties
ditto
dittoed
dittoing
dittos
ditty
ditz
ditzes
ditzier
ditziest
ditzy
diureses
diuresis
diuretic
diurnal
diurnals
diuron
diurons
diva
divagate
divalent
divan
divans
divas
dive
divebomb
dived
diver
diverge
diverged
diverges
divers
diverse
divert
diverted
diverter
diverts
dives
divest
divested
divests
divide
divided
dividend
divider
dividers
divides
dividing
dividual
divine
divined
divinely
diviner
diviners
divines
divinest
diving
divining
divinise
divinity
divinize
division
divisive
divisor
divisors
divorce
divorced
divorcee
divorcer
divorces
divot
divots
divulge
divulged
divulger
divulges
divvied
divvies
divvy
divvying
diwan
diwans
dixit
dixits
dizen
dizened
dizening
dizens
dizygous
dizzied
dizzier
dizzies
dizziest
dizzily
dizzy
dizzying
djebel
djebels
djellaba
djin
djinn
djinni
djinns
djinny
djins
do
doable
doat
doated
doating
doats
dobber
dobbers
dobbies
dobbin
dobbins
dobby
dobie
dobies
dobla
doblas
doblon
doblones
doblons
dobra
dobras
dobson
dobsons
doby
doc
docent
docents
docetic
docile
docilely
docility
dock
dockage
dockages
docked
docker
dockers
docket
docketed
dockets
dockhand
docking
dockland
docks
dockside
dockyard
docs
doctor
doctoral
doctored
doctors
doctrine
document
dodder
doddered
dodderer
dodders
doddery
dodge
dodged
dodgem
dodgems
dodger
dodgers
dodgery
dodges
dodgier
dodgiest
dodging
dodgy
dodo
dodoes
dodoism
dodoisms
dodos
doe
doer
doers
does
doeskin
doeskins
doest
doeth
doff
doffed
doffer
doffers
doffing
doffs
dog
dogbane
dogbanes
dogberry
dogcart
dogcarts
dogdom
dogdoms
doge
dogear
dogeared
dogears
dogedom
dogedoms
doges
dogeship
dogey
dogeys
dogface
dogfaces
dogfight
dogfish
dogged
doggedly
dogger
doggerel
doggers
doggery
doggie
doggier
doggies
doggiest
dogging
doggish
doggo
doggone
doggoned
doggoner
doggones
doggrel
doggrels
doggy
doghouse
dogie
dogies
dogleg
doglegs
doglike
dogma
dogmas
dogmata
dogmatic
dognap
dognaped
dognaper
dognaps
dogs
dogsbody
dogsled
dogsleds
dogteeth
dogtooth
dogtrot
dogtrots
dogvane
dogvanes
dogwatch
dogwood
dogwoods
dogy
doiled
doilies
doily
doing
doings
doit
doited
doits
dojo
dojos
dol
dolce
dolci
doldrums
dole
doled
doleful
dolerite
doles
dolesome
doling
doll
dollar
dollars
dolled
dollied
dollies
dolling
dollish
dollop
dolloped
dollops
dolls
dolly
dollying
dolma
dolmades
dolman
dolmans
dolmas
dolmen
dolmens
dolomite
dolor
doloroso
dolorous
dolors
dolour
dolours
dolphin
dolphins
dols
dolt
doltish
dolts
dom
domain
domains
domal
dome
domed
domelike
domes
domesday
domestic
domic
domical
domicil
domicile
domicils
dominant
dominate
domine
domineer
domines
doming
dominick
dominie
dominies
dominion
dominium
domino
dominoes
dominos
doms
don
dona
donas
donate
donated
donates
donating
donation
donative
donator
donators
done
donee
donees
doneness
dong
donga
dongas
dongola
dongolas
dongs
donjon
donjons
donkey
donkeys
donna
donnas
donne
donned
donnee
donnees
donnerd
donnered
donnert
donniker
donning
donnish
donor
donors
dons
donsie
donsy
donut
donuts
donzel
donzels
doodad
doodads
doodle
doodled
doodler
doodlers
doodles
doodling
doofus
doofuses
doolee
doolees
doolie
doolies
dooly
doom
doomed
doomful
doomily
dooming
dooms
doomsday
doomster
doomy
door
doorbell
doorjamb
doorknob
doorless
doorman
doormat
doormats
doormen
doornail
doorpost
doors
doorsill
doorstep
doorstop
doorway
doorways
dooryard
doozer
doozers
doozie
doozies
doozy
dopa
dopamine
dopant
dopants
dopas
dope
doped
dopehead
doper
dopers
dopes
dopester
dopey
dopier
dopiest
dopiness
doping
dopy
dor
dorado
dorados
dorbug
dorbugs
dore
dorhawk
dorhawks
dories
dork
dorkier
dorkiest
dorks
dorky
dorm
dormancy
dormant
dormer
dormers
dormice
dormie
dormient
dormin
dormins
dormouse
dorms
dormy
dorneck
dornecks
dornick
dornicks
dornock
dornocks
dorp
dorper
dorpers
dorps
dorr
dorrs
dors
dorsa
dorsad
dorsal
dorsally
dorsals
dorsel
dorsels
dorser
dorsers
dorsum
dorty
dory
dos
dosage
dosages
dose
dosed
doser
dosers
doses
dosing
doss
dossal
dossals
dossed
dossel
dossels
dosser
dosseret
dossers
dosses
dossier
dossiers
dossil
dossils
dossing
dost
dot
dotage
dotages
dotal
dotard
dotardly
dotards
dotation
dote
doted
doter
doters
dotes
doth
dotier
dotiest
doting
dotingly
dots
dotted
dottel
dottels
dotter
dotterel
dotters
dottier
dottiest
dottily
dotting
dottle
dottles
dottrel
dottrels
dotty
doty
double
doubled
doubler
doublers
doubles
doublet
doublets
doubling
doubloon
doublure
doubly
doubt
doubted
doubter
doubters
doubtful
doubting
doubts
douce
doucely
douceur
douceurs
douche
douched
douches
douching
dough
doughboy
doughier
doughnut
doughs
dought
doughty
doughy
doum
douma
doumas
doums
doupioni
dour
doura
dourah
dourahs
douras
dourer
dourest
dourine
dourines
dourly
dourness
douse
doused
douser
dousers
douses
dousing
doux
douzeper
dove
dovecot
dovecote
dovecots
dovekey
dovekeys
dovekie
dovekies
dovelike
doven
dovened
dovening
dovens
doves
dovetail
dovish
dow
dowable
dowager
dowagers
dowdier
dowdies
dowdiest
dowdily
dowdy
dowdyish
dowed
dowel
doweled
doweling
dowelled
dowels
dower
dowered
doweries
dowering
dowers
dowery
dowie
dowing
down
downbeat
downcast
downcome
downed
downer
downers
downfall
downhaul
downhill
downier
downiest
downing
downland
downlink
download
downpipe
downplay
downpour
downs
downside
downsize
downtick
downtime
downtown
downtrod
downturn
downward
downwash
downwind
downy
dowries
dowry
dows
dowsabel
dowse
dowsed
dowser
dowsers
dowses
dowsing
doxie
doxies
doxology
doxy
doyen
doyenne
doyennes
doyens
doyley
doyleys
doylies
doyly
doze
dozed
dozen
dozened
dozening
dozens
dozenth
dozenths
dozer
dozers
dozes
dozier
doziest
dozily
doziness
dozing
dozy
drab
drabbed
drabber
drabbest
drabbet
drabbets
drabbing
drabble
drabbled
drabbles
drably
drabness
drabs
dracaena
drachm
drachma
drachmae
drachmai
drachmas
drachms
draconic
draff
draffier
draffish
draffs
draffy
draft
drafted
draftee
draftees
drafter
drafters
draftier
draftily
drafting
drafts
drafty
drag
dragee
dragees
dragged
dragger
draggers
draggier
dragging
draggle
draggled
draggles
draggy
dragline
dragnet
dragnets
dragoman
dragomen
dragon
dragonet
dragons
dragoon
dragoons
dragrope
drags
dragster
drail
drails
drain
drainage
drained
drainer
drainers
draining
drains
drake
drakes
dram
drama
dramas
dramatic
dramedy
drammed
dramming
drammock
drams
dramshop
drank
drapable
drape
draped
draper
drapers
drapery
drapes
drapey
draping
drastic
drat
drats
dratted
dratting
draught
draughts
draughty
drave
draw
drawable
drawback
drawbar
drawbars
drawbore
drawdown
drawee
drawees
drawer
drawers
drawing
drawings
drawl
drawled
drawler
drawlers
drawlier
drawling
drawls
drawly
drawn
draws
drawtube
dray
drayage
drayages
drayed
draying
drayman
draymen
drays
dread
dreaded
dreadful
dreading
dreads
dream
dreamed
dreamer
dreamers
dreamful
dreamier
dreamily
dreaming
dreams
dreamt
dreamy
drear
drearier
drearies
drearily
drears
dreary
dreck
drecks
drecky
dredge
dredged
dredger
dredgers
dredges
dredging
dree
dreed
dreeing
drees
dreg
dreggier
dreggish
dreggy
dregs
dreich
dreidel
dreidels
dreidl
dreidls
dreigh
drek
dreks
drench
drenched
drencher
drenches
dress
dressage
dressed
dresser
dressers
dresses
dressier
dressily
dressing
dressy
drest
drew
drib
dribbed
dribbing
dribble
dribbled
dribbler
dribbles
dribblet
dribbly
driblet
driblets
dribs
dried
driegh
drier
driers
dries
driest
drift
driftage
drifted
drifter
drifters
driftier
drifting
driftpin
drifts
drifty
drill
drilled
driller
drillers
drilling
drills
drily
drink
drinker
drinkers
drinking
drinks
drip
dripless
dripped
dripper
drippers
drippier
dripping
drippy
drips
dript
drivable
drive
drivel
driveled
driveler
drivels
driven
driver
drivers
drives
driveway
driving
drivings
drizzle
drizzled
drizzles
drizzly
drogue
drogues
droit
droits
droll
drolled
droller
drollery
drollest
drolling
drolls
drolly
dromon
dromond
dromonds
dromons
drone
droned
droner
droners
drones
drongo
drongos
droning
dronish
drool
drooled
drooling
drools
droop
drooped
droopier
droopily
drooping
droops
droopy
drop
drophead
dropkick
droplet
droplets
dropout
dropouts
dropped
dropper
droppers
dropping
drops
dropshot
dropsied
dropsies
dropsy
dropt
dropwort
drosera
droseras
droshky
droskies
drosky
dross
drosses
drossier
drossy
drought
droughts
droughty
drouk
drouked
drouking
drouks
drouth
drouths
drouthy
drove
droved
drover
drovers
droves
droving
drown
drownd
drownded
drownds
drowned
drowner
drowners
drowning
drowns
drowse
drowsed
drowses
drowsier
drowsily
drowsing
drowsy
drub
drubbed
drubber
drubbers
drubbing
drubs
drudge
drudged
drudger
drudgers
drudgery
drudges
drudging
drug
drugged
drugget
druggets
druggie
druggier
druggies
drugging
druggist
druggy
drugs
druid
druidess
druidic
druidism
druids
drum
drumbeat
drumble
drumbled
drumbles
drumfire
drumfish
drumhead
drumlier
drumlike
drumlin
drumlins
drumly
drummed
drummer
drummers
drumming
drumroll
drums
drunk
drunkard
drunken
drunker
drunkest
drunks
drupe
drupelet
drupes
druse
druses
druthers
dry
dryable
dryad
dryades
dryadic
dryads
dryer
dryers
dryest
drying
dryish
dryland
drylot
drylots
dryly
dryness
drypoint
drys
drystone
drywall
drywalls
duad
duads
dual
dualism
dualisms
dualist
dualists
duality
dualize
dualized
dualizes
dually
duals
dub
dubbed
dubber
dubbers
dubbin
dubbing
dubbings
dubbins
dubiety
dubious
dubonnet
dubs
ducal
ducally
ducat
ducats
duce
duces
duchess
duchies
duchy
duci
duck
duckbill
ducked
ducker
duckers
duckie
duckier
duckies
duckiest
ducking
duckling
duckpin
duckpins
ducks
ducktail
duckwalk
duckweed
ducky
duct
ductal
ducted
ductile
ducting
ductings
ductless
ducts
ductule
ductules
ductwork
dud
duddie
duddy
dude
duded
dudeen
dudeens
dudes
dudgeon
dudgeons
duding
dudish
dudishly
duds
due
duecento
duel
dueled
dueler
duelers
dueling
duelist
duelists
duelled
dueller
duellers
duelli
duelling
duellist
duello
duellos
duels
duende
duendes
dueness
duenna
duennas
dues
duet
duets
duetted
duetting
duettist
duff
duffel
duffels
duffer
duffers
duffle
duffles
duffs
dug
dugong
dugongs
dugout
dugouts
dugs
dui
duiker
duikers
duit
duits
duke
duked
dukedom
dukedoms
dukes
duking
dulcet
dulcetly
dulcets
dulciana
dulcify
dulcimer
dulcinea
dulia
dulias
dull
dullard
dullards
dulled
duller
dullest
dulling
dullish
dullness
dulls
dully
dulness
dulse
dulses
duly
duma
dumas
dumb
dumbbell
dumbcane
dumbed
dumber
dumbest
dumbhead
dumbing
dumbly
dumbness
dumbs
dumdum
dumdums
dumfound
dumka
dumky
dummied
dummies
dummkopf
dummy
dummying
dump
dumpcart
dumped
dumper
dumpers
dumpier
dumpiest
dumpily
dumping
dumpings
dumpish
dumpling
dumps
dumpy
dun
dunam
dunams
dunce
dunces
dunch
dunches
duncical
duncish
dune
duneland
dunelike
dunes
dung
dungaree
dunged
dungeon
dungeons
dunghill
dungier
dungiest
dunging
dungs
dungy
dunite
dunites
dunitic
dunk
dunked
dunker
dunkers
dunking
dunks
dunlin
dunlins
dunnage
dunnages
dunned
dunner
dunness
dunnest
dunning
dunnite
dunnites
duns
dunt
dunted
dunting
dunts
duo
duodena
duodenal
duodenum
duolog
duologs
duologue
duomi
duomo
duomos
duopoly
duopsony
duos
duotone
duotones
dup
dupable
dupe
duped
duper
duperies
dupers
dupery
dupes
duping
duple
duplex
duplexed
duplexer
duplexes
dupped
dupping
dups
dura
durable
durables
durably
dural
duramen
duramens
durance
durances
duras
duration
durative
durbar
durbars
dure
dured
dures
duress
duresses
durian
durians
during
durion
durions
durmast
durmasts
durn
durndest
durned
durneder
durning
durns
duro
duroc
durocs
duros
durr
durra
durras
durrie
durries
durrs
durst
durum
durums
dusk
dusked
duskier
duskiest
duskily
dusking
duskish
dusks
dusky
dust
dustbin
dustbins
dusted
duster
dusters
dustheap
dustier
dustiest
dustily
dusting
dustless
dustlike
dustman
dustmen
dustoff
dustoffs
dustpan
dustpans
dustrag
dustrags
dusts
dustup
dustups
dusty
dutch
dutchman
dutchmen
duteous
dutiable
duties
dutiful
duty
duumvir
duumviri
duumvirs
duvet
duvetine
duvets
duvetyn
duvetyne
duvetyns
duxelles
dwarf
dwarfed
dwarfer
dwarfest
dwarfing
dwarfish
dwarfism
dwarfs
dwarves
dweeb
dweebs
dwell
dwelled
dweller
dwellers
dwelling
dwells
dwelt
dwindle
dwindled
dwindles
dwine
dwined
dwines
dwining
dyable
dyad
dyadic
dyadics
dyads
dyarchic
dyarchy
dybbuk
dybbukim
dybbuks
dye
dyeable
dyed
dyeing
dyeings
dyer
dyers
dyes
dyestuff
dyeweed
dyeweeds
dyewood
dyewoods
dying
dyings
dyke
dyked
dykes
dykey
dyking
dynamic
dynamics
dynamism
dynamist
dynamite
dynamo
dynamos
dynast
dynastic
dynasts
dynasty
dynatron
dyne
dynein
dynel
dynels
dynes
dynode
dynodes
dysgenic
dyslexia
dyslexic
dyspepsy
dyspnea
dyspneal
dyspneas
dyspneic
dyspnoea
dyspnoic
dystaxia
dystocia
dystonia
dystonic
dystopia
dysuria
dysurias
dysuric
dyvour
dyvours
each
eager
eagerer
eagerest
eagerly
eagers
eagle
eagles
eaglet
eaglets
eagre
eagres
eanling
eanlings
ear
earache
earaches
eardrop
eardrops
eardrum
eardrums
eared
earflap
earflaps
earful
earfuls
earing
earings
earl
earlap
earlaps
earldom
earldoms
earless
earlier
earliest
earlobe
earlobes
earlock
earlocks
earls
earlship
early
earmark
earmarks
earmuff
earmuffs
earn
earned
earner
earners
earnest
earnests
earning
earnings
earns
earphone
earpiece
earplug
earplugs
earring
earrings
ears
earshot
earshots
earstone
earth
earthed
earthen
earthier
earthily
earthing
earthly
earthman
earthmen
earthnut
earthpea
earths
earthset
earthy
earwax
earwaxes
earwig
earwigs
earworm
earworms
ease
eased
easeful
easel
easels
easement
eases
easier
easies
easiest
easily
easiness
easing
east
easter
easterly
eastern
easters
easting
eastings
easts
eastward
easy
eat
eatable
eatables
eaten
eater
eateries
eaters
eatery
eath
eating
eatings
eats
eau
eaux
eave
eaved
eaves
ebb
ebbed
ebbet
ebbets
ebbing
ebbs
ebon
ebonies
ebonise
ebonised
ebonises
ebonite
ebonites
ebonize
ebonized
ebonizes
ebons
ebony
ecarte
ecartes
ecaudate
ecbolic
ecbolics
ecclesia
eccrine
ecdyses
ecdysial
ecdysis
ecdyson
ecdysone
ecdysons
ecesis
ecesises
echard
echards
eche
eched
echelle
echelles
echelon
echelons
eches
echidna
echidnae
echidnas
echinate
eching
echini
echinoid
echinus
echo
echoed
echoer
echoers
echoes
echoey
echogram
echoic
echoing
echoism
echoisms
echoless
echos
eclair
eclairs
eclat
eclats
eclectic
eclipse
eclipsed
eclipses
eclipsis
ecliptic
eclogite
eclogue
eclogues
eclosion
ecocidal
ecocide
ecocides
ecofreak
ecologic
ecology
econobox
economic
economy
ecotonal
ecotone
ecotones
ecotype
ecotypes
ecotypic
ecraseur
ecru
ecrus
ecstasy
ecstatic
ectases
ectasis
ectatic
ecthyma
ectoderm
ectomere
ectopia
ectopias
ectopic
ectosarc
ectozoa
ectozoan
ectozoon
ectypal
ectype
ectypes
ecu
ecumenic
ecus
eczema
eczemas
ed
edacious
edacity
edaphic
eddied
eddies
eddo
eddoes
eddy
eddying
edema
edemas
edemata
edenic
edentate
edge
edged
edgeless
edger
edgers
edges
edgeways
edgewise
edgier
edgiest
edgily
edginess
edging
edgings
edgy
edh
edhs
edible
edibles
edict
edictal
edicts
edifice
edifices
edified
edifier
edifiers
edifies
edify
edifying
edile
ediles
edit
editable
edited
editing
edition
editions
editor
editors
editress
edits
educable
educate
educated
educates
educator
educe
educed
educes
educible
educing
educt
eduction
eductive
eductor
eductors
educts
eel
eelgrass
eelier
eeliest
eellike
eelpout
eelpouts
eels
eelworm
eelworms
eely
eerie
eerier
eeriest
eerily
eeriness
eery
ef
eff
effable
efface
effaced
effacer
effacers
effaces
effacing
effect
effected
effecter
effector
effects
effendi
effendis
efferent
effete
effetely
efficacy
effigial
effigies
effigy
effluent
effluvia
efflux
effluxes
effort
efforts
effs
effulge
effulged
effulges
effuse
effused
effuses
effusing
effusion
effusive
efs
eft
efts
eftsoon
eftsoons
egad
egads
egal
egalite
egalites
eger
egers
egest
egesta
egested
egesting
egestion
egestive
egests
egg
eggar
eggars
eggcup
eggcups
egged
egger
eggers
egghead
eggheads
egging
eggless
eggnog
eggnogs
eggplant
eggs
eggshell
eggy
egis
egises
eglatere
eglomise
ego
egoism
egoisms
egoist
egoistic
egoists
egoless
egomania
egos
egotism
egotisms
egotist
egotists
egress
egressed
egresses
egret
egrets
egyptian
eh
eide
eider
eiders
eidetic
eidola
eidolic
eidolon
eidolons
eidos
eight
eighteen
eighth
eighthly
eighths
eighties
eights
eightvo
eightvos
eighty
eikon
eikones
eikons
einkorn
einkorns
einstein
eirenic
eiswein
eisweins
either
eject
ejecta
ejected
ejecting
ejection
ejective
ejector
ejectors
ejects
eke
eked
ekes
eking
ekistic
ekistics
ekpwele
ekpweles
ektexine
ekuele
el
elain
elains
elan
eland
elands
elans
elaphine
elapid
elapids
elapine
elapse
elapsed
elapses
elapsing
elastase
elastic
elastics
elastin
elastins
elate
elated
elatedly
elater
elaterid
elaterin
elaters
elates
elating
elation
elations
elative
elatives
elbow
elbowed
elbowing
elbows
eld
elder
elderly
elders
eldest
eldress
eldrich
eldritch
elds
elect
elected
electee
electees
electing
election
elective
elector
electors
electret
electric
electro
electron
electros
electrum
elects
elegance
elegancy
elegant
elegiac
elegiacs
elegies
elegise
elegised
elegises
elegist
elegists
elegit
elegits
elegize
elegized
elegizes
elegy
element
elements
elemi
elemis
elenchi
elenchic
elenchus
elenctic
elephant
elevate
elevated
elevates
elevator
eleven
elevens
eleventh
elevon
elevons
elf
elfin
elfins
elfish
elfishly
elflike
elflock
elflocks
elhi
elicit
elicited
elicitor
elicits
elide
elided
elides
elidible
eliding
eligible
eligibly
elint
elints
elision
elisions
elite
elites
elitism
elitisms
elitist
elitists
elixir
elixirs
elk
elkhound
elks
ell
ellipse
ellipses
ellipsis
elliptic
ells
elm
elmier
elmiest
elms
elmy
elodea
elodeas
eloign
eloigned
eloigner
eloigns
eloin
eloined
eloiner
eloiners
eloining
eloins
elongate
elope
eloped
eloper
elopers
elopes
eloping
eloquent
els
else
eluant
eluants
eluate
eluates
elude
eluded
eluder
eluders
eludes
eluding
eluent
eluents
elusion
elusions
elusive
elusory
elute
eluted
elutes
eluting
elution
elutions
eluvia
eluvial
eluviate
eluvium
eluviums
elver
elvers
elves
elvish
elvishly
elysian
elytra
elytroid
elytron
elytrous
elytrum
em
emaciate
emanate
emanated
emanates
emanator
embalm
embalmed
embalmer
embalms
embank
embanked
embanks
embar
embargo
embark
embarked
embarks
embarred
embars
embassy
embattle
embay
embayed
embaying
embays
embed
embedded
embeds
ember
embers
embezzle
embitter
emblaze
emblazed
emblazer
emblazes
emblazon
emblem
emblemed
emblems
embodied
embodier
embodies
embody
embolden
emboli
embolic
embolies
embolism
embolus
emboly
emborder
embosk
embosked
embosks
embosom
embosoms
emboss
embossed
embosser
embosses
embow
embowed
embowel
embowels
embower
embowers
embowing
embows
embrace
embraced
embracer
embraces
embroil
embroils
embrown
embrowns
embrue
embrued
embrues
embruing
embrute
embruted
embrutes
embryo
embryoid
embryon
embryons
embryos
emcee
emceed
emceeing
emcees
eme
emeer
emeerate
emeers
emend
emendate
emended
emender
emenders
emending
emends
emerald
emeralds
emerge
emerged
emergent
emerges
emerging
emeries
emerita
emeritae
emeriti
emeritus
emerod
emerods
emeroid
emeroids
emersed
emersion
emery
emes
emeses
emesis
emetic
emetics
emetin
emetine
emetines
emetins
emeu
emeus
emeute
emeutes
emf
emfs
emic
emigrant
emigrate
emigre
emigres
eminence
eminency
eminent
emir
emirate
emirates
emirs
emissary
emission
emissive
emit
emits
emitted
emitter
emitters
emitting
emmer
emmers
emmet
emmets
emodin
emodins
emote
emoted
emoter
emoters
emotes
emoting
emotion
emotions
emotive
empale
empaled
empaler
empalers
empales
empaling
empanada
empanel
empanels
empathic
empathy
emperies
emperor
emperors
empery
emphases
emphasis
emphatic
empire
empires
empiric
empirics
emplace
emplaced
emplaces
emplane
emplaned
emplanes
employ
employe
employed
employee
employer
employes
employs
empoison
emporia
emporium
empower
empowers
empress
emprise
emprises
emprize
emprizes
emptied
emptier
emptiers
empties
emptiest
emptily
emptings
emptins
empty
emptying
empurple
empyema
empyemas
empyemic
empyreal
empyrean
ems
emu
emulate
emulated
emulates
emulator
emulous
emulsify
emulsion
emulsive
emulsoid
emus
emyd
emyde
emydes
emyds
en
enable
enabled
enabler
enablers
enables
enabling
enact
enacted
enacting
enactive
enactor
enactors
enactory
enacts
enamel
enameled
enameler
enamels
enamine
enamines
enamor
enamored
enamors
enamour
enamours
enate
enates
enatic
enation
enations
encaenia
encage
encaged
encages
encaging
encamp
encamped
encamps
encase
encased
encases
encash
encashed
encashes
encasing
enceinte
enchain
enchains
enchant
enchants
enchase
enchased
enchaser
enchases
enchoric
encina
encinal
encinas
encipher
encircle
enclasp
enclasps
enclave
enclaves
enclitic
enclose
enclosed
encloser
encloses
encode
encoded
encoder
encoders
encodes
encoding
encomia
encomium
encore
encored
encores
encoring
encroach
encrust
encrusts
encrypt
encrypts
encumber
encyclic
encyst
encysted
encysts
end
endamage
endameba
endanger
endarch
endarchy
endbrain
endear
endeared
endears
endeavor
ended
endemial
endemic
endemics
endemism
ender
endermic
enders
endexine
endgame
endgames
ending
endings
endite
endited
endites
enditing
endive
endives
endleaf
endless
endlong
endmost
endnote
endnotes
endocarp
endocast
endoderm
endogamy
endogen
endogens
endogeny
endopod
endopods
endorse
endorsed
endorsee
endorser
endorses
endorsor
endosarc
endosmos
endosome
endostea
endow
endowed
endower
endowers
endowing
endows
endozoic
endpaper
endplate
endpoint
endrin
endrins
ends
endue
endued
endues
enduing
endure
endured
endures
enduring
enduro
enduros
endways
endwise
enema
enemas
enemata
enemies
enemy
energid
energids
energies
energise
energize
energy
enervate
enface
enfaced
enfaces
enfacing
enfeeble
enfeoff
enfeoffs
enfetter
enfever
enfevers
enfilade
enflame
enflamed
enflames
enfold
enfolded
enfolder
enfolds
enforce
enforced
enforcer
enforces
enframe
enframed
enframes
eng
engage
engaged
engager
engagers
engages
engaging
engender
engild
engilded
engilds
engine
engined
engineer
enginery
engines
engining
enginous
engird
engirded
engirdle
engirds
engirt
english
englut
engluts
engorge
engorged
engorges
engraft
engrafts
engrail
engrails
engrain
engrains
engram
engramme
engrams
engrave
engraved
engraver
engraves
engross
engs
engulf
engulfed
engulfs
enhalo
enhaloed
enhaloes
enhalos
enhance
enhanced
enhancer
enhances
enigma
enigmas
enigmata
enisle
enisled
enisles
enisling
enjambed
enjoin
enjoined
enjoiner
enjoins
enjoy
enjoyed
enjoyer
enjoyers
enjoying
enjoys
enkindle
enlace
enlaced
enlaces
enlacing
enlarge
enlarged
enlarger
enlarges
enlist
enlisted
enlistee
enlister
enlists
enliven
enlivens
enmesh
enmeshed
enmeshes
enmities
enmity
ennead
enneadic
enneads
enneagon
ennoble
ennobled
ennobler
ennobles
ennui
ennuis
ennuye
ennuyee
enoki
enokis
enol
enolase
enolases
enolic
enology
enols
enorm
enormity
enormous
enosis
enosises
enough
enoughs
enounce
enounced
enounces
enow
enows
enplane
enplaned
enplanes
enquire
enquired
enquires
enquiry
enrage
enraged
enrages
enraging
enrapt
enravish
enrich
enriched
enricher
enriches
enrobe
enrobed
enrober
enrobers
enrobes
enrobing
enrol
enroll
enrolled
enrollee
enroller
enrolls
enrols
enroot
enrooted
enroots
ens
ensample
ensconce
enscroll
ensemble
enserf
enserfed
enserfs
ensheath
enshrine
enshroud
ensiform
ensign
ensigncy
ensigns
ensilage
ensile
ensiled
ensiles
ensiling
enskied
enskies
ensky
enskyed
enskying
enslave
enslaved
enslaver
enslaves
ensnare
ensnared
ensnarer
ensnares
ensnarl
ensnarls
ensorcel
ensoul
ensouled
ensouls
ensphere
ensue
ensued
ensues
ensuing
ensure
ensured
ensurer
ensurers
ensures
ensuring
enswathe
entail
entailed
entailer
entails
entameba
entangle
entases
entasia
entasias
entasis
entastic
entellus
entente
ententes
enter
entera
enteral
entered
enterer
enterers
enteric
entering
enteron
enterons
enters
enthalpy
enthetic
enthral
enthrall
enthrals
enthrone
enthuse
enthused
enthuses
entia
entice
enticed
enticer
enticers
entices
enticing
entire
entirely
entires
entirety
entities
entitle
entitled
entitles
entity
entoderm
entoil
entoiled
entoils
entomb
entombed
entombs
entopic
entozoa
entozoal
entozoan
entozoic
entozoon
entrails
entrain
entrains
entrance
entrant
entrants
entrap
entraps
entreat
entreats
entreaty
entree
entrees
entrench
entrepot
entresol
entries
entropic
entropy
entrust
entrusts
entry
entryway
entwine
entwined
entwines
entwist
entwists
enure
enured
enures
enuresis
enuretic
enuring
envelop
envelope
envelops
envenom
envenoms
enviable
enviably
envied
envier
enviers
envies
envious
environ
environs
envisage
envision
envoi
envois
envoy
envoys
envy
envying
enwheel
enwheels
enwind
enwinds
enwomb
enwombed
enwombs
enwound
enwrap
enwraps
enzootic
enzym
enzyme
enzymes
enzymic
enzyms
eobiont
eobionts
eohippus
eolian
eolipile
eolith
eolithic
eoliths
eolopile
eon
eonian
eonism
eonisms
eons
eosin
eosine
eosines
eosinic
eosins
epact
epacts
eparch
eparchs
eparchy
epaulet
epaulets
epazote
epazotes
epee
epeeist
epeeists
epees
epeiric
ependyma
epergne
epergnes
epha
ephah
ephahs
ephas
ephebe
ephebes
ephebi
ephebic
epheboi
ephebos
ephebus
ephedra
ephedras
ephedrin
ephemera
ephod
ephods
ephor
ephoral
ephorate
ephori
ephors
epiblast
epibolic
epiboly
epic
epical
epically
epicalyx
epicarp
epicarps
epicedia
epicene
epicenes
epiclike
epicotyl
epics
epicure
epicures
epicycle
epidemic
epiderm
epiderms
epidote
epidotes
epidotic
epidural
epifauna
epifocal
epigeal
epigean
epigeic
epigene
epigenic
epigeous
epigon
epigone
epigones
epigoni
epigonic
epigons
epigonus
epigram
epigrams
epigraph
epigyny
epilepsy
epilog
epilogs
epilogue
epimer
epimere
epimeres
epimeric
epimers
epimysia
epinaoi
epinaos
epinasty
epiphany
epiphyte
episcia
episcias
episcope
episode
episodes
episodic
episomal
episome
episomes
epistasy
epistle
epistler
epistles
epistome
epistyle
epitaph
epitaphs
epitases
epitasis
epitaxic
epitaxy
epithet
epithets
epitome
epitomes
epitomic
epitope
epitopes
epizoa
epizoic
epizoism
epizoite
epizoon
epizooty
epoch
epochal
epochs
epode
epodes
eponym
eponymic
eponyms
eponymy
epopee
epopees
epopoeia
epos
eposes
epoxide
epoxides
epoxied
epoxies
epoxy
epoxyed
epoxying
epsilon
epsilons
equable
equably
equal
equaled
equaling
equalise
equality
equalize
equalled
equally
equals
equate
equated
equates
equating
equation
equator
equators
equerry
equid
equids
equine
equinely
equines
equinity
equinox
equip
equipage
equipped
equipper
equips
equiseta
equitant
equites
equities
equity
equivoke
er
era
eradiate
eras
erasable
erase
erased
eraser
erasers
erases
erasing
erasion
erasions
erasure
erasures
erbium
erbiums
ere
erect
erected
erecter
erecters
erectile
erecting
erection
erective
erectly
erector
erectors
erects
erelong
eremite
eremites
eremitic
eremuri
eremurus
erenow
erepsin
erepsins
erethic
erethism
erewhile
erg
ergastic
ergate
ergates
ergative
ergo
ergodic
ergot
ergotic
ergotism
ergots
ergs
erica
ericas
ericoid
erigeron
eringo
eringoes
eringos
eristic
eristics
erlking
erlkings
ermine
ermined
ermines
ern
erne
ernes
erns
erode
eroded
erodent
erodes
erodible
eroding
erogenic
eros
erose
erosely
eroses
erosible
erosion
erosions
erosive
erotic
erotica
erotical
erotics
erotism
erotisms
erotize
erotized
erotizes
err
errancy
errand
errands
errant
errantly
errantry
errants
errata
erratas
erratic
erratics
erratum
erred
errhine
errhines
erring
erringly
error
errors
errs
ers
ersatz
ersatzes
erses
erst
eruct
eructate
eructed
eructing
eructs
erudite
erugo
erugos
erumpent
erupt
erupted
erupting
eruption
eruptive
erupts
ervil
ervils
eryngo
eryngoes
eryngos
erythema
erythron
es
escalade
escalate
escallop
escalop
escalops
escapade
escape
escaped
escapee
escapees
escaper
escapers
escapes
escaping
escapism
escapist
escar
escargot
escarole
escarp
escarped
escarps
escars
eschalot
eschar
eschars
escheat
escheats
eschew
eschewal
eschewed
eschews
escolar
escolars
escort
escorted
escorts
escot
escoted
escoting
escots
escrow
escrowed
escrows
escuage
escuages
escudo
escudos
esculent
eserine
eserines
eses
eskar
eskars
esker
eskers
esophagi
esoteric
espalier
espanol
esparto
espartos
especial
espial
espials
espied
espiegle
espies
espousal
espouse
espoused
espouser
espouses
espresso
esprit
esprits
espy
espying
esquire
esquired
esquires
ess
essay
essayed
essayer
essayers
essaying
essayist
essays
essence
essences
esses
essoin
essoins
essonite
estancia
estate
estated
estates
estating
esteem
esteemed
esteems
ester
esterase
esterify
esters
estheses
esthesia
esthesis
esthete
esthetes
esthetic
estimate
estival
estivate
estop
estopped
estoppel
estops
estovers
estragon
estral
estrange
estray
estrayed
estrays
estreat
estreats
estrin
estrins
estriol
estriols
estrogen
estrone
estrones
estrous
estrual
estrum
estrums
estrus
estruses
estuary
esurient
et
eta
etagere
etageres
etalon
etalons
etamin
etamine
etamines
etamins
etape
etapes
etas
etatism
etatisms
etatist
etcetera
etch
etchant
etchants
etched
etcher
etchers
etches
etching
etchings
eternal
eternals
eterne
eternise
eternity
eternize
etesian
etesians
eth
ethane
ethanes
ethanol
ethanols
ethene
ethenes
ethephon
ether
ethereal
etheric
etherify
etherish
etherize
ethers
ethic
ethical
ethicals
ethician
ethicist
ethicize
ethics
ethinyl
ethinyls
ethion
ethions
ethmoid
ethmoids
ethnarch
ethnic
ethnical
ethnics
ethnos
ethnoses
ethology
ethos
ethoses
ethoxies
ethoxy
ethoxyl
ethoxyls
eths
ethyl
ethylate
ethylene
ethylic
ethyls
ethyne
ethynes
ethynyl
ethynyls
etic
etiolate
etiology
etna
etnas
etoile
etoiles
etouffee
etude
etudes
etui
etuis
etwee
etwees
etyma
etymon
etymons
eucaine
eucaines
eucalypt
eucharis
euchre
euchred
euchres
euchring
euclase
euclases
eucrite
eucrites
eucritic
eudaemon
eudemon
eudemons
eugenia
eugenias
eugenic
eugenics
eugenist
eugenol
eugenols
euglena
euglenas
eulachan
eulachon
eulogia
eulogiae
eulogias
eulogies
eulogise
eulogist
eulogium
eulogize
eulogy
eunuch
eunuchs
euonymus
eupatrid
eupepsia
eupepsy
eupeptic
euphenic
euphonic
euphony
euphoria
euphoric
euphotic
euphrasy
euphroe
euphroes
euphuism
euphuist
euploid
euploids
euploidy
eupnea
eupneas
eupneic
eupnoea
eupnoeas
eupnoeic
eureka
euripi
euripus
euro
eurokies
eurokous
euroky
europium
euros
eurybath
euryoky
eurythmy
eustacy
eustatic
eustele
eusteles
eutaxies
eutaxy
eutectic
eutrophy
euxenite
evacuant
evacuate
evacuee
evacuees
evadable
evade
evaded
evader
evaders
evades
evadible
evading
evaluate
evanesce
evangel
evangels
evanish
evasion
evasions
evasive
eve
evection
even
evened
evener
eveners
evenest
evenfall
evening
evenings
evenly
evenness
evens
evensong
event
eventful
eventide
events
eventual
ever
evermore
eversion
evert
everted
everting
evertor
evertors
everts
every
everyday
everyman
everymen
everyone
everyway
eves
evict
evicted
evictee
evictees
evicting
eviction
evictor
evictors
evicts
evidence
evident
evil
evildoer
eviler
evilest
eviller
evillest
evilly
evilness
evils
evince
evinced
evinces
evincing
evincive
evitable
evite
evited
evites
eviting
evocable
evocator
evoke
evoked
evoker
evokers
evokes
evoking
evolute
evolutes
evolve
evolved
evolver
evolvers
evolves
evolving
evonymus
evulsion
evzone
evzones
ewe
ewer
ewers
ewes
ex
exact
exacta
exactas
exacted
exacter
exacters
exactest
exacting
exaction
exactly
exactor
exactors
exacts
exalt
exalted
exalter
exalters
exalting
exalts
exam
examen
examens
examine
examined
examinee
examiner
examines
example
exampled
examples
exams
exanthem
exarch
exarchal
exarchs
exarchy
excavate
exceed
exceeded
exceeder
exceeds
excel
excelled
excels
except
excepted
excepts
excerpt
excerpts
excess
excessed
excesses
exchange
excide
excided
excides
exciding
excimer
excimers
exciple
exciples
excise
excised
excises
excising
excision
excitant
excite
excited
exciter
exciters
excites
exciting
exciton
excitons
excitor
excitors
exclaim
exclaims
exclave
exclaves
exclude
excluded
excluder
excludes
excreta
excretal
excrete
excreted
excreter
excretes
excursus
excuse
excused
excuser
excusers
excuses
excusing
exec
execrate
execs
execute
executed
executer
executes
executor
exedra
exedrae
exegeses
exegesis
exegete
exegetes
exegetic
exempla
exemplar
exemplum
exempt
exempted
exempts
exequial
exequies
exequy
exercise
exergual
exergue
exergues
exert
exerted
exerting
exertion
exertive
exerts
exes
exeunt
exhalant
exhale
exhaled
exhalent
exhales
exhaling
exhaust
exhausts
exhibit
exhibits
exhort
exhorted
exhorter
exhorts
exhume
exhumed
exhumer
exhumers
exhumes
exhuming
exigence
exigency
exigent
exigible
exiguity
exiguous
exile
exiled
exiles
exilian
exilic
exiling
eximious
exine
exines
exist
existed
existent
existing
exists
exit
exited
exiting
exitless
exits
exocarp
exocarps
exocrine
exoderm
exoderms
exodoi
exodos
exodus
exoduses
exoergic
exogamic
exogamy
exogen
exogens
exon
exonic
exons
exonumia
exorable
exorcise
exorcism
exorcist
exorcize
exordia
exordial
exordium
exosmic
exosmose
exospore
exoteric
exotic
exotica
exotics
exotism
exotisms
exotoxic
exotoxin
expand
expanded
expander
expandor
expands
expanse
expanses
expat
expats
expect
expected
expects
expedite
expel
expelled
expellee
expeller
expels
expend
expended
expender
expends
expense
expensed
expenses
expert
experted
expertly
experts
expiable
expiate
expiated
expiates
expiator
expire
expired
expirer
expirers
expires
expiries
expiring
expiry
explain
explains
explant
explants
explicit
explode
exploded
exploder
explodes
exploit
exploits
explore
explored
explorer
explores
expo
exponent
export
exported
exporter
exports
expos
exposal
exposals
expose
exposed
exposer
exposers
exposes
exposing
exposit
exposits
exposure
expound
expounds
express
expresso
expulse
expulsed
expulses
expunge
expunged
expunger
expunges
exscind
exscinds
exsecant
exsect
exsected
exsects
exsert
exserted
exserts
extant
extend
extended
extender
extends
extensor
extent
extents
exterior
extern
external
externe
externes
externs
extinct
extincts
extol
extoll
extolled
extoller
extolls
extols
extort
extorted
extorter
extorts
extra
extract
extracts
extrados
extras
extrema
extreme
extremer
extremes
extremum
extrorse
extrude
extruded
extruder
extrudes
extubate
exudate
exudates
exude
exuded
exudes
exuding
exult
exultant
exulted
exulting
exults
exurb
exurban
exurbia
exurbias
exurbs
exuvia
exuviae
exuvial
exuviate
exuvium
eyas
eyases
eye
eyeable
eyeball
eyeballs
eyebar
eyebars
eyebeam
eyebeams
eyebolt
eyebolts
eyebrow
eyebrows
eyecup
eyecups
eyed
eyedness
eyedrops
eyeful
eyefuls
eyeglass
eyehole
eyeholes
eyehook
eyehooks
eyeing
eyelash
eyeless
eyelet
eyelets
eyelid
eyelids
eyelike
eyeliner
eyen
eyepiece
eyepoint
eyer
eyers
eyes
eyeshade
eyeshot
eyeshots
eyesight
eyesome
eyesore
eyesores
eyespot
eyespots
eyestalk
eyestone
eyeteeth
eyetooth
eyewash
eyewater
eyewear
eyewink
eyewinks
eying
eyne
eyra
eyras
eyre
eyres
eyrie
eyries
eyrir
eyry
fa
fable
fabled
fabler
fablers
fables
fabliau
fabliaux
fabling
fabric
fabrics
fabular
fabulist
fabulous
facade
facades
face
faceable
faced
facedown
faceless
facer
facers
faces
facet
facete
faceted
facetely
facetiae
faceting
facets
facetted
faceup
facia
facial
facially
facials
facias
faciend
faciends
facies
facile
facilely
facility
facing
facings
fact
factful
faction
factions
factious
factoid
factoids
factor
factored
factors
factory
factotum
facts
factual
facture
factures
facula
faculae
facular
faculty
fad
fadable
faddier
faddiest
faddish
faddism
faddisms
faddist
faddists
faddy
fade
fadeaway
faded
fadedly
fadeless
fader
faders
fades
fadge
fadged
fadges
fadging
fading
fadings
fado
fados
fads
faecal
faeces
faena
faenas
faerie
faeries
faery
fag
fagged
fagging
faggot
faggoted
faggotry
faggots
faggoty
faggy
fagin
fagins
fagot
fagoted
fagoter
fagoters
fagoting
fagots
fags
fahlband
faience
faiences
fail
failed
failing
failings
faille
failles
fails
failure
failures
fain
faineant
fainer
fainest
faint
fainted
fainter
fainters
faintest
fainting
faintish
faintly
faints
fair
faired
fairer
fairest
fairies
fairing
fairings
fairish
fairlead
fairly
fairness
fairs
fairway
fairways
fairy
fairyism
faith
faithed
faithful
faithing
faiths
faitour
faitours
fajita
fajitas
fake
faked
fakeer
fakeers
faker
fakeries
fakers
fakery
fakes
fakey
faking
fakir
fakirs
falafel
falbala
falbalas
falcate
falcated
falces
falchion
falcon
falconer
falconet
falconry
falcons
falderal
falderol
fall
fallacy
fallal
fallals
fallaway
fallback
fallen
faller
fallers
fallfish
fallible
fallibly
falling
falloff
falloffs
fallout
fallouts
fallow
fallowed
fallows
falls
false
falsely
falser
falsest
falsetto
falsie
falsies
falsify
falsity
faltboat
falter
faltered
falterer
falters
falx
fame
famed
fameless
fames
familial
familiar
families
familism
family
famine
famines
faming
famish
famished
famishes
famous
famously
famuli
famulus
fan
fanatic
fanatics
fancied
fancier
fanciers
fancies
fanciest
fanciful
fancify
fancily
fancy
fancying
fandango
fandom
fandoms
fane
fanega
fanegada
fanegas
fanes
fanfare
fanfares
fanfaron
fanfold
fanfolds
fang
fanga
fangas
fanged
fangless
fanglike
fangs
fanion
fanions
fanjet
fanjets
fanlight
fanlike
fanned
fanner
fanners
fannies
fanning
fanny
fano
fanon
fanons
fanos
fans
fantail
fantails
fantasia
fantasie
fantasm
fantasms
fantast
fantasts
fantasy
fantod
fantods
fantom
fantoms
fanum
fanums
fanwise
fanwort
fanworts
fanzine
fanzines
faqir
faqirs
faquir
faquirs
far
farad
faradaic
faraday
faradays
faradic
faradise
faradism
faradize
farads
faraway
farce
farced
farcer
farcers
farces
farceur
farceurs
farci
farcical
farcie
farcies
farcing
farcy
fard
farded
fardel
fardels
farding
fards
fare
fared
farer
farers
fares
farewell
farfal
farfals
farfel
farfels
farina
farinas
faring
farinha
farinhas
farinose
farl
farle
farles
farls
farm
farmable
farmed
farmer
farmers
farmhand
farming
farmings
farmland
farms
farmwife
farmwork
farmyard
farnesol
farness
faro
faros
farouche
farrago
farrier
farriers
farriery
farrow
farrowed
farrows
farside
farsides
fart
farted
farther
farthest
farthing
farting
farts
fas
fasces
fascia
fasciae
fascial
fascias
fasciate
fascicle
fascine
fascines
fascism
fascisms
fascist
fascists
fash
fashed
fashes
fashing
fashion
fashions
fashious
fast
fastback
fastball
fasted
fasten
fastened
fastener
fastens
faster
fastest
fasting
fastings
fastness
fasts
fastuous
fat
fatal
fatalism
fatalist
fatality
fatally
fatback
fatbacks
fatbird
fatbirds
fate
fated
fateful
fates
fathead
fatheads
father
fathered
fatherly
fathers
fathom
fathomed
fathoms
fatidic
fatigue
fatigued
fatigues
fating
fatless
fatlike
fatling
fatlings
fatly
fatness
fats
fatso
fatsoes
fatsos
fatstock
fatted
fatten
fattened
fattener
fattens
fatter
fattest
fattier
fatties
fattiest
fattily
fatting
fattish
fatty
fatuity
fatuous
fatwa
fatwas
fatwood
fatwoods
faubourg
faucal
faucals
fauces
faucet
faucets
faucial
faugh
fauld
faulds
fault
faulted
faultier
faultily
faulting
faults
faulty
faun
fauna
faunae
faunal
faunally
faunas
faunlike
fauns
fauteuil
fauve
fauves
fauvism
fauvisms
fauvist
fauvists
faux
fava
favas
fave
favela
favelas
favella
favellas
faves
favism
favisms
favonian
favor
favored
favorer
favorers
favoring
favorite
favors
favour
favoured
favourer
favours
favus
favuses
fawn
fawned
fawner
fawners
fawnier
fawniest
fawning
fawnlike
fawns
fawny
fax
faxed
faxes
faxing
fay
fayalite
fayed
faying
fays
faze
fazed
fazenda
fazendas
fazes
fazing
feal
fealties
fealty
fear
feared
fearer
fearers
fearful
fearing
fearless
fears
fearsome
feasance
fease
feased
feases
feasible
feasibly
feasing
feast
feasted
feaster
feasters
feastful
feasting
feasts
feat
feater
featest
feather
feathers
feathery
featlier
featly
feats
feature
featured
features
feaze
feazed
feazes
feazing
febrific
febrile
fecal
feces
fecial
fecials
feck
feckless
feckly
fecks
fecula
feculae
feculent
fecund
fed
fedayee
fedayeen
federacy
federal
federals
federate
fedora
fedoras
feds
fee
feeble
feebler
feeblest
feeblish
feebly
feed
feedable
feedback
feedbag
feedbags
feedbox
feeder
feeders
feedhole
feeding
feedlot
feedlots
feeds
feeing
feel
feeler
feelers
feeless
feeling
feelings
feels
fees
feet
feetless
feeze
feezed
feezes
feezing
feh
fehs
feign
feigned
feigner
feigners
feigning
feigns
feijoa
feijoas
feint
feinted
feinting
feints
feirie
feist
feistier
feists
feisty
felafel
feldsher
feldspar
felicity
felid
felids
feline
felinely
felines
felinity
fell
fella
fellable
fellah
fellahin
fellahs
fellas
fellate
fellated
fellates
fellatio
fellator
felled
feller
fellers
fellest
fellies
felling
fellness
felloe
felloes
fellow
fellowed
fellowly
fellows
fells
felly
felon
felonies
felonry
felons
felony
felsite
felsites
felsitic
felspar
felspars
felstone
felt
felted
felting
feltings
feltlike
felts
felucca
feluccas
felwort
felworts
fem
female
females
feme
femes
feminacy
feminie
feminine
feminise
feminism
feminist
feminity
feminize
femme
femmes
femora
femoral
fems
femur
femurs
fen
fenagle
fenagled
fenagles
fence
fenced
fencer
fencerow
fencers
fences
fencible
fencing
fencings
fend
fended
fender
fendered
fenders
fending
fends
fenestra
fenland
fenlands
fennec
fennecs
fennel
fennels
fenny
fens
fenthion
fenuron
fenurons
feod
feodary
feods
feoff
feoffed
feoffee
feoffees
feoffer
feoffers
feoffing
feoffor
feoffors
feoffs
fer
feracity
feral
ferbam
ferbams
fere
feres
feretory
feria
feriae
ferial
ferias
ferine
ferities
ferity
ferlie
ferlies
ferly
fermata
fermatas
fermate
ferment
ferments
fermi
fermion
fermions
fermis
fermium
fermiums
fern
fernery
fernier
ferniest
fernless
fernlike
ferns
ferny
ferocity
ferrate
ferrates
ferrel
ferreled
ferrels
ferreous
ferret
ferreted
ferreter
ferrets
ferrety
ferriage
ferric
ferried
ferries
ferrite
ferrites
ferritic
ferritin
ferrous
ferrule
ferruled
ferrules
ferrum
ferrums
ferry
ferrying
ferryman
ferrymen
fertile
ferula
ferulae
ferulas
ferule
feruled
ferules
feruling
fervency
fervent
fervid
fervidly
fervor
fervors
fervour
fervours
fescue
fescues
fess
fesse
fessed
fesses
fessing
fesswise
festal
festally
fester
festered
festers
festival
festive
festoon
festoons
fet
feta
fetal
fetas
fetation
fetch
fetched
fetcher
fetchers
fetches
fetching
fete
feted
feterita
fetes
fetial
fetiales
fetialis
fetials
fetich
fetiches
feticide
fetid
fetidly
feting
fetish
fetishes
fetlock
fetlocks
fetology
fetor
fetors
fets
fetted
fetter
fettered
fetterer
fetters
fetting
fettle
fettled
fettles
fettling
fetus
fetuses
feu
feuar
feuars
feud
feudal
feudally
feudary
feuded
feuding
feudist
feudists
feuds
feued
feuing
feus
fever
fevered
feverfew
fevering
feverish
feverous
fevers
few
fewer
fewest
fewness
fewtrils
fey
feyer
feyest
feyly
feyness
fez
fezes
fezzed
fezzes
fiacre
fiacres
fiance
fiancee
fiancees
fiances
fiar
fiars
fiaschi
fiasco
fiascoes
fiascos
fiat
fiats
fib
fibbed
fibber
fibbers
fibbing
fiber
fibered
fiberize
fibers
fibranne
fibre
fibres
fibril
fibrilla
fibrils
fibrin
fibrins
fibroid
fibroids
fibroin
fibroins
fibroma
fibromas
fibroses
fibrosis
fibrotic
fibrous
fibs
fibula
fibulae
fibular
fibulas
fice
fices
fiche
fiches
fichu
fichus
ficin
ficins
fickle
fickler
ficklest
fickly
fico
ficoes
fictile
fiction
fictions
fictive
ficus
ficuses
fid
fiddle
fiddled
fiddler
fiddlers
fiddles
fiddling
fiddly
fideism
fideisms
fideist
fideists
fidelity
fidge
fidged
fidges
fidget
fidgeted
fidgeter
fidgets
fidgety
fidging
fido
fidos
fids
fiducial
fie
fief
fiefdom
fiefdoms
fiefs
field
fielded
fielder
fielders
fielding
fields
fiend
fiendish
fiends
fierce
fiercely
fiercer
fiercest
fierier
fieriest
fierily
fiery
fiesta
fiestas
fife
fifed
fifer
fifers
fifes
fifing
fifteen
fifteens
fifth
fifthly
fifths
fifties
fiftieth
fifty
fiftyish
fig
figeater
figged
figging
fight
fighter
fighters
fighting
fights
figment
figments
figs
figuline
figural
figurant
figurate
figure
figured
figurer
figurers
figures
figurine
figuring
figwort
figworts
fil
fila
filagree
filament
filar
filaree
filarees
filaria
filariae
filarial
filarian
filariid
filature
filbert
filberts
filch
filched
filcher
filchers
filches
filching
file
fileable
filed
filefish
filemot
filer
filers
files
filet
fileted
fileting
filets
filial
filially
filiate
filiated
filiates
filibeg
filibegs
filicide
filiform
filigree
filing
filings
filister
fill
fille
filled
filler
fillers
filles
fillet
filleted
fillets
fillies
filling
fillings
fillip
filliped
fillips
fillo
fillos
fills
filly
film
filmable
filmcard
filmdom
filmdoms
filmed
filmer
filmers
filmgoer
filmic
filmier
filmiest
filmily
filming
filmland
films
filmset
filmsets
filmy
filo
filos
filose
fils
filter
filtered
filterer
filters
filth
filthier
filthily
filths
filthy
filtrate
filum
fimble
fimbles
fimbria
fimbriae
fimbrial
fin
finable
finagle
finagled
finagler
finagles
final
finale
finales
finalis
finalise
finalism
finalist
finality
finalize
finally
finals
finance
financed
finances
finback
finbacks
finch
finches
find
findable
finder
finders
finding
findings
finds
fine
fineable
fined
finely
fineness
finer
fineries
finery
fines
finespun
finesse
finessed
finesses
finest
finfish
finfoot
finfoots
finger
fingered
fingerer
fingers
finial
finialed
finials
finical
finickin
finicky
finikin
finiking
fining
finings
finis
finises
finish
finished
finisher
finishes
finite
finitely
finites
finitude
fink
finked
finking
finks
finless
finlike
finmark
finmarks
finned
finnicky
finnier
finniest
finning
finnmark
finny
fino
finochio
finos
fins
fiord
fiords
fipple
fipples
fique
fiques
fir
fire
fireable
firearm
firearms
fireback
fireball
firebase
firebird
fireboat
firebomb
firebox
firebrat
firebug
firebugs
fireclay
fired
firedamp
firedog
firedogs
firefang
firefly
firehall
fireless
firelit
firelock
fireman
firemen
firepan
firepans
firepink
fireplug
firepot
firepots
firer
fireroom
firers
fires
fireside
firetrap
fireweed
firewood
firework
fireworm
firing
firings
firkin
firkins
firm
firman
firmans
firmed
firmer
firmers
firmest
firming
firmly
firmness
firms
firmware
firn
firns
firry
firs
first
firstly
firsts
firth
firths
fisc
fiscal
fiscally
fiscals
fiscs
fish
fishable
fishbolt
fishbone
fishbowl
fished
fisher
fishers
fishery
fishes
fisheye
fisheyes
fishgig
fishgigs
fishhook
fishier
fishiest
fishily
fishing
fishings
fishless
fishlike
fishline
fishmeal
fishnet
fishnets
fishpole
fishpond
fishtail
fishway
fishways
fishwife
fishworm
fishy
fissate
fissile
fission
fissions
fissiped
fissure
fissured
fissures
fist
fisted
fistful
fistfuls
fistic
fisting
fistnote
fists
fistula
fistulae
fistular
fistulas
fit
fitch
fitchee
fitches
fitchet
fitchets
fitchew
fitchews
fitchy
fitful
fitfully
fitly
fitment
fitments
fitness
fits
fittable
fitted
fitter
fitters
fittest
fitting
fittings
five
fivefold
fivepins
fiver
fivers
fives
fix
fixable
fixate
fixated
fixates
fixatif
fixatifs
fixating
fixation
fixative
fixed
fixedly
fixer
fixers
fixes
fixing
fixings
fixit
fixities
fixity
fixt
fixture
fixtures
fixure
fixures
fiz
fizgig
fizgigs
fizz
fizzed
fizzer
fizzers
fizzes
fizzier
fizziest
fizzing
fizzle
fizzled
fizzles
fizzling
fizzy
fjeld
fjelds
fjord
fjords
flab
flabbier
flabbily
flabby
flabella
flabs
flaccid
flack
flacked
flackery
flacking
flacks
flacon
flacons
flag
flagella
flagged
flagger
flaggers
flaggier
flagging
flaggy
flagless
flagman
flagmen
flagon
flagons
flagpole
flagrant
flags
flagship
flail
flailed
flailing
flails
flair
flairs
flak
flake
flaked
flaker
flakers
flakes
flakey
flakier
flakiest
flakily
flaking
flaky
flam
flambe
flambeau
flambee
flambeed
flambes
flame
flamed
flamen
flamenco
flamens
flameout
flamer
flamers
flames
flamier
flamiest
flamines
flaming
flamingo
flammed
flamming
flams
flamy
flan
flancard
flanerie
flanes
flaneur
flaneurs
flange
flanged
flanger
flangers
flanges
flanging
flank
flanked
flanken
flanker
flankers
flanking
flanks
flannel
flannels
flans
flap
flapjack
flapless
flapped
flapper
flappers
flappier
flapping
flappy
flaps
flare
flared
flares
flaring
flash
flashed
flasher
flashers
flashes
flashgun
flashier
flashily
flashing
flashy
flask
flasket
flaskets
flasks
flat
flatbed
flatbeds
flatboat
flatcap
flatcaps
flatcar
flatcars
flatfeet
flatfish
flatfoot
flathead
flatiron
flatland
flatlet
flatlets
flatling
flatlong
flatly
flatmate
flatness
flats
flatted
flatten
flattens
flatter
flatters
flattery
flattest
flatting
flattish
flattop
flattops
flatus
flatuses
flatware
flatwash
flatways
flatwise
flatwork
flatworm
flaunt
flaunted
flaunter
flaunts
flaunty
flautist
flavanol
flavin
flavine
flavines
flavins
flavone
flavones
flavonol
flavor
flavored
flavorer
flavors
flavory
flavour
flavours
flavoury
flaw
flawed
flawier
flawiest
flawing
flawless
flaws
flawy
flax
flaxen
flaxes
flaxier
flaxiest
flaxseed
flaxy
flay
flayed
flayer
flayers
flaying
flays
flea
fleabag
fleabags
fleabane
fleabite
fleam
fleams
fleapit
fleapits
fleas
fleawort
fleche
fleches
fleck
flecked
flecking
flecks
flecky
flection
fled
fledge
fledged
fledges
fledgier
fledging
fledgy
flee
fleece
fleeced
fleecer
fleecers
fleeces
fleech
fleeched
fleeches
fleecier
fleecily
fleecing
fleecy
fleeing
fleer
fleered
fleering
fleers
flees
fleet
fleeted
fleeter
fleetest
fleeting
fleetly
fleets
fleishig
flemish
flench
flenched
flenches
flense
flensed
flenser
flensers
flenses
flensing
flesh
fleshed
flesher
fleshers
fleshes
fleshier
fleshing
fleshly
fleshpot
fleshy
fletch
fletched
fletcher
fletches
fleury
flew
flews
flex
flexagon
flexed
flexes
flexible
flexibly
flexile
flexing
flexion
flexions
flexor
flexors
flextime
flexuose
flexuous
flexural
flexure
flexures
fley
fleyed
fleying
fleys
flic
flichter
flick
flicked
flicker
flickers
flickery
flicking
flicks
flics
flied
flier
fliers
flies
fliest
flight
flighted
flights
flighty
flimflam
flimsier
flimsies
flimsily
flimsy
flinch
flinched
flincher
flinches
flinder
flinders
fling
flinger
flingers
flinging
flings
flinkite
flint
flinted
flintier
flintily
flinting
flints
flinty
flip
flippant
flipped
flipper
flippers
flippest
flipping
flippy
flips
flirt
flirted
flirter
flirters
flirtier
flirting
flirts
flirty
flit
flitch
flitched
flitches
flite
flited
flites
fliting
flits
flitted
flitter
flitters
flitting
flivver
flivvers
float
floatage
floated
floatel
floatels
floater
floaters
floatier
floating
floats
floaty
floc
flocced
flocci
floccing
floccose
floccule
flocculi
floccus
flock
flocked
flockier
flocking
flocks
flocky
flocs
floe
floes
flog
flogged
flogger
floggers
flogging
flogs
flokati
flokatis
flong
flongs
flood
flooded
flooder
flooders
flooding
floodlit
floods
floodway
flooey
flooie
floor
floorage
floored
floorer
floorers
flooring
floors
floosie
floosies
floosy
floozie
floozies
floozy
flop
flopover
flopped
flopper
floppers
floppier
floppies
floppily
flopping
floppy
flops
flora
florae
floral
florally
florals
floras
florence
floret
florets
florid
floridly
florigen
florin
florins
florist
florists
floruit
floruits
floss
flossed
flosses
flossie
flossier
flossies
flossily
flossing
flossy
flota
flotage
flotages
flotas
flotilla
flotsam
flotsams
flounce
flounced
flounces
flouncy
flounder
flour
floured
flouring
flourish
flours
floury
flout
flouted
flouter
flouters
flouting
flouts
flow
flowage
flowages
flowed
flower
flowered
flowerer
floweret
flowers
flowery
flowing
flown
flows
flu
flub
flubbed
flubber
flubbers
flubbing
flubdub
flubdubs
flubs
flue
flued
fluency
fluent
fluently
flueric
fluerics
flues
fluff
fluffed
fluffier
fluffily
fluffing
fluffs
fluffy
fluid
fluidal
fluidic
fluidics
fluidise
fluidity
fluidize
fluidly
fluidram
fluids
fluke
fluked
flukes
flukey
flukier
flukiest
fluking
fluky
flume
flumed
flumes
fluming
flummery
flummox
flump
flumped
flumping
flumps
flung
flunk
flunked
flunker
flunkers
flunkey
flunkeys
flunkies
flunking
flunks
flunky
fluor
fluorene
fluoric
fluorid
fluoride
fluorids
fluorin
fluorine
fluorins
fluorite
fluors
flurried
flurries
flurry
flus
flush
flushed
flusher
flushers
flushes
flushest
flushing
fluster
flusters
flute
fluted
fluter
fluters
flutes
flutey
flutier
flutiest
fluting
flutings
flutist
flutists
flutter
flutters
fluttery
fluty
fluvial
flux
fluxed
fluxes
fluxgate
fluxing
fluxion
fluxions
fluyt
fluyts
fly
flyable
flyaway
flyaways
flybelt
flybelts
flyblew
flyblow
flyblown
flyblows
flyboat
flyboats
flyboy
flyboys
flyby
flybys
flyer
flyers
flying
flyings
flyleaf
flyless
flyman
flymen
flyoff
flyoffs
flyover
flyovers
flypaper
flypast
flypasts
flysch
flysches
flyspeck
flyte
flyted
flytes
flytier
flytiers
flyting
flytings
flytrap
flytraps
flyway
flyways
flywheel
foal
foaled
foaling
foals
foam
foamable
foamed
foamer
foamers
foamier
foamiest
foamily
foaming
foamless
foamlike
foams
foamy
fob
fobbed
fobbing
fobs
focaccia
focal
focalise
focalize
focally
foci
focus
focused
focuser
focusers
focuses
focusing
focussed
focusses
fodder
foddered
fodders
fodgel
foe
foehn
foehns
foeman
foemen
foes
foetal
foetid
foetor
foetors
foetus
foetuses
fog
fogbound
fogbow
fogbows
fogdog
fogdogs
fogey
fogeys
fogfruit
foggage
foggages
fogged
fogger
foggers
foggier
foggiest
foggily
fogging
foggy
foghorn
foghorns
fogie
fogies
fogless
fogs
fogy
fogyish
fogyism
fogyisms
foh
fohn
fohns
foible
foibles
foil
foilable
foiled
foiling
foils
foilsman
foilsmen
foin
foined
foining
foins
foison
foisons
foist
foisted
foisting
foists
folacin
folacins
folate
folates
fold
foldable
foldaway
foldboat
folded
folder
folderol
folders
folding
foldout
foldouts
folds
folia
foliage
foliaged
foliages
foliar
foliate
foliated
foliates
folio
folioed
folioing
folios
foliose
folious
folium
foliums
folk
folkie
folkies
folkish
folklife
folklike
folklore
folkmoot
folkmot
folkmote
folkmots
folks
folksier
folksily
folksy
folktale
folkway
folkways
folky
folles
follicle
follies
follis
follow
followed
follower
follows
folly
foment
fomented
fomenter
foments
fomite
fomites
fon
fond
fondant
fondants
fonded
fonder
fondest
fonding
fondle
fondled
fondler
fondlers
fondles
fondling
fondly
fondness
fonds
fondu
fondue
fondues
fondus
fons
font
fontal
fontanel
fontina
fontinas
fonts
food
foodie
foodies
foodless
foods
foodways
foofaraw
fool
fooled
foolery
foolfish
fooling
foolish
fools
foolscap
foot
footage
footages
football
footbath
footboy
footboys
footed
footer
footers
footfall
footgear
foothill
foothold
footie
footier
footies
footiest
footing
footings
footle
footled
footler
footlers
footles
footless
footlike
footling
footman
footmark
footmen
footnote
footpace
footpad
footpads
footpath
footrace
footrest
footrope
foots
footsie
footsies
footslog
footsore
footstep
footsy
footwall
footway
footways
footwear
footwork
footworn
footy
foozle
foozled
foozler
foozlers
foozles
foozling
fop
fopped
foppery
fopping
foppish
fops
for
fora
forage
foraged
forager
foragers
forages
foraging
foram
foramen
foramens
foramina
forams
foray
forayed
forayer
forayers
foraying
forays
forb
forbad
forbade
forbear
forbears
forbid
forbidal
forbids
forbode
forboded
forbodes
forbore
forborne
forbs
forby
forbye
force
forced
forcedly
forceful
forceps
forcer
forcers
forces
forcible
forcibly
forcing
forcipes
ford
fordable
forded
fordid
fording
fordless
fordo
fordoes
fordoing
fordone
fords
fore
forearm
forearms
forebay
forebays
forebear
forebode
forebody
foreboom
foreby
forebye
forecast
foredate
foredeck
foredid
foredo
foredoes
foredone
foredoom
foreface
forefeel
forefeet
forefelt
forefend
forefoot
forego
foregoer
foregoes
foregone
foregut
foreguts
forehand
forehead
forehoof
foreign
foreknew
foreknow
forelady
foreland
foreleg
forelegs
forelimb
forelock
foreman
foremast
foremen
foremilk
foremost
forename
forenoon
forensic
forepart
forepast
forepaw
forepaws
forepeak
foreplay
foreran
forerank
forerun
foreruns
fores
foresaid
foresail
foresaw
foresee
foreseen
foreseer
foresees
foreshow
foreside
foreskin
forest
forestal
forestay
forested
forester
forestry
forests
foretell
foretime
foretold
foretop
foretops
forever
forevers
forewarn
forewent
forewing
foreword
foreworn
foreyard
forfeit
forfeits
forfend
forfends
forgat
forgave
forge
forged
forger
forgers
forgery
forges
forget
forgets
forging
forgings
forgive
forgiven
forgiver
forgives
forgo
forgoer
forgoers
forgoes
forgoing
forgone
forgot
forint
forints
forjudge
fork
forkball
forked
forkedly
forker
forkers
forkful
forkfuls
forkier
forkiest
forking
forkless
forklift
forklike
forks
forksful
forky
forlorn
form
formable
formal
formalin
formally
formals
formant
formants
format
formate
formates
formats
forme
formed
formee
former
formerly
formers
formes
formful
formic
forming
formless
formol
formols
forms
formula
formulae
formulas
formwork
formyl
formyls
fornical
fornices
fornix
forrader
forrit
forsake
forsaken
forsaker
forsakes
forsook
forsooth
forspent
forswear
forswore
forsworn
fort
forte
fortes
forth
forties
fortieth
fortify
fortis
fortress
forts
fortuity
fortune
fortuned
fortunes
forty
fortyish
forum
forums
forward
forwards
forwent
forwhy
forworn
forzando
foss
fossa
fossae
fossas
fossate
fosse
fosses
fossette
fossick
fossicks
fossil
fossils
foster
fostered
fosterer
fosters
fou
fouette
fouettes
fought
foughten
foul
foulard
foulards
fouled
fouler
foulest
fouling
foulings
foully
foulness
fouls
found
founded
founder
founders
founding
foundry
founds
fount
fountain
founts
four
fourchee
fourfold
fourgon
fourgons
fourplex
fours
foursome
fourteen
fourth
fourthly
fourths
fovea
foveae
foveal
foveas
foveate
foveated
foveola
foveolae
foveolar
foveolas
foveole
foveoles
foveolet
fowl
fowled
fowler
fowlers
fowling
fowlings
fowlpox
fowls
fox
foxed
foxes
foxfire
foxfires
foxfish
foxglove
foxhole
foxholes
foxhound
foxhunt
foxhunts
foxier
foxiest
foxily
foxiness
foxing
foxings
foxlike
foxskin
foxskins
foxtail
foxtails
foxtrot
foxtrots
foxy
foy
foyer
foyers
foys
fozier
foziest
foziness
fozy
frabjous
fracas
fracases
fractal
fractals
fracted
fracti
fraction
fractur
fracture
fracturs
fractus
frae
fraena
fraenum
fraenums
frag
fragged
fragging
fragile
fragment
fragrant
frags
frail
frailer
frailest
frailly
frails
frailty
fraise
fraises
fraktur
frakturs
framable
frame
framed
framer
framers
frames
framing
framings
franc
francium
francs
frank
franked
franker
frankers
frankest
franking
franklin
frankly
franks
frantic
frap
frappe
frapped
frappes
frapping
fraps
frass
frasses
frat
frater
fraters
frats
fraud
frauds
fraught
fraughts
fraulein
fray
frayed
fraying
frayings
frays
frazil
frazils
frazzle
frazzled
frazzles
freak
freaked
freakier
freakily
freaking
freakish
freakout
freaks
freaky
freckle
freckled
freckles
freckly
free
freebase
freebee
freebees
freebie
freebies
freeboot
freeborn
freed
freedman
freedmen
freedom
freedoms
freeform
freehand
freehold
freeing
freeload
freely
freeman
freemen
freeness
freer
freers
frees
freesia
freesias
freest
freeway
freeways
freewill
freeze
freezer
freezers
freezes
freezing
freight
freights
fremd
fremitus
frena
french
frenched
frenches
frenetic
frenula
frenulum
frenum
frenums
frenzied
frenzies
frenzily
frenzy
frequent
frere
freres
fresco
frescoed
frescoer
frescoes
frescos
fresh
freshed
freshen
freshens
fresher
freshes
freshest
freshet
freshets
freshing
freshly
freshman
freshmen
fresnel
fresnels
fret
fretful
fretless
frets
fretsaw
fretsaws
fretsome
fretted
fretter
fretters
frettier
fretting
fretty
fretwork
friable
friar
friaries
friarly
friars
friary
fribble
fribbled
fribbler
fribbles
fricando
friction
fridge
fridges
fried
friend
friended
friendly
friends
frier
friers
fries
frieze
friezes
frig
frigate
frigates
frigged
frigging
fright
frighted
frighten
frights
frigid
frigidly
frigs
frijol
frijole
frijoles
frill
frilled
friller
frillers
frillier
frilling
frills
frilly
fringe
fringed
fringes
fringier
fringing
fringy
frippery
frise
frises
frisette
friseur
friseurs
frisk
frisked
frisker
friskers
frisket
friskets
friskier
friskily
frisking
frisks
frisky
frisson
frissons
frit
frith
friths
frits
fritt
frittata
fritted
fritter
fritters
fritting
fritts
fritz
fritzes
frivol
frivoled
frivoler
frivols
friz
frized
frizer
frizers
frizes
frizette
frizing
frizz
frizzed
frizzer
frizzers
frizzes
frizzier
frizzily
frizzing
frizzle
frizzled
frizzler
frizzles
frizzly
frizzy
fro
frock
frocked
frocking
frocks
froe
froes
frog
frogeye
frogeyed
frogeyes
frogfish
frogged
froggier
frogging
froggy
froglike
frogman
frogmen
frogs
frolic
frolicky
frolics
from
fromage
fromages
fromenty
frond
fronded
frondeur
frondose
fronds
frons
front
frontage
frontal
frontals
fronted
fronter
frontes
frontier
fronting
frontlet
fronton
frontons
fronts
frore
frosh
frost
frostbit
frosted
frosteds
frostier
frostily
frosting
frosts
frosty
froth
frothed
frothier
frothily
frothing
froths
frothy
frottage
frotteur
froufrou
frounce
frounced
frounces
frouzier
frouzy
frow
froward
frown
frowned
frowner
frowners
frowning
frowns
frows
frowsier
frowst
frowsted
frowsts
frowsty
frowsy
frowzier
frowzily
frowzy
froze
frozen
frozenly
fructify
fructose
frug
frugal
frugally
frugged
frugging
frugs
fruit
fruitage
fruited
fruiter
fruiters
fruitful
fruitier
fruitily
fruiting
fruition
fruitlet
fruits
fruity
frumenty
frump
frumpier
frumpily
frumpish
frumps
frumpy
frusta
frustule
frustum
frustums
fry
fryer
fryers
frying
frypan
frypans
fub
fubbed
fubbing
fubs
fubsier
fubsiest
fubsy
fuchsia
fuchsias
fuchsin
fuchsine
fuchsins
fuci
fuck
fucked
fucker
fuckers
fucking
fucks
fuckup
fuckups
fucoid
fucoidal
fucoids
fucose
fucoses
fucous
fucus
fucuses
fud
fuddle
fuddled
fuddles
fuddling
fudge
fudged
fudges
fudging
fuds
fuehrer
fuehrers
fuel
fueled
fueler
fuelers
fueling
fuelled
fueller
fuellers
fuelling
fuels
fuelwood
fug
fugacity
fugal
fugally
fugato
fugatos
fugged
fuggier
fuggiest
fuggily
fugging
fuggy
fugio
fugios
fugitive
fugle
fugled
fugleman
fuglemen
fugles
fugling
fugs
fugu
fugue
fugued
fugues
fuguing
fuguist
fuguists
fugus
fuhrer
fuhrers
fuji
fujis
fulcra
fulcrum
fulcrums
fulfil
fulfill
fulfills
fulfils
fulgent
fulgid
fulham
fulhams
full
fullam
fullams
fullback
fulled
fuller
fullered
fullers
fullery
fullest
fullface
fulling
fullness
fulls
fully
fulmar
fulmars
fulmine
fulmined
fulmines
fulminic
fulness
fulsome
fulvous
fumarase
fumarate
fumaric
fumarole
fumatory
fumble
fumbled
fumbler
fumblers
fumbles
fumbling
fume
fumed
fumeless
fumelike
fumer
fumers
fumes
fumet
fumets
fumette
fumettes
fumier
fumiest
fumigant
fumigate
fuming
fumingly
fumitory
fumuli
fumulus
fumy
fun
function
functor
functors
fund
funded
fundi
fundic
funding
funds
fundus
funeral
funerals
funerary
funereal
funest
funfair
funfairs
fungal
fungals
fungi
fungible
fungic
fungo
fungoes
fungoid
fungoids
fungous
fungus
funguses
funicle
funicles
funiculi
funk
funked
funker
funkers
funkia
funkias
funkier
funkiest
funking
funks
funky
funned
funnel
funneled
funnels
funner
funnest
funnier
funnies
funniest
funnily
funning
funny
funnyman
funnymen
funs
fur
furan
furane
furanes
furanose
furans
furbelow
furbish
furcate
furcated
furcates
furcraea
furcula
furculae
furcular
furculum
furfur
furfural
furfuran
furfures
furibund
furies
furioso
furious
furl
furlable
furled
furler
furlers
furless
furling
furlong
furlongs
furlough
furls
furmenty
furmety
furmity
furnace
furnaced
furnaces
furnish
furor
furore
furores
furors
furred
furrier
furriers
furriery
furriest
furrily
furriner
furring
furrings
furrow
furrowed
furrower
furrows
furrowy
furry
furs
further
furthers
furthest
furtive
furuncle
fury
furze
furzes
furzier
furziest
furzy
fusain
fusains
fuscous
fuse
fused
fusee
fusees
fusel
fuselage
fuseless
fusels
fuses
fusible
fusibly
fusiform
fusil
fusile
fusileer
fusilier
fusilli
fusillis
fusils
fusing
fusion
fusions
fuss
fussed
fusser
fussers
fusses
fussier
fussiest
fussily
fussing
fusspot
fusspots
fussy
fustian
fustians
fustic
fustics
fustier
fustiest
fustily
fusty
futharc
futharcs
futhark
futharks
futhorc
futhorcs
futhork
futhorks
futile
futilely
futility
futon
futons
futtock
futtocks
futural
future
futures
futurism
futurist
futurity
futz
futzed
futzes
futzing
fuze
fuzed
fuzee
fuzees
fuzes
fuzil
fuzils
fuzing
fuzz
fuzzed
fuzzes
fuzzier
fuzziest
fuzzily
fuzzing
fuzzy
fyce
fyces
fyke
fykes
fylfot
fylfots
fytte
fyttes
gab
gabbard
gabbards
gabbart
gabbarts
gabbed
gabber
gabbers
gabbier
gabbiest
gabbing
gabble
gabbled
gabbler
gabblers
gabbles
gabbling
gabbro
gabbroic
gabbroid
gabbros
gabby
gabelle
gabelled
gabelles
gabfest
gabfests
gabies
gabion
gabions
gable
gabled
gables
gabling
gaboon
gaboons
gabs
gaby
gad
gadabout
gadarene
gadded
gadder
gadders
gaddi
gadding
gaddis
gadflies
gadfly
gadget
gadgetry
gadgets
gadgety
gadi
gadid
gadids
gadis
gadoid
gadoids
gadroon
gadroons
gads
gadwall
gadwalls
gadzooks
gae
gaed
gaeing
gaen
gaes
gaff
gaffe
gaffed
gaffer
gaffers
gaffes
gaffing
gaffs
gag
gaga
gagaku
gagakus
gage
gaged
gager
gagers
gages
gagged
gagger
gaggers
gagging
gaggle
gaggled
gaggles
gaggling
gaging
gagman
gagmen
gags
gagster
gagsters
gahnite
gahnites
gaieties
gaiety
gaijin
gaily
gain
gainable
gained
gainer
gainers
gainful
gaining
gainless
gainlier
gainly
gains
gainsaid
gainsay
gainsays
gainst
gait
gaited
gaiter
gaiters
gaiting
gaits
gal
gala
galabia
galabias
galabieh
galabiya
galactic
galago
galagos
galah
galahs
galangal
galas
galatea
galateas
galavant
galax
galaxes
galaxies
galaxy
galbanum
gale
galea
galeae
galeas
galeate
galeated
galena
galenas
galenic
galenite
galere
galeres
gales
galilee
galilees
galiot
galiots
galipot
galipots
galivant
gall
gallant
gallants
gallate
gallates
galleass
galled
gallein
galleins
galleon
galleons
galleria
gallery
gallet
galleta
galletas
galleted
gallets
galley
galleys
gallfly
galliard
galliass
gallic
gallican
gallied
gallies
galling
galliot
galliots
gallipot
gallium
galliums
gallnut
gallnuts
gallon
gallons
galloon
galloons
galloot
galloots
gallop
galloped
galloper
gallops
gallous
gallows
galls
gallus
gallused
galluses
gally
gallying
galoot
galoots
galop
galopade
galoped
galoping
galops
galore
galores
galosh
galoshe
galoshed
galoshes
gals
galumph
galumphs
galvanic
galyac
galyacs
galyak
galyaks
gam
gama
gamas
gamashes
gamay
gamays
gamb
gamba
gambade
gambades
gambado
gambados
gambas
gambe
gambes
gambeson
gambia
gambias
gambier
gambiers
gambir
gambirs
gambit
gambits
gamble
gambled
gambler
gamblers
gambles
gambling
gamboge
gamboges
gambol
gamboled
gambols
gambrel
gambrels
gambs
gambusia
game
gamecock
gamed
gamelan
gamelans
gamelike
gamely
gameness
gamer
gamers
games
gamesman
gamesmen
gamesome
gamest
gamester
gamete
gametes
gametic
gamey
gamic
gamier
gamiest
gamily
gamin
gamine
gamines
gaminess
gaming
gamings
gamins
gamma
gammadia
gammas
gammed
gammer
gammers
gammier
gammiest
gamming
gammon
gammoned
gammoner
gammons
gammy
gamodeme
gamp
gamps
gams
gamut
gamuts
gamy
gan
ganache
ganaches
gander
gandered
ganders
gane
ganef
ganefs
ganev
ganevs
gang
gangbang
ganged
ganger
gangers
ganging
gangland
ganglia
ganglial
gangliar
ganglier
gangling
ganglion
gangly
gangplow
gangrel
gangrels
gangrene
gangs
gangster
gangue
gangues
gangway
gangways
ganister
ganja
ganjah
ganjahs
ganjas
gannet
gannets
ganof
ganofs
ganoid
ganoids
gantlet
gantlets
gantline
gantlope
gantries
gantry
ganymede
gaol
gaoled
gaoler
gaolers
gaoling
gaols
gap
gape
gaped
gaper
gapers
gapes
gapeseed
gapeworm
gaping
gapingly
gaposis
gapped
gappier
gappiest
gapping
gappy
gaps
gapy
gar
garage
garaged
garages
garaging
garb
garbage
garbages
garbanzo
garbed
garbing
garble
garbled
garbler
garblers
garbles
garbless
garbling
garboard
garboil
garboils
garbs
garcon
garcons
gardant
garden
gardened
gardener
gardenia
gardens
gardyloo
garfish
garganey
garget
gargets
gargety
gargle
gargled
gargler
garglers
gargles
gargling
gargoyle
garigue
garigues
garish
garishly
garland
garlands
garlic
garlicky
garlics
garment
garments
garner
garnered
garners
garnet
garnets
garni
garnish
garote
garoted
garotes
garoting
garotte
garotted
garotter
garottes
garpike
garpikes
garred
garret
garrets
garring
garrison
garron
garrons
garrote
garroted
garroter
garrotes
garrotte
gars
garter
gartered
garters
garth
garths
garvey
garveys
gas
gasalier
gasbag
gasbags
gascon
gascons
gaselier
gaseous
gases
gash
gashed
gasher
gashes
gashest
gashing
gashouse
gasified
gasifier
gasifies
gasiform
gasify
gasket
gaskets
gaskin
gasking
gaskings
gaskins
gasless
gaslight
gaslit
gasman
gasmen
gasogene
gasohol
gasohols
gasolene
gasolier
gasoline
gasp
gasped
gasper
gaspers
gasping
gasps
gassed
gasser
gassers
gasses
gassier
gassiest
gassily
gassing
gassings
gassy
gast
gasted
gaster
gasters
gastight
gasting
gastness
gastraea
gastral
gastrea
gastreas
gastric
gastrin
gastrins
gastrula
gasts
gasworks
gat
gate
gateau
gateaux
gated
gatefold
gateless
gatelike
gateman
gatemen
gatepost
gates
gateway
gateways
gather
gathered
gatherer
gathers
gating
gator
gators
gats
gauche
gauchely
gaucher
gauchest
gaucho
gauchos
gaud
gaudery
gaudier
gaudies
gaudiest
gaudily
gauds
gaudy
gauffer
gauffers
gauge
gauged
gauger
gaugers
gauges
gauging
gault
gaults
gaum
gaumed
gauming
gaums
gaun
gaunt
gaunter
gauntest
gauntlet
gauntly
gauntry
gaur
gaurs
gauss
gausses
gauze
gauzes
gauzier
gauziest
gauzily
gauzy
gavage
gavages
gave
gavel
gaveled
gaveling
gavelled
gavelock
gavels
gavial
gavials
gavot
gavots
gavotte
gavotted
gavottes
gawk
gawked
gawker
gawkers
gawkier
gawkies
gawkiest
gawkily
gawking
gawkish
gawks
gawky
gawp
gawped
gawper
gawpers
gawping
gawps
gawsie
gawsy
gay
gayal
gayals
gayer
gayest
gayeties
gayety
gayly
gayness
gays
gaywings
gazabo
gazaboes
gazabos
gazania
gazanias
gazar
gazars
gaze
gazebo
gazeboes
gazebos
gazed
gazelle
gazelles
gazer
gazers
gazes
gazette
gazetted
gazettes
gazing
gazogene
gazpacho
gazump
gazumped
gazumper
gazumps
gear
gearbox
gearcase
geared
gearing
gearings
gearless
gears
geck
gecked
gecking
gecko
geckoes
geckos
gecks
ged
geds
gee
geed
geegaw
geegaws
geeing
geek
geekier
geekiest
geeks
geeky
geepound
gees
geese
geest
geests
geez
geezer
geezers
geisha
geishas
gel
gelable
gelada
geladas
gelant
gelants
gelate
gelated
gelates
gelati
gelatin
gelatine
gelating
gelatins
gelation
gelato
gelatos
geld
gelded
gelder
gelders
gelding
geldings
gelds
gelee
gelees
gelid
gelidity
gelidly
gellant
gellants
gelled
gelling
gels
gelsemia
gelt
gelts
gem
geminal
geminate
gemlike
gemma
gemmae
gemmate
gemmated
gemmates
gemmed
gemmier
gemmiest
gemmily
gemming
gemmule
gemmules
gemmy
gemology
gemot
gemote
gemotes
gemots
gems
gemsbok
gemsboks
gemsbuck
gemstone
gen
gendarme
gender
gendered
genders
gene
genera
general
generals
generate
generic
generics
generous
genes
geneses
genesis
genet
genetic
genetics
genets
genette
genettes
geneva
genevas
genial
genially
genic
genie
genies
genii
genip
genipap
genipaps
genips
genital
genitals
genitive
genitor
genitors
geniture
genius
geniuses
genoa
genoas
genocide
genoise
genoises
genom
genome
genomes
genomic
genoms
genotype
genre
genres
genro
genros
gens
genseng
gensengs
gent
genteel
gentes
gentian
gentians
gentil
gentile
gentiles
gentle
gentled
gentler
gentles
gentlest
gentling
gently
gentoo
gentoos
gentrice
gentries
gentrify
gentry
gents
genu
genua
genuine
genus
genuses
geode
geodes
geodesic
geodesy
geodetic
geodic
geoduck
geoducks
geognosy
geoid
geoidal
geoids
geologer
geologic
geology
geomancy
geometer
geometry
geophagy
geophone
geophyte
geoponic
geoprobe
georgic
georgics
geotaxes
geotaxis
gerah
gerahs
geranial
geraniol
geranium
gerardia
gerbera
gerberas
gerbil
gerbille
gerbils
gerent
gerents
gerenuk
gerenuks
germ
german
germane
germanic
germans
germen
germens
germfree
germier
germiest
germina
germinal
germs
germy
gerontic
gerund
gerunds
gesneria
gesso
gessoed
gessoes
gest
gestalt
gestalts
gestapo
gestapos
gestate
gestated
gestates
geste
gestes
gestic
gestical
gests
gestural
gesture
gestured
gesturer
gestures
get
geta
getable
getas
getaway
getaways
gets
gettable
getter
gettered
getters
getting
getup
getups
geum
geums
gewgaw
gewgaws
gey
geyser
geysers
gharial
gharials
gharri
gharries
gharris
gharry
ghast
ghastful
ghastly
ghat
ghats
ghaut
ghauts
ghazi
ghazies
ghazis
ghee
ghees
gherao
gheraoed
gheraoes
gherkin
gherkins
ghetto
ghettoed
ghettoes
ghettos
ghi
ghibli
ghiblis
ghillie
ghillies
ghis
ghost
ghosted
ghostier
ghosting
ghostly
ghosts
ghosty
ghoul
ghoulie
ghoulies
ghoulish
ghouls
ghyll
ghylls
giant
giantess
giantism
giants
giaour
giaours
gib
gibbed
gibber
gibbered
gibbers
gibbet
gibbeted
gibbets
gibbing
gibbon
gibbons
gibbose
gibbous
gibbsite
gibe
gibed
giber
gibers
gibes
gibing
gibingly
giblet
giblets
gibs
gibson
gibsons
gid
giddap
giddied
giddier
giddies
giddiest
giddily
giddy
giddyap
giddying
giddyup
gids
gie
gied
gieing
gien
gies
gift
gifted
giftedly
gifting
giftless
gifts
giftware
gig
giga
gigabit
gigabits
gigabyte
gigantic
gigas
gigaton
gigatons
gigawatt
gigged
gigging
giggle
giggled
giggler
gigglers
giggles
gigglier
giggling
giggly
gighe
giglet
giglets
giglot
giglots
gigolo
gigolos
gigot
gigots
gigs
gigue
gigues
gilbert
gilberts
gild
gilded
gilder
gilders
gildhall
gilding
gildings
gilds
gill
gilled
giller
gillers
gillie
gillied
gillies
gilling
gillnet
gillnets
gills
gilly
gillying
gilt
gilthead
gilts
gimbal
gimbaled
gimbals
gimcrack
gimel
gimels
gimlet
gimleted
gimlets
gimmal
gimmals
gimme
gimmes
gimmick
gimmicks
gimmicky
gimmie
gimmies
gimp
gimped
gimpier
gimpiest
gimping
gimps
gimpy
gin
gingal
gingall
gingalls
gingals
gingeley
gingeli
gingelis
gingelli
gingelly
gingely
ginger
gingered
gingerly
gingers
gingery
gingham
ginghams
gingili
gingilis
gingilli
gingiva
gingivae
gingival
gingko
gingkoes
gink
ginkgo
ginkgoes
ginkgos
ginks
ginned
ginner
ginners
ginnier
ginniest
ginning
ginnings
ginny
gins
ginseng
ginsengs
gip
gipon
gipons
gipped
gipper
gippers
gipping
gips
gipsied
gipsies
gipsy
gipsying
giraffe
giraffes
girasol
girasole
girasols
gird
girded
girder
girders
girding
girdle
girdled
girdler
girdlers
girdles
girdling
girds
girl
girlhood
girlie
girlies
girlish
girls
girly
girn
girned
girning
girns
giro
giron
girons
giros
girosol
girosols
girsh
girshes
girt
girted
girth
girthed
girthing
girths
girting
girts
gisarme
gisarmes
gismo
gismos
gist
gists
git
gitano
gitanos
gits
gittern
gitterns
gittin
give
giveable
giveaway
giveback
given
givens
giver
givers
gives
giving
gizmo
gizmos
gizzard
gizzards
gjetost
gjetosts
glabella
glabrate
glabrous
glace
glaceed
glaceing
glaces
glacial
glaciate
glacier
glaciers
glacis
glacises
glad
gladded
gladden
gladdens
gladder
gladdest
gladding
glade
glades
gladiate
gladier
gladiest
gladiola
gladioli
gladlier
gladly
gladness
glads
gladsome
glady
glaiket
glaikit
glair
glaire
glaired
glaires
glairier
glairing
glairs
glairy
glaive
glaived
glaives
glamor
glamors
glamour
glamours
glance
glanced
glancer
glancers
glances
glancing
gland
glanders
glandes
glands
glandule
glans
glare
glared
glares
glarier
glariest
glaring
glary
glasnost
glass
glassed
glasses
glassful
glassie
glassier
glassies
glassily
glassine
glassing
glassman
glassmen
glassy
glaucoma
glaucous
glaze
glazed
glazer
glazers
glazes
glazier
glaziers
glaziery
glaziest
glazing
glazings
glazy
gleam
gleamed
gleamer
gleamers
gleamier
gleaming
gleams
gleamy
glean
gleaned
gleaner
gleaners
gleaning
gleans
gleba
glebae
glebe
glebes
gled
glede
gledes
gleds
glee
gleed
gleeds
gleeful
gleek
gleeked
gleeking
gleeks
gleeman
gleemen
glees
gleesome
gleet
gleeted
gleetier
gleeting
gleets
gleety
gleg
glegly
glegness
glen
glenlike
glenoid
glens
gley
gleyed
gleying
gleyings
gleys
glia
gliadin
gliadine
gliadins
glial
glias
glib
glibber
glibbest
glibly
glibness
glide
glided
glider
gliders
glides
gliding
gliff
gliffs
glim
glime
glimed
glimes
gliming
glimmer
glimmers
glimpse
glimpsed
glimpser
glimpses
glims
glint
glinted
glinting
glints
glioma
gliomas
gliomata
glissade
glisten
glistens
glister
glisters
glitch
glitches
glitchy
glitter
glitters
glittery
glitz
glitzes
glitzier
glitzy
gloam
gloaming
gloams
gloat
gloated
gloater
gloaters
gloating
gloats
glob
global
globally
globate
globated
globbier
globby
globe
globed
globes
globin
globing
globins
globoid
globoids
globose
globous
globs
globular
globule
globules
globulin
glochid
glochids
glogg
gloggs
glom
glomera
glommed
glomming
gloms
glomus
glonoin
glonoins
gloom
gloomed
gloomful
gloomier
gloomily
glooming
glooms
gloomy
glop
glopped
glopping
gloppy
glops
gloria
glorias
gloried
glories
glorify
gloriole
glorious
glory
glorying
gloss
glossa
glossae
glossal
glossary
glossas
glossed
glosseme
glosser
glossers
glosses
glossier
glossies
glossily
glossina
glossing
glossy
glost
glosts
glottal
glottic
glottis
glout
glouted
glouting
glouts
glove
gloved
glover
glovers
gloves
gloving
glow
glowed
glower
glowered
glowers
glowfly
glowing
glows
glowworm
gloxinia
gloze
glozed
glozes
glozing
glucagon
glucan
glucans
glucinic
glucinum
glucose
glucoses
glucosic
glue
glued
glueing
gluelike
gluepot
gluepots
gluer
gluers
glues
gluey
glug
glugged
glugging
glugs
gluier
gluiest
gluily
gluing
glum
glume
glumes
glumly
glummer
glummest
glumness
glumpier
glumpily
glumpy
glunch
glunched
glunches
gluon
gluons
glut
gluteal
glutei
glutelin
gluten
glutens
gluteus
gluts
glutted
glutting
glutton
gluttons
gluttony
glycan
glycans
glyceric
glycerin
glycerol
glyceryl
glycin
glycine
glycines
glycins
glycogen
glycol
glycolic
glycols
glyconic
glycosyl
glycyl
glycyls
glyph
glyphic
glyphs
glyptic
glyptics
gnar
gnarl
gnarled
gnarlier
gnarling
gnarls
gnarly
gnarr
gnarred
gnarring
gnarrs
gnars
gnash
gnashed
gnashes
gnashing
gnat
gnathal
gnathic
gnathion
gnathite
gnatlike
gnats
gnattier
gnatty
gnaw
gnawable
gnawed
gnawer
gnawers
gnawing
gnawings
gnawn
gnaws
gneiss
gneisses
gneissic
gnocchi
gnome
gnomes
gnomic
gnomical
gnomish
gnomist
gnomists
gnomon
gnomonic
gnomons
gnoses
gnosis
gnostic
gnu
gnus
go
goa
goad
goaded
goading
goadlike
goads
goal
goaled
goalie
goalies
goaling
goalless
goalpost
goals
goalward
goanna
goannas
goas
goat
goatee
goateed
goatees
goatfish
goatherd
goatish
goatlike
goats
goatskin
gob
goban
gobang
gobangs
gobans
gobbed
gobbet
gobbets
gobbing
gobble
gobbled
gobbler
gobblers
gobbles
gobbling
gobies
gobioid
gobioids
goblet
goblets
goblin
goblins
gobo
goboes
gobonee
gobony
gobos
gobs
goby
god
godchild
goddam
goddamn
goddamns
goddams
godded
goddess
godding
godet
godets
godhead
godheads
godhood
godhoods
godless
godlier
godliest
godlike
godlily
godling
godlings
godly
godown
godowns
godroon
godroons
gods
godsend
godsends
godship
godships
godson
godsons
godwit
godwits
goer
goers
goes
goethite
gofer
gofers
goffer
goffered
goffers
goggle
goggled
goggler
gogglers
goggles
gogglier
goggling
goggly
goglet
goglets
gogo
gogos
going
goings
goiter
goiters
goitre
goitres
goitrous
golconda
gold
goldarn
goldarns
goldbug
goldbugs
golden
goldener
goldenly
golder
goldest
goldeye
goldeyes
goldfish
golds
goldurn
goldurns
golem
golems
golf
golfed
golfer
golfers
golfing
golfings
golfs
golgotha
goliard
goliards
golliwog
golly
gollywog
golosh
goloshe
goloshes
gombo
gombos
gombroon
gomeral
gomerals
gomerel
gomerels
gomeril
gomerils
gomuti
gomutis
gonad
gonadal
gonadial
gonadic
gonads
gondola
gondolas
gone
gonef
gonefs
goneness
goner
goners
gonfalon
gonfanon
gong
gonged
gonging
gonglike
gongs
gonia
gonidia
gonidial
gonidic
gonidium
gonif
goniff
goniffs
gonifs
gonion
gonium
gonocyte
gonof
gonofs
gonoph
gonophs
gonopore
gonzo
goo
goober
goobers
good
goodby
goodbye
goodbyes
goodbys
goodie
goodies
goodish
goodlier
goodly
goodman
goodmen
goodness
goods
goodwife
goodwill
goody
gooey
goof
goofball
goofed
goofier
goofiest
goofily
goofing
goofs
goofy
googlies
googly
googol
googols
gooier
gooiest
gook
gooks
gooky
goombah
goombahs
goombay
goombays
goon
gooney
gooneys
goonie
goonies
goons
goony
goop
goopier
goopiest
goops
goopy
gooral
goorals
goos
goose
goosed
gooses
goosey
goosier
goosiest
goosing
goosy
gopher
gophers
gor
goral
gorals
gorbelly
gorblimy
gorcock
gorcocks
gore
gored
gores
gorge
gorged
gorgedly
gorgeous
gorger
gorgerin
gorgers
gorges
gorget
gorgeted
gorgets
gorging
gorgon
gorgons
gorhen
gorhens
gorier
goriest
gorilla
gorillas
gorily
goriness
goring
gormand
gormands
gormless
gorp
gorps
gorse
gorses
gorsier
gorsiest
gorsy
gory
gosh
goshawk
goshawks
gosling
goslings
gospel
gospeler
gospels
gosport
gosports
gossamer
gossan
gossans
gossip
gossiped
gossiper
gossipry
gossips
gossipy
gossoon
gossoons
gossypol
got
gothic
gothics
gothite
gothites
gotten
gouache
gouaches
gouge
gouged
gouger
gougers
gouges
gouging
goulash
gourami
gouramis
gourd
gourde
gourdes
gourds
gourmand
gourmet
gourmets
gout
goutier
goutiest
goutily
gouts
gouty
govern
governed
governor
governs
gowan
gowaned
gowans
gowany
gowd
gowds
gowk
gowks
gown
gowned
gowning
gowns
gownsman
gownsmen
gox
goxes
goy
goyim
goyish
goys
graal
graals
grab
grabbed
grabber
grabbers
grabbier
grabbing
grabble
grabbled
grabbler
grabbles
grabby
graben
grabens
grabs
grace
graced
graceful
graces
gracile
graciles
gracilis
gracing
gracioso
gracious
grackle
grackles
grad
gradable
gradate
gradated
gradates
grade
graded
grader
graders
grades
gradient
gradin
gradine
gradines
grading
gradins
grads
gradual
graduals
graduand
graduate
gradus
graduses
graecize
graffiti
graffito
graft
graftage
grafted
grafter
grafters
grafting
grafts
graham
grahams
grail
grails
grain
grained
grainer
grainers
grainier
graining
grains
grainy
gram
grama
gramary
gramarye
gramas
gramercy
grammar
grammars
gramme
grammes
gramp
gramps
grampus
grams
gran
grana
granary
grand
grandad
grandads
grandam
grandame
grandams
granddad
granddam
grandee
grandees
grander
grandest
grandeur
grandkid
grandly
grandma
grandmas
grandpa
grandpas
grands
grandsir
grandson
grange
granger
grangers
granges
granita
granitas
granite
granites
granitic
grannie
grannies
granny
granola
granolas
grans
grant
granted
grantee
grantees
granter
granters
granting
grantor
grantors
grants
granular
granule
granules
granum
grape
grapery
grapes
grapey
graph
graphed
grapheme
graphic
graphics
graphing
graphite
graphs
grapier
grapiest
graplin
grapline
graplins
grapnel
grapnels
grappa
grappas
grapple
grappled
grappler
grapples
grapy
grasp
grasped
grasper
graspers
grasping
grasps
grass
grassed
grasses
grassier
grassily
grassing
grassy
grat
grate
grated
grateful
grater
graters
grates
gratify
gratin
gratine
gratinee
grating
gratings
gratins
gratis
gratuity
graupel
graupels
gravamen
grave
graved
gravel
graveled
gravelly
gravels
gravely
graven
graver
gravers
graves
gravest
gravid
gravida
gravidae
gravidas
gravidly
gravies
graving
gravitas
graviton
gravity
gravlaks
gravlax
gravure
gravures
gravy
gray
grayback
grayed
grayer
grayest
grayfish
graying
grayish
graylag
graylags
grayling
grayly
graymail
grayness
grayout
grayouts
grays
grazable
graze
grazed
grazer
grazers
grazes
grazier
graziers
grazing
grazings
grazioso
grease
greased
greaser
greasers
greases
greasier
greasily
greasing
greasy
great
greaten
greatens
greater
greatest
greatly
greats
greave
greaved
greaves
grebe
grebes
grecize
grecized
grecizes
gree
greed
greedier
greedily
greeds
greedy
greegree
greeing
greek
green
greenbug
greened
greener
greenery
greenest
greenfly
greenie
greenier
greenies
greening
greenish
greenlet
greenly
greens
greenth
greenths
greenway
greeny
grees
greet
greeted
greeter
greeters
greeting
greets
grego
gregos
greige
greiges
greisen
greisens
gremial
gremials
gremlin
gremlins
gremmie
gremmies
gremmy
grenade
grenades
grew
grewsome
grey
greyed
greyer
greyest
greyhen
greyhens
greying
greyish
greylag
greylags
greyly
greyness
greys
gribble
gribbles
grid
gridder
gridders
griddle
griddled
griddles
gride
grided
grides
griding
gridiron
gridlock
grids
grief
griefs
grievant
grieve
grieved
griever
grievers
grieves
grieving
grievous
griff
griffe
griffes
griffin
griffins
griffon
griffons
griffs
grift
grifted
grifter
grifters
grifting
grifts
grig
grigri
grigris
grigs
grill
grillade
grillage
grille
grilled
griller
grillers
grilles
grilling
grills
grilse
grilses
grim
grimace
grimaced
grimacer
grimaces
grime
grimed
grimes
grimier
grimiest
grimily
griming
grimly
grimmer
grimmest
grimness
grimy
grin
grinch
grinches
grind
grinded
grinder
grinders
grindery
grinding
grinds
gringo
gringos
grinned
grinner
grinners
grinning
grins
griot
griots
grip
gripe
griped
griper
gripers
gripes
gripey
gripier
gripiest
griping
gripman
gripmen
grippe
gripped
gripper
grippers
grippes
grippier
gripping
gripple
grippy
grips
gripsack
gript
gripy
griseous
grisette
griskin
griskins
grislier
grisly
grison
grisons
grist
gristle
gristles
gristly
grists
grit
grith
griths
grits
gritted
grittier
grittily
gritting
gritty
grivet
grivets
grizzle
grizzled
grizzler
grizzles
grizzly
groan
groaned
groaner
groaners
groaning
groans
groat
groats
grocer
grocers
grocery
grog
groggery
groggier
groggily
groggy
grogram
grograms
grogs
grogshop
groin
groined
groining
groins
grommet
grommets
gromwell
groom
groomed
groomer
groomers
grooming
grooms
groove
grooved
groover
groovers
grooves
groovier
grooving
groovy
grope
groped
groper
gropers
gropes
groping
grosbeak
groschen
gross
grossed
grosser
grossers
grosses
grossest
grossing
grossly
grosz
grosze
groszy
grot
grots
grottier
grotto
grottoes
grottos
grotty
grouch
grouched
grouches
grouchy
ground
grounded
grounder
grounds
group
grouped
grouper
groupers
groupie
groupies
grouping
groupoid
groups
grouse
groused
grouser
grousers
grouses
grousing
grout
grouted
grouter
grouters
groutier
grouting
grouts
grouty
grove
groved
grovel
groveled
groveler
grovels
groves
grow
growable
grower
growers
growing
growl
growled
growler
growlers
growlier
growling
growls
growly
grown
grownup
grownups
grows
growth
growths
growthy
groyne
groynes
grub
grubbed
grubber
grubbers
grubbier
grubbily
grubbing
grubby
grubs
grubworm
grudge
grudged
grudger
grudgers
grudges
grudging
grue
gruel
grueled
grueler
gruelers
grueling
gruelled
grueller
gruels
grues
gruesome
gruff
gruffed
gruffer
gruffest
gruffier
gruffily
gruffing
gruffish
gruffly
gruffs
gruffy
grugru
grugrus
gruiform
grum
grumble
grumbled
grumbler
grumbles
grumbly
grume
grumes
grummer
grummest
grummet
grummets
grumose
grumous
grump
grumped
grumphie
grumphy
grumpier
grumpily
grumping
grumpish
grumps
grumpy
grunge
grunges
grungier
grungy
grunion
grunions
grunt
grunted
grunter
grunters
grunting
gruntle
gruntled
gruntles
grunts
grushie
grutch
grutched
grutches
grutten
gruyere
gruyeres
gryphon
gryphons
guacharo
guaco
guacos
guaiac
guaiacol
guaiacs
guaiacum
guaiocum
guan
guanaco
guanacos
guanase
guanases
guanay
guanays
guanidin
guanin
guanine
guanines
guanins
guano
guanos
guans
guar
guarani
guaranis
guaranty
guard
guardant
guarded
guarder
guarders
guardian
guarding
guards
guars
guava
guavas
guayule
guayules
guck
gucks
gude
gudes
gudgeon
gudgeons
guenon
guenons
guerdon
guerdons
gueridon
guerilla
guernsey
guess
guessed
guesser
guessers
guesses
guessing
guest
guested
guesting
guests
guff
guffaw
guffawed
guffaws
guffs
guggle
guggled
guggles
guggling
guglet
guglets
guid
guidable
guidance
guide
guided
guider
guiders
guides
guideway
guiding
guidon
guidons
guids
guild
guilder
guilders
guilds
guile
guiled
guileful
guiles
guiling
guilt
guiltier
guiltily
guilts
guilty
guimpe
guimpes
guinea
guineas
guipure
guipures
guiro
guiros
guisard
guisards
guise
guised
guises
guising
guitar
guitars
guitguit
gul
gulag
gulags
gular
gulch
gulches
gulden
guldens
gules
gulf
gulfed
gulfier
gulfiest
gulfing
gulflike
gulfs
gulfweed
gulfy
gull
gullable
gullably
gulled
gullet
gullets
gulley
gulleys
gullible
gullibly
gullied
gullies
gulling
gulls
gully
gullying
gulosity
gulp
gulped
gulper
gulpers
gulpier
gulpiest
gulping
gulps
gulpy
guls
gum
gumbo
gumboil
gumboils
gumboot
gumboots
gumbos
gumbotil
gumdrop
gumdrops
gumless
gumlike
gumma
gummas
gummata
gummed
gummer
gummers
gummier
gummiest
gumming
gummite
gummites
gummose
gummoses
gummosis
gummous
gummy
gumption
gums
gumshoe
gumshoed
gumshoes
gumtree
gumtrees
gumweed
gumweeds
gumwood
gumwoods
gun
gunboat
gunboats
gundog
gundogs
gunfight
gunfire
gunfires
gunflint
gunite
gunites
gunk
gunkhole
gunks
gunky
gunless
gunlock
gunlocks
gunman
gunmen
gunmetal
gunned
gunnel
gunnels
gunnen
gunner
gunners
gunnery
gunnies
gunning
gunnings
gunny
gunnybag
gunpaper
gunplay
gunplays
gunpoint
gunroom
gunrooms
guns
gunsel
gunsels
gunship
gunships
gunshot
gunshots
gunsmith
gunstock
gunwale
gunwales
guppies
guppy
gurge
gurged
gurges
gurging
gurgle
gurgled
gurgles
gurglet
gurglets
gurgling
gurnard
gurnards
gurnet
gurnets
gurney
gurneys
gurries
gurry
gursh
gurshes
guru
gurus
guruship
gush
gushed
gusher
gushers
gushes
gushier
gushiest
gushily
gushing
gushy
gusset
gusseted
gussets
gussie
gussied
gussies
gussy
gussying
gust
gustable
gusted
gustier
gustiest
gustily
gusting
gustless
gusto
gustoes
gusts
gusty
gut
gutless
gutlike
guts
gutsier
gutsiest
gutsily
gutsy
gutta
guttae
guttate
guttated
gutted
gutter
guttered
gutters
guttery
guttier
guttiest
gutting
guttle
guttled
guttler
guttlers
guttles
guttling
guttural
gutty
guv
guvs
guy
guyed
guying
guyline
guylines
guyot
guyots
guys
guzzle
guzzled
guzzler
guzzlers
guzzles
guzzling
gweduc
gweduck
gweducks
gweducs
gybe
gybed
gybes
gybing
gym
gymkhana
gymnasia
gymnast
gymnasts
gyms
gynaecea
gynaecia
gynandry
gynarchy
gynecia
gynecic
gynecium
gynecoid
gyniatry
gynoecia
gyp
gyplure
gyplures
gypped
gypper
gyppers
gypping
gyps
gypseian
gypseous
gypsied
gypsies
gypster
gypsters
gypsum
gypsums
gypsy
gypsydom
gypsying
gypsyish
gypsyism
gyral
gyrally
gyrase
gyrases
gyrate
gyrated
gyrates
gyrating
gyration
gyrator
gyrators
gyratory
gyre
gyred
gyrene
gyrenes
gyres
gyri
gyring
gyro
gyroidal
gyron
gyrons
gyros
gyrose
gyrostat
gyrus
gyve
gyved
gyves
gyving
ha
haaf
haafs
haar
haars
habanera
habdalah
habile
habit
habitan
habitans
habitant
habitat
habitats
habited
habiting
habits
habitual
habitude
habitue
habitues
habitus
haboob
haboobs
habu
habus
hacek
haceks
hachure
hachured
hachures
hacienda
hack
hackbut
hackbuts
hacked
hackee
hackees
hacker
hackers
hackie
hackies
hacking
hackle
hackled
hackler
hacklers
hackles
hacklier
hackling
hackly
hackman
hackmen
hackney
hackneys
hacks
hacksaw
hacksaws
hackwork
had
hadal
hadarim
haddest
haddock
haddocks
hade
haded
hades
hading
hadith
hadiths
hadj
hadjee
hadjees
hadjes
hadji
hadjis
hadron
hadronic
hadrons
hadst
hae
haed
haeing
haem
haemal
haematal
haematic
haematin
haemic
haemin
haemins
haemoid
haems
haen
haeredes
haeres
haes
haet
haets
haffet
haffets
haffit
haffits
hafis
hafiz
hafnium
hafniums
haft
haftara
haftarah
haftaras
haftarot
hafted
hafter
hafters
hafting
haftorah
haftorot
hafts
hag
hagadic
hagadist
hagberry
hagborn
hagbush
hagbut
hagbuts
hagdon
hagdons
hagfish
haggada
haggadah
haggadas
haggadic
haggadot
haggard
haggards
hagged
hagging
haggis
haggises
haggish
haggle
haggled
haggler
hagglers
haggles
haggling
hagride
hagrides
hagrode
hags
hah
haha
hahas
hahnium
hahniums
hahs
haik
haika
haiks
haiku
hail
hailed
hailer
hailers
hailing
hails
hair
hairball
hairband
haircap
haircaps
haircut
haircuts
hairdo
hairdos
haired
hairier
hairiest
hairless
hairlike
hairline
hairlock
hairnet
hairnets
hairpin
hairpins
hairs
hairwork
hairworm
hairy
haj
hajes
haji
hajis
hajj
hajjes
hajji
hajjis
hake
hakeem
hakeems
hakes
hakim
hakims
halacha
halachas
halachot
halakah
halakahs
halakha
halakhas
halakhot
halakic
halakist
halakoth
halala
halalah
halalahs
halalas
halation
halavah
halavahs
halazone
halberd
halberds
halbert
halberts
halcyon
halcyons
hale
haled
haleness
haler
halers
haleru
hales
halest
half
halfback
halfbeak
halflife
halfness
halftime
halftone
halfway
halibut
halibuts
halid
halide
halides
halidom
halidome
halidoms
halids
haling
halite
halites
halitus
hall
hallah
hallahs
hallel
hallels
halliard
hallmark
hallo
halloa
halloaed
halloas
halloed
halloes
halloing
halloo
hallooed
halloos
hallos
hallot
halloth
hallow
hallowed
hallower
hallows
halls
halluces
hallux
hallway
hallways
halm
halma
halmas
halms
halo
haloed
haloes
halogen
halogens
haloid
haloids
haloing
halolike
halos
halt
halted
halter
haltere
haltered
halteres
halters
halting
haltless
halts
halutz
halutzim
halva
halvah
halvahs
halvas
halve
halved
halvers
halves
halving
halyard
halyards
ham
hamada
hamadas
hamal
hamals
hamartia
hamate
hamates
hamaul
hamauls
hambone
hamboned
hambones
hamburg
hamburgs
hame
hames
hamlet
hamlets
hammada
hammadas
hammal
hammals
hammed
hammer
hammered
hammerer
hammers
hammier
hammiest
hammily
hamming
hammock
hammocks
hammy
hamper
hampered
hamperer
hampers
hams
hamster
hamsters
hamular
hamulate
hamuli
hamulose
hamulous
hamulus
hamza
hamzah
hamzahs
hamzas
hanaper
hanapers
hance
hances
hand
handbag
handbags
handball
handbell
handbill
handbook
handcar
handcars
handcart
handcuff
handed
handfast
handful
handfuls
handgrip
handgun
handguns
handheld
handhold
handicap
handier
handiest
handily
handing
handle
handled
handler
handlers
handles
handless
handlike
handling
handlist
handloom
handmade
handmaid
handoff
handoffs
handout
handouts
handover
handpick
handrail
hands
handsaw
handsaws
handsel
handsels
handset
handsets
handsewn
handsful
handsome
handwork
handwrit
handy
handyman
handymen
hang
hangable
hangar
hangared
hangars
hangbird
hangdog
hangdogs
hanged
hanger
hangers
hangfire
hanging
hangings
hangman
hangmen
hangnail
hangnest
hangout
hangouts
hangover
hangs
hangtag
hangtags
hangul
hangup
hangups
haniwa
hank
hanked
hanker
hankered
hankerer
hankers
hankie
hankies
hanking
hanks
hanky
hansa
hansas
hanse
hansel
hanseled
hansels
hanses
hansom
hansoms
hant
hanted
hanting
hantle
hantles
hants
hanuman
hanumans
hao
haole
haoles
hap
hapax
hapaxes
haphtara
hapless
haplite
haplites
haploid
haploids
haploidy
haplont
haplonts
haplopia
haploses
haplosis
haply
happed
happen
happened
happens
happier
happiest
happily
happing
happy
haps
hapten
haptene
haptenes
haptenic
haptens
haptic
haptical
harangue
harass
harassed
harasser
harasses
harbor
harbored
harborer
harbors
harbour
harbours
hard
hardback
hardball
hardboot
hardcase
hardcore
hardedge
harden
hardened
hardener
hardens
harder
hardest
hardhack
hardhat
hardhats
hardhead
hardier
hardies
hardiest
hardily
hardline
hardly
hardness
hardnose
hardpan
hardpans
hards
hardset
hardship
hardtack
hardtop
hardtops
hardware
hardwire
hardwood
hardy
hare
harebell
hared
hareem
hareems
harelike
harelip
harelips
harem
harems
hares
hariana
harianas
haricot
haricots
harijan
harijans
haring
hark
harked
harken
harkened
harkener
harkens
harking
harks
harl
harlot
harlotry
harlots
harls
harm
harmed
harmer
harmers
harmful
harmin
harmine
harmines
harming
harmins
harmless
harmonic
harmony
harms
harness
harp
harped
harper
harpers
harpies
harpin
harping
harpings
harpins
harpist
harpists
harpoon
harpoons
harps
harpy
harridan
harried
harrier
harriers
harries
harrow
harrowed
harrower
harrows
harrumph
harry
harrying
harsh
harshen
harshens
harsher
harshest
harshly
harslet
harslets
hart
hartal
hartals
harts
harumph
harumphs
haruspex
harvest
harvests
has
hash
hashed
hasheesh
hashes
hashhead
hashing
hashish
haslet
haslets
hasp
hasped
hasping
hasps
hassel
hassels
hassle
hassled
hassles
hassling
hassock
hassocks
hast
hastate
haste
hasted
hasteful
hasten
hastened
hastener
hastens
hastes
hastier
hastiest
hastily
hasting
hasty
hat
hatable
hatband
hatbands
hatbox
hatboxes
hatch
hatcheck
hatched
hatchel
hatchels
hatcher
hatchers
hatchery
hatches
hatchet
hatchets
hatching
hatchway
hate
hateable
hated
hateful
hater
haters
hates
hatful
hatfuls
hath
hating
hatless
hatlike
hatmaker
hatpin
hatpins
hatrack
hatracks
hatred
hatreds
hats
hatsful
hatted
hatter
hatteria
hatters
hatting
hauberk
hauberks
haugh
haughs
haughty
haul
haulage
haulages
hauled
hauler
haulers
haulier
hauliers
hauling
haulm
haulmier
haulms
haulmy
hauls
haulyard
haunch
haunched
haunches
haunt
haunted
haunter
haunters
haunting
haunts
hausen
hausens
hausfrau
haut
hautbois
hautboy
hautboys
haute
hauteur
hauteurs
havarti
havartis
havdalah
have
havelock
haven
havened
havening
havens
haver
havered
haverel
haverels
havering
havers
haves
having
havior
haviors
haviour
haviours
havoc
havocked
havocker
havocs
haw
hawed
hawfinch
hawing
hawk
hawkbill
hawked
hawker
hawkers
hawkey
hawkeyed
hawkeys
hawkie
hawkies
hawking
hawkings
hawkish
hawklike
hawkmoth
hawknose
hawks
hawkshaw
hawkweed
haws
hawse
hawser
hawsers
hawses
hawthorn
hay
haycock
haycocks
hayed
hayer
hayers
hayfield
hayfork
hayforks
haying
hayings
haylage
haylages
hayloft
haylofts
haymaker
haymow
haymows
hayrack
hayracks
hayrick
hayricks
hayride
hayrides
hays
hayseed
hayseeds
haystack
hayward
haywards
haywire
haywires
hazan
hazanim
hazans
hazard
hazarded
hazards
haze
hazed
hazel
hazelhen
hazelly
hazelnut
hazels
hazer
hazers
hazes
hazier
haziest
hazily
haziness
hazing
hazings
hazy
hazzan
hazzanim
hazzans
he
head
headache
headachy
headband
headed
header
headers
headfish
headgate
headgear
headhunt
headier
headiest
headily
heading
headings
headlamp
headland
headless
headline
headlock
headlong
headman
headmen
headmost
headnote
headpin
headpins
headrace
headrest
headroom
heads
headsail
headset
headsets
headship
headsman
headsmen
headstay
headway
headways
headwind
headword
headwork
heady
heal
healable
healed
healer
healers
healing
heals
health
healths
healthy
heap
heaped
heaping
heaps
hear
hearable
heard
hearer
hearers
hearing
hearings
hearken
hearkens
hears
hearsay
hearsays
hearse
hearsed
hearses
hearsing
heart
hearted
hearten
heartens
hearth
hearths
heartier
hearties
heartily
hearting
hearts
hearty
heat
heatable
heated
heatedly
heater
heaters
heath
heathen
heathens
heather
heathers
heathery
heathier
heaths
heathy
heating
heatless
heats
heaume
heaumes
heave
heaved
heaven
heavenly
heavens
heaver
heavers
heaves
heavier
heavies
heaviest
heavily
heaving
heavy
heavyset
hebdomad
hebe
hebes
hebetate
hebetic
hebetude
hebraize
hecatomb
heck
heckle
heckled
heckler
hecklers
heckles
heckling
hecks
hectare
hectares
hectic
hectical
hecticly
hector
hectored
hectors
heddle
heddles
heder
heders
hedge
hedged
hedgehog
hedgehop
hedgepig
hedger
hedgerow
hedgers
hedges
hedgier
hedgiest
hedging
hedgy
hedonic
hedonics
hedonism
hedonist
heed
heeded
heeder
heeders
heedful
heeding
heedless
heeds
heehaw
heehawed
heehaws
heel
heelball
heeled
heeler
heelers
heeling
heelings
heelless
heelpost
heels
heeltap
heeltaps
heeze
heezed
heezes
heezing
heft
hefted
hefter
hefters
heftier
heftiest
heftily
hefting
hefts
hefty
hegari
hegaris
hegemony
hegira
hegiras
hegumen
hegumene
hegumens
hegumeny
heh
hehs
heifer
heifers
heigh
height
heighten
heighth
heighths
heights
heil
heiled
heiling
heils
heimish
heinie
heinies
heinous
heir
heirdom
heirdoms
heired
heiress
heiring
heirless
heirloom
heirs
heirship
heishi
heist
heisted
heister
heisters
heisting
heists
hejira
hejiras
hektare
hektares
held
heliac
heliacal
heliast
heliasts
helical
helices
helicity
helicoid
helicon
helicons
helicopt
helilift
helio
helios
helipad
helipads
heliport
helistop
helium
heliums
helix
helixes
hell
hellbent
hellbox
hellcat
hellcats
helled
heller
helleri
hellers
hellery
hellfire
hellhole
helling
hellion
hellions
hellish
hellkite
hello
helloed
helloes
helloing
hellos
hells
helluva
helm
helmed
helmet
helmeted
helmets
helming
helminth
helmless
helms
helmsman
helmsmen
helo
helos
helot
helotage
helotism
helotry
helots
help
helpable
helped
helper
helpers
helpful
helping
helpings
helpless
helpmate
helpmeet
helps
helve
helved
helves
helving
hem
hemagog
hemagogs
hemal
hematal
hematein
hematic
hematics
hematin
hematine
hematins
hematite
hematoid
hematoma
heme
hemes
hemic
hemin
hemins
hemiola
hemiolas
hemiolia
hemipter
hemline
hemlines
hemlock
hemlocks
hemmed
hemmer
hemmers
hemming
hemocoel
hemocyte
hemoid
hemolyze
hemostat
hemp
hempen
hempie
hempier
hempiest
hemplike
hemps
hempseed
hempweed
hempy
hems
hen
henbane
henbanes
henbit
henbits
hence
henchman
henchmen
hencoop
hencoops
henequen
henequin
henhouse
heniquen
henlike
henna
hennaed
hennaing
hennas
hennery
henpeck
henpecks
henries
henry
henrys
hens
hent
hented
henting
hents
hep
heparin
heparins
hepatic
hepatica
hepatics
hepatize
hepatoma
hepcat
hepcats
heptad
heptads
heptagon
heptane
heptanes
heptarch
heptose
heptoses
her
herald
heralded
heraldic
heraldry
heralds
herb
herbage
herbages
herbal
herbals
herbaria
herbed
herbier
herbiest
herbless
herblike
herbs
herby
hercules
herd
herded
herder
herders
herdic
herdics
herding
herdlike
herdman
herdmen
herds
herdsman
herdsmen
here
hereat
hereaway
hereby
heredes
heredity
herein
hereinto
hereof
hereon
heres
heresies
heresy
heretic
heretics
hereto
heretrix
hereunto
hereupon
herewith
heriot
heriots
heritage
heritor
heritors
heritrix
herl
herls
herm
herma
hermae
hermaean
hermai
hermetic
hermit
hermitic
hermitry
hermits
herms
hern
hernia
herniae
hernial
hernias
herniate
herns
hero
heroes
heroic
heroical
heroics
heroin
heroine
heroines
heroins
heroism
heroisms
heroize
heroized
heroizes
heron
heronry
herons
heros
herpes
herpetic
herried
herries
herring
herrings
herry
herrying
hers
herself
herstory
hertz
hertzes
hes
hesitant
hesitate
hessian
hessians
hessite
hessites
hest
hests
het
hetaera
hetaerae
hetaeras
hetaeric
hetaira
hetairai
hetairas
hetero
heteros
heth
heths
hetman
hetmans
hets
heuch
heuchs
heugh
heughs
hew
hewable
hewed
hewer
hewers
hewing
hewn
hews
hex
hexad
hexade
hexades
hexadic
hexads
hexagon
hexagons
hexagram
hexamine
hexane
hexanes
hexapla
hexaplar
hexaplas
hexapod
hexapods
hexapody
hexarchy
hexed
hexer
hexerei
hexereis
hexers
hexes
hexing
hexone
hexones
hexosan
hexosans
hexose
hexoses
hexyl
hexyls
hey
heyday
heydays
heydey
heydeys
hi
hiatal
hiatus
hiatuses
hibachi
hibachis
hibernal
hibiscus
hic
hiccough
hiccup
hiccuped
hiccups
hick
hickey
hickeys
hickies
hickish
hickory
hicks
hid
hidable
hidalgo
hidalgos
hidden
hiddenly
hide
hideaway
hided
hideless
hideous
hideout
hideouts
hider
hiders
hides
hiding
hidings
hidroses
hidrosis
hidrotic
hie
hied
hieing
hiemal
hierarch
hieratic
hies
higgle
higgled
higgler
higglers
higgles
higgling
high
highball
highborn
highboy
highboys
highbred
highbrow
highbush
higher
highest
highjack
highland
highlife
highly
highness
highroad
highs
highspot
hight
hightail
highted
highth
highths
highting
hights
highway
highways
hijack
hijacked
hijacker
hijacks
hijinks
hike
hiked
hiker
hikers
hikes
hiking
hila
hilar
hilarity
hilding
hildings
hili
hill
hilled
hiller
hillers
hillier
hilliest
hilling
hillo
hilloa
hilloaed
hilloas
hillock
hillocks
hillocky
hilloed
hilloes
hilloing
hillos
hills
hillside
hilltop
hilltops
hilly
hilt
hilted
hilting
hiltless
hilts
hilum
hilus
him
himatia
himation
himself
hin
hind
hinder
hindered
hinderer
hinders
hindgut
hindguts
hindmost
hinds
hinge
hinged
hinger
hingers
hinges
hinging
hinnied
hinnies
hinny
hinnying
hins
hint
hinted
hinter
hinters
hinting
hints
hip
hipbone
hipbones
hipless
hiplike
hipline
hiplines
hipness
hipparch
hipped
hipper
hippest
hippie
hippier
hippies
hippiest
hipping
hippish
hippo
hippos
hippy
hips
hipshot
hipster
hipsters
hirable
hiragana
hircine
hire
hireable
hired
hireling
hirer
hirers
hires
hiring
hirple
hirpled
hirples
hirpling
hirsel
hirseled
hirsels
hirsle
hirsled
hirsles
hirsling
hirsute
hirudin
hirudins
his
hisn
hispid
hiss
hissed
hisself
hisser
hissers
hisses
hissies
hissing
hissings
hissy
hist
histamin
histed
histidin
histing
histogen
histoid
histone
histones
historic
history
hists
hit
hitch
hitched
hitcher
hitchers
hitches
hitching
hither
hitherto
hitless
hits
hitter
hitters
hitting
hive
hived
hiveless
hives
hiving
hizzoner
hm
hmm
ho
hoactzin
hoagie
hoagies
hoagy
hoar
hoard
hoarded
hoarder
hoarders
hoarding
hoards
hoarier
hoariest
hoarily
hoars
hoarse
hoarsely
hoarsen
hoarsens
hoarser
hoarsest
hoary
hoatzin
hoatzins
hoax
hoaxed
hoaxer
hoaxers
hoaxes
hoaxing
hob
hobbed
hobbies
hobbing
hobbit
hobbits
hobble
hobbled
hobbler
hobblers
hobbles
hobbling
hobby
hobbyist
hoblike
hobnail
hobnails
hobnob
hobnobs
hobo
hoboed
hoboes
hoboing
hoboism
hoboisms
hobos
hobs
hock
hocked
hocker
hockers
hockey
hockeys
hocking
hocks
hockshop
hocus
hocused
hocuses
hocusing
hocussed
hocusses
hod
hodad
hodaddy
hodads
hodden
hoddens
hoddin
hoddins
hods
hoe
hoecake
hoecakes
hoed
hoedown
hoedowns
hoeing
hoelike
hoer
hoers
hoes
hog
hogan
hogans
hogback
hogbacks
hogfish
hogg
hogged
hogger
hoggers
hogget
hoggets
hogging
hoggish
hoggs
hoglike
hogmanay
hogmane
hogmanes
hogmenay
hognose
hognoses
hognut
hognuts
hogs
hogshead
hogtie
hogtied
hogties
hogtying
hogwash
hogweed
hogweeds
hoick
hoicked
hoicking
hoicks
hoiden
hoidened
hoidens
hoise
hoised
hoises
hoising
hoist
hoisted
hoister
hoisters
hoisting
hoists
hoke
hoked
hokes
hokey
hokier
hokiest
hokily
hokiness
hoking
hokku
hokum
hokums
hokypoky
holard
holards
hold
holdable
holdall
holdalls
holdback
holden
holder
holders
holdfast
holding
holdings
holdout
holdouts
holdover
holds
holdup
holdups
hole
holed
holeless
holes
holey
holibut
holibuts
holiday
holidays
holier
holies
holiest
holily
holiness
holing
holism
holisms
holist
holistic
holists
holk
holked
holking
holks
holla
hollaed
hollaing
holland
hollands
hollas
holler
hollered
hollers
hollies
hollo
holloa
holloaed
holloas
holloed
holloes
holloing
holloo
hollooed
holloos
hollos
hollow
hollowed
hollower
hollowly
hollows
holly
holm
holmic
holmium
holmiums
holms
hologamy
hologram
hologyny
holotype
holozoic
holp
holpen
hols
holstein
holster
holsters
holt
holts
holy
holyday
holydays
holytide
homage
homaged
homager
homagers
homages
homaging
hombre
hombres
homburg
homburgs
home
homebody
homeboy
homeboys
homebred
homed
homeland
homeless
homelier
homelike
homely
homemade
homeobox
homeotic
homeport
homer
homered
homering
homeroom
homers
homes
homesick
homesite
homespun
homestay
hometown
homeward
homework
homey
homicide
homier
homiest
homilies
homilist
homily
homines
hominess
homing
hominian
hominid
hominids
hominies
hominine
hominize
hominoid
hominy
hommock
hommocks
hommos
hommoses
homo
homogamy
homogeny
homogony
homolog
homologs
homology
homonym
homonyms
homonymy
homos
homosex
homy
hon
honan
honans
honcho
honchoed
honchos
honda
hondas
hondle
hondled
hondles
hondling
hone
honed
honer
honers
hones
honest
honester
honestly
honesty
honewort
honey
honeybee
honeybun
honeydew
honeyed
honeyful
honeying
honeys
hong
hongs
honied
honing
honk
honked
honker
honkers
honkey
honkeys
honkie
honkies
honking
honks
honky
honor
honorand
honorary
honored
honoree
honorees
honorer
honorers
honoring
honors
honour
honoured
honourer
honours
hons
hooch
hooches
hood
hooded
hoodie
hoodier
hoodies
hoodiest
hooding
hoodless
hoodlike
hoodlum
hoodlums
hoodoo
hoodooed
hoodoos
hoods
hoodwink
hoody
hooey
hooeys
hoof
hoofbeat
hoofed
hoofer
hoofers
hoofing
hoofless
hooflike
hoofs
hook
hooka
hookah
hookahs
hookas
hooked
hooker
hookers
hookey
hookeys
hookier
hookies
hookiest
hooking
hookless
hooklet
hooklets
hooklike
hooknose
hooks
hookup
hookups
hookworm
hooky
hoolie
hooligan
hooly
hoop
hooped
hooper
hoopers
hooping
hoopla
hooplas
hoopless
hooplike
hoopoe
hoopoes
hoopoo
hoopoos
hoops
hoopster
hoorah
hoorahed
hoorahs
hooray
hoorayed
hoorays
hoosegow
hoosgow
hoosgows
hoot
hootch
hootches
hooted
hooter
hooters
hootier
hootiest
hooting
hoots
hooty
hooved
hooves
hop
hope
hoped
hopeful
hopefuls
hopeless
hoper
hopers
hopes
hophead
hopheads
hoping
hoplite
hoplites
hoplitic
hopped
hopper
hoppers
hoppier
hoppiest
hopping
hoppings
hopple
hoppled
hopples
hoppling
hoppy
hops
hopsack
hopsacks
hoptoad
hoptoads
hora
horah
horahs
horal
horary
horas
horde
horded
hordein
hordeins
hordes
hording
horizon
horizons
hormonal
hormone
hormones
hormonic
horn
hornbeam
hornbill
hornbook
horned
hornet
hornets
hornfels
hornier
horniest
hornily
horning
hornist
hornists
hornito
hornitos
hornless
hornlike
hornpipe
hornpout
horns
horntail
hornworm
hornwort
horny
horologe
horology
horrent
horrible
horribly
horrid
horridly
horrific
horrify
horror
horrors
horse
horsecar
horsed
horsefly
horseman
horsemen
horsepox
horses
horsey
horsier
horsiest
horsily
horsing
horst
horste
horstes
horsts
horsy
hosanna
hosannah
hosannas
hose
hosed
hosel
hosels
hosen
hosepipe
hoses
hosier
hosiers
hosiery
hosing
hospice
hospices
hospital
hospitia
hospodar
host
hosta
hostage
hostages
hostas
hosted
hostel
hosteled
hosteler
hostelry
hostels
hostess
hostile
hostiles
hosting
hostler
hostlers
hostly
hosts
hot
hotbed
hotbeds
hotblood
hotbox
hotboxes
hotcake
hotcakes
hotch
hotched
hotches
hotching
hotchpot
hotdog
hotdogs
hotel
hoteldom
hotelier
hotelman
hotelmen
hotels
hotfoot
hotfoots
hothead
hotheads
hothouse
hotline
hotlines
hotly
hotness
hotpress
hotrod
hotrods
hots
hotshot
hotshots
hotspur
hotspurs
hotted
hotter
hottest
hotting
hottish
houdah
houdahs
hound
hounded
hounder
hounders
hounding
hounds
hour
houri
houris
hourly
hours
house
houseboy
housed
housefly
houseful
housel
houseled
housels
houseman
housemen
houser
housers
houses
housesat
housesit
housetop
housing
housings
hove
hovel
hoveled
hoveling
hovelled
hovels
hover
hovered
hoverer
hoverers
hovering
hovers
how
howbeit
howdah
howdahs
howdie
howdied
howdies
howdy
howdying
howe
howes
however
howf
howff
howffs
howfs
howitzer
howk
howked
howking
howks
howl
howled
howler
howlers
howlet
howlets
howling
howls
hows
hoy
hoya
hoyas
hoyden
hoydened
hoydens
hoyle
hoyles
hoys
huarache
huaracho
hub
hubbies
hubbly
hubbub
hubbubs
hubby
hubcap
hubcaps
hubris
hubrises
hubs
huck
huckle
huckles
hucks
huckster
huddle
huddled
huddler
huddlers
huddles
huddling
hue
hued
hueless
hues
huff
huffed
huffier
huffiest
huffily
huffing
huffish
huffs
huffy
hug
huge
hugely
hugeness
hugeous
huger
hugest
huggable
hugged
hugger
huggers
hugging
hugs
huh
huic
huipil
huipiles
huipils
huisache
hula
hulas
hulk
hulked
hulkier
hulkiest
hulking
hulks
hulky
hull
hulled
huller
hullers
hulling
hullo
hulloa
hulloaed
hulloas
hulloed
hulloes
hulloing
hullos
hulls
hum
human
humane
humanely
humaner
humanest
humanise
humanism
humanist
humanity
humanize
humanly
humanoid
humans
humate
humates
humble
humbled
humbler
humblers
humbles
humblest
humbling
humbly
humbug
humbugs
humdrum
humdrums
humeral
humerals
humeri
humerus
humic
humid
humidify
humidity
humidly
humidor
humidors
humified
humility
hummable
hummed
hummer
hummers
humming
hummock
hummocks
hummocky
hummus
hummuses
humor
humoral
humored
humorful
humoring
humorist
humorous
humors
humour
humoured
humours
hump
humpback
humped
humph
humphed
humphing
humphs
humpier
humpiest
humping
humpless
humps
humpy
hums
humus
humuses
humvee
humvees
hun
hunch
hunched
hunches
hunching
hundred
hundreds
hung
hunger
hungered
hungers
hungover
hungrier
hungrily
hungry
hunh
hunk
hunker
hunkered
hunkers
hunkier
hunkies
hunkiest
hunks
hunky
hunnish
huns
hunt
huntable
hunted
huntedly
hunter
hunters
hunting
huntings
huntress
hunts
huntsman
huntsmen
hup
hurdies
hurdle
hurdled
hurdler
hurdlers
hurdles
hurdling
hurds
hurl
hurled
hurler
hurlers
hurley
hurleys
hurlies
hurling
hurlings
hurls
hurly
hurrah
hurrahed
hurrahs
hurray
hurrayed
hurrays
hurried
hurrier
hurriers
hurries
hurry
hurrying
hurst
hursts
hurt
hurter
hurters
hurtful
hurting
hurtle
hurtled
hurtles
hurtless
hurtling
hurts
husband
husbands
hush
hushaby
hushed
hushedly
hushes
hushful
hushing
husk
husked
husker
huskers
huskier
huskies
huskiest
huskily
husking
huskings
husklike
husks
husky
hussar
hussars
hussies
hussy
hustings
hustle
hustled
hustler
hustlers
hustles
hustling
huswife
huswifes
huswives
hut
hutch
hutched
hutches
hutching
hutlike
hutment
hutments
huts
hutted
hutting
hutzpa
hutzpah
hutzpahs
hutzpas
huzza
huzzaed
huzzah
huzzahed
huzzahs
huzzaing
huzzas
hwan
hyacinth
hyaena
hyaenas
hyaenic
hyalin
hyaline
hyalines
hyalins
hyalite
hyalites
hyalogen
hyaloid
hyaloids
hybrid
hybrids
hybris
hybrises
hydatid
hydatids
hydra
hydracid
hydrae
hydragog
hydrant
hydranth
hydrants
hydras
hydrase
hydrases
hydrate
hydrated
hydrates
hydrator
hydria
hydriae
hydric
hydrid
hydride
hydrides
hydrids
hydro
hydrogel
hydrogen
hydroid
hydroids
hydromel
hydronic
hydropic
hydrops
hydropsy
hydros
hydroski
hydrosol
hydrous
hydroxy
hydroxyl
hyena
hyenas
hyenic
hyenine
hyenoid
hyetal
hygeist
hygeists
hygieist
hygiene
hygienes
hygienic
hying
hyla
hylas
hylozoic
hymen
hymenal
hymeneal
hymenia
hymenial
hymenium
hymens
hymn
hymnal
hymnals
hymnary
hymnbook
hymned
hymning
hymnist
hymnists
hymnless
hymnlike
hymnody
hymns
hyoid
hyoidal
hyoidean
hyoids
hyoscine
hyp
hype
hyped
hyper
hypergol
hyperon
hyperons
hyperope
hypes
hypha
hyphae
hyphal
hyphemia
hyphen
hyphened
hyphens
hyping
hypnic
hypnoid
hypnoses
hypnosis
hypnotic
hypo
hypoacid
hypoderm
hypoed
hypogea
hypogeal
hypogean
hypogene
hypogeum
hypogyny
hypoing
hyponea
hyponeas
hyponoia
hypopnea
hypopyon
hypos
hypothec
hypoxia
hypoxias
hypoxic
hyps
hyraces
hyracoid
hyrax
hyraxes
hyson
hysons
hyssop
hyssops
hysteria
hysteric
hyte
iamb
iambi
iambic
iambics
iambs
iambus
iambuses
iatric
iatrical
ibex
ibexes
ibices
ibidem
ibis
ibises
ibogaine
ice
iceberg
icebergs
iceblink
iceboat
iceboats
icebound
icebox
iceboxes
icecap
icecaps
iced
icefall
icefalls
icehouse
icekhana
iceless
icelike
iceman
icemen
ices
ich
ichnite
ichnites
ichor
ichorous
ichors
ichs
ichthyic
icicle
icicled
icicles
icier
iciest
icily
iciness
icing
icings
ick
icker
ickers
ickier
ickiest
ickily
ickiness
icky
icon
icones
iconic
iconical
icons
icteric
icterics
icterus
ictic
ictus
ictuses
icy
id
idea
ideal
idealess
idealise
idealism
idealist
ideality
idealize
ideally
idealogy
ideals
ideas
ideate
ideated
ideates
ideating
ideation
ideative
idem
identic
identify
identity
ideogram
ideology
ides
idiocies
idiocy
idiolect
idiom
idioms
idiot
idiotic
idiotism
idiots
idle
idled
idleness
idler
idlers
idles
idlesse
idlesses
idlest
idling
idly
idocrase
idol
idolater
idolator
idolatry
idolise
idolised
idoliser
idolises
idolism
idolisms
idolize
idolized
idolizer
idolizes
idols
idoneity
idoneous
ids
idyl
idylist
idylists
idyll
idyllic
idyllist
idylls
idyls
if
iff
iffier
iffiest
iffiness
iffy
ifs
igloo
igloos
iglu
iglus
ignatia
ignatias
igneous
ignified
ignifies
ignify
ignite
ignited
igniter
igniters
ignites
igniting
ignition
ignitor
ignitors
ignitron
ignoble
ignobly
ignominy
ignorami
ignorant
ignore
ignored
ignorer
ignorers
ignores
ignoring
iguana
iguanas
iguanian
ihram
ihrams
ikat
ikats
ikebana
ikebanas
ikon
ikons
ilea
ileac
ileal
ileitis
ileum
ileus
ileuses
ilex
ilexes
ilia
iliac
iliad
iliads
ilial
ilium
ilk
ilka
ilks
ill
illation
illative
illegal
illegals
iller
illest
illicit
illinium
illiquid
illite
illites
illitic
illness
illogic
illogics
ills
illume
illumed
illumes
illumine
illuming
illusion
illusive
illusory
illuvia
illuvial
illuvium
illy
ilmenite
image
imaged
imager
imagers
imagery
images
imaginal
imagine
imagined
imaginer
imagines
imaging
imagings
imagism
imagisms
imagist
imagists
imago
imagoes
imagos
imam
imamate
imamates
imams
imaret
imarets
imaum
imaums
imbalm
imbalmed
imbalmer
imbalms
imbark
imbarked
imbarks
imbecile
imbed
imbedded
imbeds
imbibe
imbibed
imbiber
imbibers
imbibes
imbibing
imbitter
imblaze
imblazed
imblazes
imbodied
imbodies
imbody
imbolden
imbosom
imbosoms
imbower
imbowers
imbrown
imbrowns
imbrue
imbrued
imbrues
imbruing
imbrute
imbruted
imbrutes
imbue
imbued
imbues
imbuing
imid
imide
imides
imidic
imido
imids
imine
imines
imino
imitable
imitate
imitated
imitates
imitator
immane
immanent
immature
immense
immenser
immerge
immerged
immerges
immerse
immersed
immerses
immesh
immeshed
immeshes
immies
imminent
immingle
immix
immixed
immixes
immixing
immobile
immodest
immolate
immoral
immortal
immotile
immune
immunes
immunise
immunity
immunize
immure
immured
immures
immuring
immy
imp
impact
impacted
impacter
impactor
impacts
impaint
impaints
impair
impaired
impairer
impairs
impala
impalas
impale
impaled
impaler
impalers
impales
impaling
impanel
impanels
imparity
impark
imparked
imparks
impart
imparted
imparter
imparts
impasse
impasses
impaste
impasted
impastes
impasto
impastos
impavid
impawn
impawned
impawns
impeach
impearl
impearls
imped
impede
impeded
impeder
impeders
impedes
impeding
impel
impelled
impeller
impellor
impels
impend
impended
impends
imperia
imperial
imperil
imperils
imperium
impetigo
impetus
imphee
imphees
impi
impiety
imping
impinge
impinged
impinger
impinges
impings
impious
impis
impish
impishly
implant
implants
implead
impleads
impledge
implicit
implied
implies
implode
imploded
implodes
implore
implored
implorer
implores
imply
implying
impolicy
impolite
impone
imponed
impones
imponing
imporous
import
imported
importer
imports
impose
imposed
imposer
imposers
imposes
imposing
impost
imposted
imposter
impostor
imposts
impotent
impound
impounds
impower
impowers
impregn
impregns
impresa
impresas
imprese
impreses
impress
imprest
imprests
imprimis
imprint
imprints
imprison
improper
improv
improve
improved
improver
improves
improvs
imps
impudent
impugn
impugned
impugner
impugns
impulse
impulsed
impulses
impunity
impure
impurely
impurity
impute
imputed
imputer
imputers
imputes
imputing
in
inaction
inactive
inane
inanely
inaner
inanes
inanest
inanity
inapt
inaptly
inarable
inarch
inarched
inarches
inarm
inarmed
inarming
inarms
inbeing
inbeings
inboard
inboards
inborn
inbound
inbounds
inbred
inbreds
inbreed
inbreeds
inbuilt
inburst
inbursts
inby
inbye
incage
incaged
incages
incaging
incant
incanted
incants
incase
incased
incases
incasing
incense
incensed
incenses
incenter
incept
incepted
inceptor
incepts
incest
incests
inch
inched
inches
inching
inchmeal
inchoate
inchworm
incident
incipit
incipits
incisal
incise
incised
incises
incising
incision
incisive
incisor
incisors
incisory
incisure
incitant
incite
incited
inciter
inciters
incites
inciting
incivil
inclasp
inclasps
incline
inclined
incliner
inclines
inclip
inclips
inclose
inclosed
incloser
incloses
include
included
includes
incog
incogs
income
incomer
incomers
incomes
incoming
inconnu
inconnus
incony
incorpse
increase
increate
incross
incrust
incrusts
incubate
incubi
incubus
incudal
incudate
incudes
incult
incumber
incur
incurred
incurs
incurve
incurved
incurves
incus
incuse
incused
incuses
incusing
indaba
indabas
indagate
indamin
indamine
indamins
indebted
indecent
indeed
indene
indenes
indent
indented
indenter
indentor
indents
indevout
index
indexed
indexer
indexers
indexes
indexing
indican
indicans
indicant
indicate
indices
indicia
indicias
indicium
indict
indicted
indictee
indicter
indictor
indicts
indie
indies
indigen
indigene
indigens
indigent
indign
indignly
indigo
indigoes
indigoid
indigos
indirect
indite
indited
inditer
inditers
indites
inditing
indium
indiums
indocile
indol
indole
indolent
indoles
indols
indoor
indoors
indorse
indorsed
indorsee
indorser
indorses
indorsor
indow
indowed
indowing
indows
indoxyl
indoxyls
indraft
indrafts
indrawn
indri
indris
induce
induced
inducer
inducers
induces
inducing
induct
inducted
inductee
inductor
inducts
indue
indued
indues
induing
indulge
indulged
indulger
indulges
indulin
induline
indulins
indult
indults
indurate
indusia
indusial
indusium
industry
indwell
indwells
indwelt
inearth
inearths
inedible
inedita
inedited
inept
ineptly
inequity
inerrant
inert
inertia
inertiae
inertial
inertias
inertly
inerts
inexact
inexpert
infall
infalls
infamies
infamous
infamy
infancy
infant
infanta
infantas
infante
infantes
infantry
infants
infarct
infarcts
infare
infares
infauna
infaunae
infaunal
infaunas
infect
infected
infecter
infector
infects
infecund
infeoff
infeoffs
infer
inferior
infernal
inferno
infernos
inferred
inferrer
infers
infest
infested
infester
infests
infidel
infidels
infield
infields
infight
infights
infinite
infinity
infirm
infirmed
infirmly
infirms
infix
infixed
infixes
infixing
infixion
inflame
inflamed
inflamer
inflames
inflate
inflated
inflater
inflates
inflator
inflect
inflects
inflexed
inflict
inflicts
inflight
inflow
inflows
influent
influx
influxes
info
infold
infolded
infolder
infolds
inform
informal
informed
informer
informs
infos
infought
infra
infract
infracts
infrared
infringe
infrugal
infuse
infused
infuser
infusers
infuses
infusing
infusion
infusive
ingate
ingates
ingather
ingenue
ingenues
ingest
ingesta
ingested
ingests
ingle
ingles
ingoing
ingot
ingoted
ingoting
ingots
ingraft
ingrafts
ingrain
ingrains
ingrate
ingrates
ingress
ingroup
ingroups
ingrown
ingrowth
inguinal
ingulf
ingulfed
ingulfs
inhabit
inhabits
inhalant
inhale
inhaled
inhaler
inhalers
inhales
inhaling
inhaul
inhauler
inhauls
inhere
inhered
inherent
inheres
inhering
inherit
inherits
inhesion
inhibin
inhibins
inhibit
inhibits
inhuman
inhumane
inhume
inhumed
inhumer
inhumers
inhumes
inhuming
inia
inimical
inion
iniquity
initial
initials
initiate
inject
injected
injector
injects
injure
injured
injurer
injurers
injures
injuries
injuring
injury
ink
inkberry
inkblot
inkblots
inked
inker
inkers
inkhorn
inkhorns
inkier
inkiest
inkiness
inking
inkjet
inkle
inkles
inkless
inklike
inkling
inklings
inkpot
inkpots
inks
inkstand
inkstone
inkwell
inkwells
inkwood
inkwoods
inky
inlace
inlaced
inlaces
inlacing
inlaid
inland
inlander
inlands
inlay
inlayer
inlayers
inlaying
inlays
inlet
inlets
inlier
inliers
inly
inmate
inmates
inmesh
inmeshed
inmeshes
inmost
inn
innards
innate
innately
inned
inner
innerly
inners
innerve
innerved
innerves
inning
innings
innless
innocent
innovate
inns
innuendo
inocula
inoculum
inosite
inosites
inositol
inphase
inpour
inpoured
inpours
input
inputs
inputted
inquest
inquests
inquiet
inquiets
inquire
inquired
inquirer
inquires
inquiry
inro
inroad
inroads
inrush
inrushes
ins
insane
insanely
insaner
insanest
insanity
inscape
inscapes
inscribe
inscroll
insculp
insculps
inseam
inseams
insect
insectan
insects
insecure
insert
inserted
inserter
inserts
inset
insets
insetted
insetter
insheath
inshore
inshrine
inside
insider
insiders
insides
insight
insights
insigne
insignia
insipid
insist
insisted
insister
insists
insnare
insnared
insnarer
insnares
insofar
insolate
insole
insolent
insoles
insomnia
insomuch
insoul
insouled
insouls
inspan
inspans
inspect
inspects
insphere
inspire
inspired
inspirer
inspires
inspirit
instable
instal
install
installs
instals
instance
instancy
instant
instants
instar
instars
instate
instated
instates
instead
instep
insteps
instil
instill
instills
instils
instinct
instroke
instruct
insulant
insular
insulars
insulate
insulin
insulins
insult
insulted
insulter
insults
insurant
insure
insured
insureds
insurer
insurers
insures
insuring
inswathe
inswept
intact
intagli
intaglio
intake
intakes
intarsia
integer
integers
integral
intend
intended
intender
intends
intense
intenser
intent
intently
intents
inter
interact
interage
interbed
intercom
intercut
interest
interim
interims
interior
interlap
interlay
intermit
intermix
intern
internal
interne
interned
internee
internes
interns
interred
interrex
interrow
inters
intersex
intertie
interval
interwar
inthral
inthrall
inthrals
inthrone
inti
intima
intimacy
intimae
intimal
intimas
intimate
intime
intimist
intine
intines
intis
intitle
intitled
intitles
intitule
into
intomb
intombed
intombs
intonate
intone
intoned
intoner
intoners
intones
intoning
intort
intorted
intorts
intown
intraday
intrados
intrant
intrants
intreat
intreats
intrench
intrepid
intrigue
intro
introfy
introit
introits
intromit
intron
introns
introrse
intros
intrude
intruded
intruder
intrudes
intrust
intrusts
intubate
intuit
intuited
intuits
inturn
inturned
inturns
intwine
intwined
intwines
intwist
intwists
inulase
inulases
inulin
inulins
inundant
inundate
inurbane
inure
inured
inures
inuring
inurn
inurned
inurning
inurns
inutile
invade
invaded
invader
invaders
invades
invading
invalid
invalids
invar
invars
invasion
invasive
invected
inveigh
inveighs
inveigle
invent
invented
inventer
inventor
invents
inverity
inverse
inverses
invert
inverted
inverter
invertor
inverts
invest
invested
investor
invests
inviable
inviably
invirile
inviscid
invital
invite
invited
invitee
invitees
inviter
inviters
invites
inviting
invocate
invoice
invoiced
invoices
invoke
invoked
invoker
invokers
invokes
invoking
involute
involve
involved
involver
involves
inwall
inwalled
inwalls
inward
inwardly
inwards
inweave
inweaved
inweaves
inwind
inwinds
inwound
inwove
inwoven
inwrap
inwraps
iodate
iodated
iodates
iodating
iodation
iodic
iodid
iodide
iodides
iodids
iodin
iodinate
iodine
iodines
iodins
iodise
iodised
iodises
iodising
iodism
iodisms
iodize
iodized
iodizer
iodizers
iodizes
iodizing
iodoform
iodophor
iodopsin
iodous
iolite
iolites
ion
ionic
ionicity
ionics
ionise
ionised
ionises
ionising
ionium
ioniums
ionize
ionized
ionizer
ionizers
ionizes
ionizing
ionogen
ionogens
ionomer
ionomers
ionone
ionones
ions
iota
iotacism
iotas
ipecac
ipecacs
ipomoea
ipomoeas
iracund
irade
irades
irate
irately
irater
iratest
ire
ired
ireful
irefully
ireless
irenic
irenical
irenics
ires
irid
irides
iridic
iridium
iridiums
irids
iring
iris
irised
irises
irising
iritic
iritis
iritises
irk
irked
irking
irks
irksome
iroko
irokos
iron
ironbark
ironclad
irone
ironed
ironer
ironers
irones
ironic
ironical
ironies
ironing
ironings
ironist
ironists
ironize
ironized
ironizes
ironlike
ironness
irons
ironside
ironware
ironweed
ironwood
ironwork
irony
irreal
irrigate
irritant
irritate
irrupt
irrupted
irrupts
is
isagoge
isagoges
isagogic
isarithm
isatin
isatine
isatines
isatinic
isatins
isba
isbas
ischemia
ischemic
ischia
ischial
ischium
island
islanded
islander
islands
isle
isled
isleless
isles
islet
islets
isling
ism
isms
isobar
isobare
isobares
isobaric
isobars
isobath
isobaths
isocheim
isochime
isochor
isochore
isochors
isochron
isocline
isocracy
isodose
isogamy
isogenic
isogeny
isogloss
isogon
isogonal
isogone
isogones
isogonic
isogons
isogony
isograft
isogram
isograms
isograph
isogriv
isogrivs
isohel
isohels
isohyet
isohyets
isolable
isolate
isolated
isolates
isolator
isolead
isoleads
isoline
isolines
isolog
isologs
isologue
isomer
isomeric
isomers
isometry
isomorph
isonomic
isonomy
isopach
isopachs
isophote
isopleth
isopod
isopodan
isopods
isoprene
isospin
isospins
isospory
isostasy
isotach
isotachs
isothere
isotherm
isotone
isotones
isotonic
isotope
isotopes
isotopic
isotopy
isotropy
isotype
isotypes
isotypic
isozyme
isozymes
isozymic
issei
isseis
issuable
issuably
issuance
issuant
issue
issued
issuer
issuers
issues
issuing
isthmi
isthmian
isthmic
isthmoid
isthmus
istle
istles
it
italic
italics
itch
itched
itches
itchier
itchiest
itchily
itching
itchings
itchy
item
itemed
iteming
itemise
itemised
itemises
itemize
itemized
itemizer
itemizes
items
iterance
iterant
iterate
iterated
iterates
iterum
ither
its
itself
ivied
ivies
ivories
ivory
ivy
ivylike
iwis
ixia
ixias
ixodid
ixodids
ixora
ixoras
ixtle
ixtles
izar
izars
izzard
izzards
jab
jabbed
jabber
jabbered
jabberer
jabbers
jabbing
jabiru
jabirus
jabot
jabots
jabs
jacal
jacales
jacals
jacamar
jacamars
jacana
jacanas
jacinth
jacinthe
jacinths
jack
jackal
jackals
jackaroo
jackass
jackboot
jackdaw
jackdaws
jacked
jacker
jackeroo
jackers
jacket
jacketed
jackets
jackfish
jackies
jacking
jackleg
jacklegs
jackpot
jackpots
jackroll
jacks
jackstay
jacky
jacobin
jacobins
jacobus
jaconet
jaconets
jacquard
jaculate
jade
jaded
jadedly
jadeite
jadeites
jades
jading
jadish
jadishly
jaditic
jaeger
jaegers
jag
jager
jagers
jagg
jaggary
jagged
jaggeder
jaggedly
jagger
jaggers
jaggery
jagghery
jaggier
jaggiest
jagging
jaggs
jaggy
jagless
jagra
jagras
jags
jaguar
jaguars
jail
jailbait
jailbird
jailed
jailer
jailers
jailing
jailor
jailors
jails
jake
jakes
jalap
jalapeno
jalapic
jalapin
jalapins
jalaps
jalop
jalopies
jaloppy
jalops
jalopy
jalousie
jam
jamb
jambe
jambeau
jambeaux
jambed
jambes
jambing
jamboree
jambs
jammed
jammer
jammers
jammier
jammies
jammiest
jamming
jammy
jams
jane
janes
jangle
jangled
jangler
janglers
jangles
janglier
jangling
jangly
janiform
janisary
janitor
janitors
janizary
janty
japan
japanize
japanned
japanner
japans
jape
japed
japer
japeries
japers
japery
japes
japing
japingly
japonica
jar
jarful
jarfuls
jargon
jargoned
jargonel
jargons
jargoon
jargoons
jarhead
jarheads
jarina
jarinas
jarl
jarldom
jarldoms
jarls
jarosite
jarovize
jarrah
jarrahs
jarred
jarring
jars
jarsful
jarvey
jarveys
jasmin
jasmine
jasmines
jasmins
jasper
jaspers
jaspery
jassid
jassids
jato
jatos
jauk
jauked
jauking
jauks
jaunce
jaunced
jaunces
jauncing
jaundice
jaunt
jaunted
jauntier
jauntily
jaunting
jaunts
jaunty
jaup
jauped
jauping
jaups
java
javas
javelin
javelina
javelins
jaw
jawan
jawans
jawbone
jawboned
jawboner
jawbones
jawed
jawing
jawlike
jawline
jawlines
jaws
jay
jaybird
jaybirds
jaygee
jaygees
jays
jayvee
jayvees
jaywalk
jaywalks
jazz
jazzed
jazzer
jazzers
jazzes
jazzier
jazziest
jazzily
jazzing
jazzlike
jazzman
jazzmen
jazzy
jealous
jealousy
jean
jeans
jebel
jebels
jee
jeed
jeeing
jeep
jeeped
jeepers
jeeping
jeepney
jeepneys
jeeps
jeer
jeered
jeerer
jeerers
jeering
jeers
jees
jeez
jefe
jefes
jehad
jehads
jehu
jehus
jejuna
jejunal
jejune
jejunely
jejunity
jejunum
jell
jellaba
jellabas
jelled
jellied
jellies
jellify
jelling
jells
jelly
jellying
jelutong
jemadar
jemadars
jemidar
jemidars
jemmied
jemmies
jemmy
jemmying
jennet
jennets
jennies
jenny
jeon
jeopard
jeopards
jeopardy
jerboa
jerboas
jereed
jereeds
jeremiad
jerid
jerids
jerk
jerked
jerker
jerkers
jerkier
jerkies
jerkiest
jerkily
jerkin
jerking
jerkins
jerks
jerky
jeroboam
jerreed
jerreeds
jerrican
jerrid
jerrids
jerries
jerry
jerrycan
jersey
jerseyed
jerseys
jess
jessant
jesse
jessed
jesses
jessing
jest
jested
jester
jesters
jestful
jesting
jestings
jests
jesuit
jesuitic
jesuitry
jesuits
jet
jetbead
jetbeads
jete
jetes
jetlike
jetliner
jeton
jetons
jetport
jetports
jets
jetsam
jetsams
jetsom
jetsoms
jetted
jettied
jettier
jetties
jettiest
jetting
jettison
jetton
jettons
jetty
jettying
jeu
jeux
jew
jewed
jewel
jeweled
jeweler
jewelers
jeweling
jewelled
jeweller
jewelry
jewels
jewfish
jewing
jews
jezail
jezails
jezebel
jezebels
jiao
jib
jibb
jibbed
jibber
jibbers
jibbing
jibboom
jibbooms
jibbs
jibe
jibed
jiber
jibers
jibes
jibing
jibingly
jibs
jicama
jicamas
jiff
jiffies
jiffs
jiffy
jig
jigaboo
jigaboos
jigged
jigger
jiggered
jiggers
jigging
jiggle
jiggled
jiggles
jigglier
jiggling
jiggly
jigs
jigsaw
jigsawed
jigsawn
jigsaws
jihad
jihads
jill
jillion
jillions
jills
jilt
jilted
jilter
jilters
jilting
jilts
jiminy
jimjams
jimmied
jimmies
jimminy
jimmy
jimmying
jimp
jimper
jimpest
jimply
jimpy
jin
jingal
jingall
jingalls
jingals
jingko
jingkoes
jingle
jingled
jingler
jinglers
jingles
jinglier
jingling
jingly
jingo
jingoes
jingoish
jingoism
jingoist
jink
jinked
jinker
jinkers
jinking
jinks
jinn
jinnee
jinni
jinns
jins
jinx
jinxed
jinxes
jinxing
jipijapa
jism
jisms
jitney
jitneys
jitter
jittered
jitters
jittery
jiujitsu
jiujutsu
jive
jiveass
jived
jiver
jivers
jives
jivey
jivier
jiviest
jiving
jnana
jnanas
jo
joannes
job
jobbed
jobber
jobbers
jobbery
jobbing
jobless
jobname
jobnames
jobs
jock
jockette
jockey
jockeyed
jockeys
jocko
jockos
jocks
jocose
jocosely
jocosity
jocular
jocund
jocundly
jodhpur
jodhpurs
joe
joes
joey
joeys
jog
jogged
jogger
joggers
jogging
joggings
joggle
joggled
joggler
jogglers
joggles
joggling
jogs
johannes
john
johnboat
johnnies
johnny
johns
join
joinable
joinder
joinders
joined
joiner
joiners
joinery
joining
joinings
joins
joint
jointed
jointer
jointers
jointing
jointly
joints
jointure
joist
joisted
joisting
joists
jojoba
jojobas
joke
joked
joker
jokers
jokes
jokester
jokey
jokier
jokiest
jokily
jokiness
joking
jokingly
joky
jole
joles
jollied
jollier
jollies
jolliest
jollify
jollily
jollity
jolly
jollying
jolt
jolted
jolter
jolters
joltier
joltiest
joltily
jolting
jolts
jolty
jones
joneses
jongleur
jonquil
jonquils
joram
jorams
jordan
jordans
jorum
jorums
joseph
josephs
josh
joshed
josher
joshers
joshes
joshing
joss
josses
jostle
jostled
jostler
jostlers
jostles
jostling
jot
jota
jotas
jots
jotted
jotter
jotters
jotting
jottings
jotty
joual
jouals
jouk
jouked
jouking
jouks
joule
joules
jounce
jounced
jounces
jouncier
jouncing
jouncy
journal
journals
journey
journeys
joust
jousted
jouster
jousters
jousting
jousts
jovial
jovially
jovialty
jow
jowar
jowars
jowed
jowing
jowl
jowled
jowlier
jowliest
jowls
jowly
jows
joy
joyance
joyances
joyed
joyful
joyfully
joying
joyless
joyous
joyously
joypop
joypops
joyride
joyrider
joyrides
joyrode
joys
joystick
juba
jubas
jubbah
jubbahs
jube
jubes
jubhah
jubhahs
jubilant
jubilate
jubile
jubilee
jubilees
jubiles
judas
judases
judder
juddered
judders
judge
judged
judger
judgers
judges
judging
judgment
judicial
judo
judoist
judoists
judoka
judokas
judos
jug
juga
jugal
jugate
jugful
jugfuls
jugged
jugging
juggle
juggled
juggler
jugglers
jugglery
juggles
juggling
jughead
jugheads
jugs
jugsful
jugula
jugular
jugulars
jugulate
jugulum
jugum
jugums
juice
juiced
juicer
juicers
juices
juicier
juiciest
juicily
juicing
juicy
jujitsu
jujitsus
juju
jujube
jujubes
jujuism
jujuisms
jujuist
jujuists
jujus
jujutsu
jujutsus
juke
jukebox
juked
jukes
juking
julep
juleps
julienne
jumbal
jumbals
jumble
jumbled
jumbler
jumblers
jumbles
jumbling
jumbo
jumbos
jumbuck
jumbucks
jump
jumped
jumper
jumpers
jumpier
jumpiest
jumpily
jumping
jumpoff
jumpoffs
jumps
jumpsuit
jumpy
jun
junco
juncoes
juncos
junction
juncture
jungle
jungled
jungles
junglier
jungly
junior
juniors
juniper
junipers
junk
junked
junker
junkers
junket
junketed
junketer
junkets
junkie
junkier
junkies
junkiest
junking
junkman
junkmen
junks
junky
junkyard
junta
juntas
junto
juntos
jupe
jupes
jupon
jupons
jura
jural
jurally
jurant
jurants
jurat
juratory
jurats
jurel
jurels
juridic
juried
juries
jurist
juristic
jurists
juror
jurors
jury
jurying
juryman
jurymen
jus
jussive
jussives
just
justed
juster
justers
justest
justice
justices
justify
justing
justle
justled
justles
justling
justly
justness
justs
jut
jute
jutes
juts
jutted
juttied
jutties
jutting
jutty
juttying
juvenal
juvenals
juvenile
ka
kaas
kab
kabab
kababs
kabaka
kabakas
kabala
kabalas
kabar
kabars
kabaya
kabayas
kabbala
kabbalah
kabbalas
kabeljou
kabiki
kabikis
kabob
kabobs
kabs
kabuki
kabukis
kachina
kachinas
kaddish
kadi
kadis
kae
kaes
kaf
kaffir
kaffirs
kaffiyeh
kafir
kafirs
kafs
kaftan
kaftans
kagu
kagus
kahuna
kahunas
kaiak
kaiaks
kaif
kaifs
kail
kails
kailyard
kain
kainit
kainite
kainites
kainits
kains
kaiser
kaiserin
kaisers
kajeput
kajeputs
kaka
kakapo
kakapos
kakas
kakemono
kaki
kakiemon
kakis
kalam
kalams
kale
kalends
kales
kalewife
kaleyard
kalian
kalians
kalif
kalifate
kalifs
kalimba
kalimbas
kaliph
kaliphs
kalium
kaliums
kallidin
kalmia
kalmias
kalong
kalongs
kalpa
kalpak
kalpaks
kalpas
kalyptra
kamaaina
kamacite
kamala
kamalas
kame
kames
kami
kamik
kamikaze
kamiks
kampong
kampongs
kamseen
kamseens
kamsin
kamsins
kana
kanas
kanban
kanbans
kane
kanes
kangaroo
kanji
kanjis
kantar
kantars
kantele
kanteles
kaoliang
kaolin
kaoline
kaolines
kaolinic
kaolins
kaon
kaons
kapa
kapas
kaph
kaphs
kapok
kapoks
kappa
kappas
kaput
kaputt
karakul
karakuls
karaoke
karaokes
karat
karate
karates
karats
karma
karmas
karmic
karn
karns
karoo
karoos
kaross
karosses
karroo
karroos
karst
karstic
karsts
kart
karting
kartings
karts
karyotin
kas
kasbah
kasbahs
kasha
kashas
kasher
kashered
kashers
kashmir
kashmirs
kashrut
kashruth
kashruts
kat
kata
katakana
katas
katchina
katcina
katcinas
kathodal
kathode
kathodes
kathodic
kation
kations
kats
katydid
katydids
kauri
kauries
kauris
kaury
kava
kavakava
kavas
kavass
kavasses
kay
kayak
kayaked
kayaker
kayakers
kayaking
kayaks
kayles
kayo
kayoed
kayoes
kayoing
kayos
kays
kazachki
kazachok
kazatski
kazatsky
kazoo
kazoos
kbar
kbars
kea
keas
kebab
kebabs
kebar
kebars
kebbie
kebbies
kebbock
kebbocks
kebbuck
kebbucks
keblah
keblahs
kebob
kebobs
keck
kecked
kecking
keckle
keckled
keckles
keckling
kecks
keddah
keddahs
kedge
kedged
kedgeree
kedges
kedging
keef
keefs
keek
keeked
keeking
keeks
keel
keelage
keelages
keelboat
keeled
keelhale
keelhaul
keeling
keelless
keels
keelson
keelsons
keen
keened
keener
keeners
keenest
keening
keenly
keenness
keens
keep
keepable
keeper
keepers
keeping
keepings
keeps
keepsake
keeshond
keester
keesters
keet
keets
keeve
keeves
kef
keffiyeh
kefir
kefirs
kefs
keg
kegeler
kegelers
kegler
keglers
kegling
keglings
kegs
keir
keirs
keister
keisters
keitloa
keitloas
kelep
keleps
kelim
kelims
kellies
kelly
keloid
keloidal
keloids
kelp
kelped
kelpie
kelpies
kelping
kelps
kelpy
kelson
kelsons
kelter
kelters
kelvin
kelvins
kemp
kemps
kempt
ken
kenaf
kenafs
kench
kenches
kendo
kendos
kenned
kennel
kenneled
kennels
kenning
kennings
keno
kenos
kenosis
kenotic
kenotron
kens
kent
kep
kephalin
kepi
kepis
kepped
keppen
kepping
keps
kept
keramic
keramics
keratin
keratins
keratoid
keratoma
keratose
kerb
kerbed
kerbing
kerbs
kerchief
kerchoo
kerf
kerfed
kerfing
kerfs
kermes
kermess
kermesse
kermis
kermises
kern
kerne
kerned
kernel
kerneled
kernels
kernes
kerning
kernite
kernites
kerns
kerogen
kerogens
kerosene
kerosine
kerplunk
kerria
kerrias
kerries
kerry
kersey
kerseys
kerygma
kestrel
kestrels
ketch
ketches
ketchup
ketchups
ketene
ketenes
keto
ketol
ketols
ketone
ketones
ketonic
ketose
ketoses
ketosis
ketotic
kettle
kettles
kevel
kevels
kevil
kevils
kex
kexes
key
keyboard
keycard
keycards
keyed
keyhole
keyholes
keying
keyless
keynote
keynoted
keynoter
keynotes
keypad
keypads
keypunch
keys
keyset
keysets
keyster
keysters
keystone
keyway
keyways
keyword
keywords
khaddar
khaddars
khadi
khadis
khaf
khafs
khaki
khakis
khalif
khalifa
khalifas
khalifs
khamseen
khamsin
khamsins
khan
khanate
khanates
khans
khaph
khaphs
khat
khats
khazen
khazenim
khazens
kheda
khedah
khedahs
khedas
khedival
khedive
khedives
khet
kheth
kheths
khets
khi
khirkah
khirkahs
khis
khoum
khoums
kiang
kiangs
kiaugh
kiaughs
kibbe
kibbeh
kibbehs
kibbes
kibbi
kibbis
kibbitz
kibble
kibbled
kibbles
kibbling
kibbutz
kibe
kibei
kibeis
kibes
kibitz
kibitzed
kibitzer
kibitzes
kibla
kiblah
kiblahs
kiblas
kibosh
kiboshed
kiboshes
kick
kickable
kickback
kickball
kicked
kicker
kickers
kickier
kickiest
kicking
kickoff
kickoffs
kicks
kickshaw
kickup
kickups
kicky
kid
kidded
kidder
kidders
kiddie
kiddies
kidding
kiddish
kiddo
kiddoes
kiddos
kiddush
kiddy
kidlike
kidnap
kidnaped
kidnapee
kidnaper
kidnaps
kidney
kidneys
kids
kidskin
kidskins
kidvid
kidvids
kief
kiefs
kielbasa
kielbasi
kielbasy
kier
kiers
kiester
kiesters
kif
kifs
kike
kikes
kilim
kilims
kill
killdee
killdeer
killdees
killed
killer
killers
killick
killicks
killie
killies
killing
killings
killjoy
killjoys
killock
killocks
kills
kiln
kilned
kilning
kilns
kilo
kilobar
kilobars
kilobase
kilobaud
kilobit
kilobits
kilobyte
kilogram
kilomole
kilorad
kilorads
kilos
kiloton
kilotons
kilovolt
kilowatt
kilt
kilted
kilter
kilters
kiltie
kilties
kilting
kiltings
kilts
kilty
kimchee
kimchees
kimchi
kimchis
kimono
kimonoed
kimonos
kin
kina
kinas
kinase
kinases
kind
kinder
kindest
kindle
kindled
kindler
kindlers
kindles
kindless
kindlier
kindling
kindly
kindness
kindred
kindreds
kinds
kine
kinema
kinemas
kines
kineses
kinesic
kinesics
kinesis
kinetic
kinetics
kinetin
kinetins
kinfolk
kinfolks
king
kingbird
kingbolt
kingcup
kingcups
kingdom
kingdoms
kinged
kingfish
kinghood
kinging
kingless
kinglet
kinglets
kinglier
kinglike
kingly
kingpin
kingpins
kingpost
kings
kingship
kingside
kingwood
kinin
kinins
kink
kinkajou
kinked
kinkier
kinkiest
kinkily
kinking
kinks
kinky
kino
kinos
kins
kinsfolk
kinship
kinships
kinsman
kinsmen
kiosk
kiosks
kip
kipped
kippen
kipper
kippered
kipperer
kippers
kipping
kips
kipskin
kipskins
kir
kirigami
kirk
kirkman
kirkmen
kirks
kirmess
kirn
kirned
kirning
kirns
kirs
kirsch
kirsches
kirtle
kirtled
kirtles
kishka
kishkas
kishke
kishkes
kismat
kismats
kismet
kismetic
kismets
kiss
kissable
kissably
kissed
kisser
kissers
kisses
kissing
kissy
kist
kistful
kistfuls
kists
kit
kitchen
kitchens
kite
kited
kitelike
kiter
kiters
kites
kith
kithara
kitharas
kithe
kithed
kithes
kithing
kiths
kiting
kitling
kitlings
kits
kitsch
kitsches
kitschy
kitted
kittel
kitten
kittened
kittens
kitties
kitting
kittle
kittled
kittler
kittles
kittlest
kittling
kitty
kiva
kivas
kiwi
kiwis
klatch
klatches
klatsch
klavern
klaverns
klaxon
klaxons
kleagle
kleagles
klepht
klephtic
klephts
klezmer
klister
klisters
klong
klongs
kloof
kloofs
kludge
kludges
kluge
kluges
klutz
klutzes
klutzier
klutzy
klystron
knack
knacked
knacker
knackers
knackery
knacking
knacks
knap
knapped
knapper
knappers
knapping
knaps
knapsack
knapweed
knar
knarred
knarry
knars
knaur
knaurs
knave
knavery
knaves
knavish
knawel
knawels
knead
kneaded
kneader
kneaders
kneading
kneads
knee
kneecap
kneecaps
kneed
kneehole
kneeing
kneel
kneeled
kneeler
kneelers
kneeling
kneels
kneepad
kneepads
kneepan
kneepans
knees
kneesock
knell
knelled
knelling
knells
knelt
knesset
knessets
knew
knickers
knife
knifed
knifer
knifers
knifes
knifing
knight
knighted
knightly
knights
knish
knishes
knit
knits
knitted
knitter
knitters
knitting
knitwear
knives
knob
knobbed
knobbier
knobbly
knobby
knoblike
knobs
knock
knocked
knocker
knockers
knocking
knockoff
knockout
knocks
knoll
knolled
knoller
knollers
knolling
knolls
knolly
knop
knopped
knops
knosp
knosps
knot
knothole
knotless
knotlike
knots
knotted
knotter
knotters
knottier
knottily
knotting
knotty
knotweed
knout
knouted
knouting
knouts
know
knowable
knower
knowers
knowing
knowings
known
knowns
knows
knubbier
knubby
knuckle
knuckled
knuckler
knuckles
knuckly
knur
knurl
knurled
knurlier
knurling
knurls
knurly
knurs
koa
koala
koalas
koan
koans
koas
kob
kobo
kobold
kobolds
kobs
koel
koels
kohl
kohlrabi
kohls
koi
koine
koines
kokanee
kokanees
kola
kolacky
kolas
kolbasi
kolbasis
kolbassi
kolhoz
kolhozes
kolhozy
kolinski
kolinsky
kolkhos
kolkhosy
kolkhoz
kolkhozy
kolkoz
kolkozes
kolkozy
kolo
kolos
komatik
komatiks
komondor
konk
konked
konking
konks
koodoo
koodoos
kook
kookie
kookier
kookiest
kooks
kooky
kop
kopeck
kopecks
kopek
kopeks
koph
kophs
kopje
kopjes
koppa
koppas
koppie
koppies
kops
kor
korai
korat
korats
kore
kors
korun
koruna
korunas
koruny
kos
kosher
koshered
koshers
koss
koto
kotos
kotow
kotowed
kotower
kotowers
kotowing
kotows
koumis
koumises
koumiss
koumys
koumyses
koumyss
kouprey
koupreys
kouroi
kouros
kousso
koussos
kowtow
kowtowed
kowtower
kowtows
kraal
kraaled
kraaling
kraals
kraft
krafts
krait
kraits
kraken
krakens
krater
kraters
kraut
krauts
kreep
kreeps
kremlin
kremlins
kreplach
kreutzer
kreuzer
kreuzers
krill
krills
krimmer
krimmers
kris
krises
krona
krone
kronen
kroner
kronor
kronur
kroon
krooni
kroons
krubi
krubis
krubut
krubuts
kruller
krullers
krumhorn
kryolite
kryolith
krypton
kryptons
kuchen
kudo
kudos
kudu
kudus
kudzu
kudzus
kue
kues
kugel
kugels
kukri
kukris
kulak
kulaki
kulaks
kultur
kulturs
kumiss
kumisses
kummel
kummels
kumquat
kumquats
kumys
kumyses
kunzite
kunzites
kurbash
kurgan
kurgans
kurta
kurtas
kurtosis
kuru
kurus
kusso
kussos
kuvasz
kuvaszok
kvas
kvases
kvass
kvasses
kvetch
kvetched
kvetches
kvetchy
kwacha
kwanza
kwanzas
kyack
kyacks
kyak
kyaks
kyanise
kyanised
kyanises
kyanite
kyanites
kyanize
kyanized
kyanizes
kyar
kyars
kyat
kyats
kybosh
kyboshed
kyboshes
kylikes
kylix
kymogram
kyphoses
kyphosis
kyphotic
kyrie
kyries
kyte
kytes
kythe
kythed
kythes
kything
la
laager
laagered
laagers
laari
lab
labara
labarum
labarums
labdanum
label
labeled
labeler
labelers
labeling
labella
labelled
labeller
labellum
labels
labia
labial
labially
labials
labiate
labiated
labiates
labile
lability
labium
labor
labored
laborer
laborers
laboring
laborite
labors
labour
laboured
labourer
labours
labra
labrador
labret
labrets
labroid
labroids
labrum
labrums
labrusca
labs
laburnum
lac
lace
laced
laceless
lacelike
lacer
lacerate
lacers
lacertid
laces
lacewing
lacewood
lacework
lacey
laches
lacier
laciest
lacily
laciness
lacing
lacings
lack
lackaday
lacked
lacker
lackered
lackers
lackey
lackeyed
lackeys
lacking
lacks
laconic
laconism
lacquer
lacquers
lacquey
lacqueys
lacrimal
lacrosse
lacs
lactam
lactams
lactary
lactase
lactases
lactate
lactated
lactates
lacteal
lacteals
lactean
lacteous
lactic
lactone
lactones
lactonic
lactose
lactoses
lacuna
lacunae
lacunal
lacunar
lacunars
lacunary
lacunas
lacunate
lacune
lacunes
lacunose
lacy
lad
ladanum
ladanums
ladder
laddered
ladders
laddie
laddies
lade
laded
laden
ladened
ladening
ladens
lader
laders
lades
ladies
lading
ladings
ladino
ladinos
ladle
ladled
ladleful
ladler
ladlers
ladles
ladling
ladron
ladrone
ladrones
ladrons
lads
lady
ladybird
ladybug
ladybugs
ladyfish
ladyhood
ladyish
ladykin
ladykins
ladylike
ladylove
ladypalm
ladyship
laetrile
laevo
lag
lagan
lagans
lagend
lagends
lager
lagered
lagering
lagers
laggard
laggards
lagged
lagger
laggers
lagging
laggings
lagnappe
lagoon
lagoonal
lagoons
lags
laguna
lagunas
lagune
lagunes
lahar
lahars
laic
laical
laically
laich
laichs
laicise
laicised
laicises
laicism
laicisms
laicize
laicized
laicizes
laics
laid
laigh
laighs
lain
lair
laird
lairdly
lairds
laired
lairing
lairs
laitance
laith
laithly
laities
laity
lake
laked
lakelike
lakeport
laker
lakers
lakes
lakeside
lakh
lakhs
lakier
lakiest
laking
lakings
laky
lall
lallan
lalland
lallands
lallans
lalled
lalling
lalls
lallygag
lam
lama
lamas
lamasery
lamb
lambast
lambaste
lambasts
lambda
lambdas
lambdoid
lambed
lambency
lambent
lamber
lambers
lambert
lamberts
lambie
lambier
lambies
lambiest
lambing
lambkill
lambkin
lambkins
lamblike
lambs
lambskin
lamby
lame
lamed
lamedh
lamedhs
lameds
lamella
lamellae
lamellar
lamellas
lamely
lameness
lament
lamented
lamenter
laments
lamer
lames
lamest
lamia
lamiae
lamias
lamina
laminae
laminal
laminar
laminary
laminas
laminate
laming
laminose
laminous
lamister
lammed
lamming
lamp
lampad
lampads
lampas
lampases
lamped
lampers
lamping
lampion
lampions
lampoon
lampoons
lamppost
lamprey
lampreys
lamps
lampyrid
lams
lamster
lamsters
lanai
lanais
lanate
lanated
lance
lanced
lancelet
lancer
lancers
lances
lancet
lanceted
lancets
lanciers
lancing
land
landau
landaus
landed
lander
landers
landfall
landfill
landform
landgrab
landing
landings
landlady
landler
landlers
landless
landline
landlord
landman
landmark
landmass
landmen
lands
landside
landskip
landslid
landslip
landsman
landsmen
landward
lane
lanely
lanes
laneway
laneways
lang
langlauf
langley
langleys
langrage
langrel
langrels
langshan
langsyne
language
langue
langues
languet
languets
languid
languish
languor
languors
langur
langurs
laniard
laniards
laniary
lanital
lanitals
lank
lanker
lankest
lankier
lankiest
lankily
lankly
lankness
lanky
lanner
lanneret
lanners
lanolin
lanoline
lanolins
lanose
lanosity
lantana
lantanas
lantern
lanterns
lanthorn
lanugo
lanugos
lanyard
lanyards
lap
lapboard
lapdog
lapdogs
lapel
lapeled
lapelled
lapels
lapful
lapfuls
lapidary
lapidate
lapides
lapidify
lapidist
lapilli
lapillus
lapin
lapins
lapis
lapises
lapped
lapper
lappered
lappers
lappet
lappeted
lappets
lapping
laps
lapsable
lapse
lapsed
lapser
lapsers
lapses
lapsible
lapsing
lapsus
laptop
laptops
lapwing
lapwings
lar
larboard
larcener
larceny
larch
larches
lard
larded
larder
larders
lardier
lardiest
larding
lardlike
lardon
lardons
lardoon
lardoons
lards
lardy
laree
larees
lares
largando
large
largely
larger
larges
largess
largesse
largest
largish
largo
largos
lari
lariat
lariated
lariats
larine
laris
lark
larked
larker
larkers
larkier
larkiest
larking
larkish
larks
larksome
larkspur
larky
larrigan
larrikin
larrup
larruped
larruper
larrups
lars
larum
larums
larva
larvae
larval
larvas
laryngal
larynges
larynx
larynxes
las
lasagna
lasagnas
lasagne
lasagnes
lascar
lascars
lase
lased
laser
lasers
lases
lash
lashed
lasher
lashers
lashes
lashing
lashings
lashins
lashkar
lashkars
lasing
lass
lasses
lassie
lassies
lasso
lassoed
lassoer
lassoers
lassoes
lassoing
lassos
last
lasted
laster
lasters
lasting
lastings
lastly
lasts
lat
latakia
latakias
latch
latched
latches
latchet
latchets
latching
latchkey
late
lated
lateen
lateener
lateens
lately
laten
latency
latened
lateness
latening
latens
latent
latently
latents
later
laterad
lateral
laterals
laterite
laterize
latest
latests
latewood
latex
latexes
lath
lathe
lathed
lather
lathered
latherer
lathers
lathery
lathes
lathi
lathier
lathiest
lathing
lathings
lathis
laths
lathwork
lathy
lati
latices
latigo
latigoes
latigos
latinity
latinize
latino
latinos
latish
latitude
latke
latkes
latosol
latosols
latria
latrias
latrine
latrines
lats
latte
latten
lattens
latter
latterly
lattes
lattice
latticed
lattices
lattin
lattins
lauan
lauans
laud
laudable
laudably
laudanum
laudator
lauded
lauder
lauders
lauding
lauds
laugh
laughed
laugher
laughers
laughing
laughs
laughter
launce
launces
launch
launched
launcher
launches
launder
launders
laundry
laura
laurae
lauras
laureate
laurel
laureled
laurels
lauwine
lauwines
lav
lava
lavabo
lavaboes
lavabos
lavage
lavages
lavalava
lavalier
lavalike
lavas
lavation
lavatory
lave
laved
laveer
laveered
laveers
lavender
laver
laverock
lavers
laves
laving
lavish
lavished
lavisher
lavishes
lavishly
lavrock
lavrocks
lavs
law
lawbook
lawbooks
lawed
lawful
lawfully
lawgiver
lawine
lawines
lawing
lawings
lawless
lawlike
lawmaker
lawman
lawmen
lawn
lawns
lawny
laws
lawsuit
lawsuits
lawyer
lawyered
lawyerly
lawyers
lax
laxation
laxative
laxer
laxest
laxities
laxity
laxly
laxness
lay
layabout
layaway
layaways
layed
layer
layerage
layered
layering
layers
layette
layettes
laying
layman
laymen
layoff
layoffs
layout
layouts
layover
layovers
lays
layup
layups
laywoman
laywomen
lazar
lazaret
lazarets
lazars
laze
lazed
lazes
lazied
lazier
lazies
laziest
lazily
laziness
lazing
lazuli
lazulis
lazulite
lazurite
lazy
lazying
lazyish
lea
leach
leachate
leached
leacher
leachers
leaches
leachier
leaching
leachy
lead
leaded
leaden
leadenly
leader
leaders
leadier
leadiest
leading
leadings
leadless
leadman
leadmen
leadoff
leadoffs
leads
leadsman
leadsmen
leadwork
leadwort
leady
leaf
leafage
leafages
leafed
leafier
leafiest
leafing
leafless
leaflet
leaflets
leaflike
leafs
leafworm
leafy
league
leagued
leaguer
leaguers
leagues
leaguing
leak
leakage
leakages
leaked
leaker
leakers
leakier
leakiest
leakily
leaking
leakless
leaks
leaky
leal
leally
lealties
lealty
lean
leaned
leaner
leaners
leanest
leaning
leanings
leanly
leanness
leans
leant
leap
leaped
leaper
leapers
leapfrog
leaping
leaps
leapt
lear
learier
leariest
learn
learned
learner
learners
learning
learns
learnt
lears
leary
leas
leasable
lease
leased
leaser
leasers
leases
leash
leashed
leashes
leashing
leasing
leasings
least
leasts
leather
leathern
leathers
leathery
leave
leaved
leaven
leavened
leavens
leaver
leavers
leaves
leavier
leaviest
leaving
leavings
leavy
leben
lebens
lech
lechayim
leched
lecher
lechered
lechers
lechery
leches
leching
lechwe
lechwes
lecithin
lectern
lecterns
lectin
lectins
lection
lections
lector
lectors
lecture
lectured
lecturer
lectures
lecythi
lecythis
lecythus
led
ledge
ledger
ledgers
ledges
ledgier
ledgiest
ledgy
lee
leeboard
leech
leeched
leeches
leeching
leek
leeks
leer
leered
leerier
leeriest
leerily
leering
leers
leery
lees
leet
leets
leeward
leewards
leeway
leeways
left
lefter
leftest
lefties
leftish
leftism
leftisms
leftist
leftists
leftover
lefts
leftward
leftwing
lefty
leg
legacies
legacy
legal
legalese
legalise
legalism
legalist
legality
legalize
legally
legals
legate
legated
legatee
legatees
legates
legatine
legating
legation
legato
legator
legators
legatos
legend
legendry
legends
leger
legerity
legers
leges
legged
leggier
leggiero
leggiest
leggin
legging
leggings
leggins
leggy
leghorn
leghorns
legible
legibly
legion
legions
legist
legists
legit
legits
legless
leglike
legman
legmen
legong
legongs
legroom
legrooms
legs
legume
legumes
legumin
legumins
legwork
legworks
lehayim
lehayims
lehr
lehrs
lehua
lehuas
lei
leis
leister
leisters
leisure
leisured
leisures
lek
leke
leks
leku
lekvar
lekvars
lekythi
lekythoi
lekythos
lekythus
leman
lemans
lemma
lemmas
lemmata
lemming
lemmings
lemnisci
lemon
lemonade
lemonish
lemons
lemony
lempira
lempiras
lemur
lemures
lemurine
lemuroid
lemurs
lend
lendable
lender
lenders
lending
lends
lenes
length
lengthen
lengths
lengthy
lenience
leniency
lenient
lenis
lenities
lenition
lenitive
lenity
leno
lenos
lens
lense
lensed
lenses
lensing
lensless
lensman
lensmen
lent
lentando
lenten
lentic
lenticel
lentigo
lentil
lentils
lentisk
lentisks
lento
lentoid
lentos
leone
leones
leonine
leopard
leopards
leotard
leotards
leper
lepers
lepidote
leporid
leporids
leporine
leprose
leprosy
leprotic
leprous
lept
lepta
lepton
leptonic
leptons
lesbian
lesbians
lesion
lesioned
lesions
less
lessee
lessees
lessen
lessened
lessens
lesser
lesson
lessoned
lessons
lessor
lessors
lest
let
letch
letched
letches
letching
letdown
letdowns
lethal
lethally
lethals
lethargy
lethe
lethean
lethes
lets
letted
letter
lettered
letterer
letters
letting
lettuce
lettuces
letup
letups
leu
leucemia
leucemic
leucin
leucine
leucines
leucins
leucite
leucites
leucitic
leucoma
leucomas
leud
leudes
leuds
leukemia
leukemic
leukoma
leukomas
leukon
leukons
leukoses
leukosis
leukotic
lev
leva
levant
levanted
levanter
levants
levator
levators
levee
leveed
leveeing
levees
level
leveled
leveler
levelers
leveling
levelled
leveller
levelly
levels
lever
leverage
levered
leveret
leverets
levering
levers
leviable
levied
levier
leviers
levies
levigate
levin
levins
levirate
levitate
levities
levity
levo
levodopa
levogyre
levulin
levulins
levulose
levy
levying
lewd
lewder
lewdest
lewdly
lewdness
lewis
lewises
lewisite
lewisson
lex
lexeme
lexemes
lexemic
lexes
lexica
lexical
lexicon
lexicons
lexis
ley
leys
lez
lezzes
lezzie
lezzies
lezzy
li
liable
liaise
liaised
liaises
liaising
liaison
liaisons
liana
lianas
liane
lianes
liang
liangs
lianoid
liar
liard
liards
liars
lib
libation
libber
libbers
libeccio
libel
libelant
libeled
libelee
libelees
libeler
libelers
libeling
libelist
libelled
libellee
libeller
libelous
libels
liber
liberal
liberals
liberate
libers
liberty
libido
libidos
liblab
liblabs
libra
librae
library
libras
librate
librated
librates
libretti
libretto
libri
libs
lice
licence
licenced
licencee
licencer
licences
license
licensed
licensee
licenser
licenses
licensor
licente
lich
lichee
lichees
lichen
lichened
lichenin
lichens
liches
lichi
lichis
licht
lichted
lichting
lichtly
lichts
licit
licitly
lick
licked
licker
lickers
licking
lickings
licks
lickspit
licorice
lictor
lictors
lid
lidar
lidars
lidded
lidding
lidless
lido
lidos
lids
lie
lied
lieder
lief
liefer
liefest
liefly
liege
liegeman
liegemen
lieges
lien
lienable
lienal
liens
lientery
lier
lierne
liernes
liers
lies
lieu
lieus
lieve
liever
lievest
life
lifeboat
lifeful
lifeless
lifelike
lifeline
lifelong
lifer
lifers
lifetime
lifeway
lifeways
lifework
lift
liftable
lifted
lifter
lifters
liftgate
lifting
liftman
liftmen
liftoff
liftoffs
lifts
ligament
ligan
ligand
ligands
ligans
ligase
ligases
ligate
ligated
ligates
ligating
ligation
ligative
ligature
liger
ligers
light
lighted
lighten
lightens
lighter
lighters
lightest
lightful
lighting
lightish
lightly
lights
ligneous
lignify
lignin
lignins
lignite
lignites
lignitic
ligroin
ligroine
ligroins
ligula
ligulae
ligular
ligulas
ligulate
ligule
ligules
liguloid
ligure
ligures
likable
like
likeable
liked
likelier
likely
liken
likened
likeness
likening
likens
liker
likers
likes
likest
likewise
liking
likings
likuta
lilac
lilacs
lilied
lilies
lilliput
lilt
lilted
lilting
lilts
lily
lilylike
lima
limacine
limacon
limacons
liman
limans
limas
limb
limba
limbas
limbate
limbeck
limbecks
limbed
limber
limbered
limberer
limberly
limbers
limbi
limbic
limbier
limbiest
limbing
limbless
limbo
limbos
limbs
limbus
limbuses
limby
lime
limeade
limeades
limed
limekiln
limeless
limen
limens
limerick
limes
limey
limeys
limier
limiest
limina
liminal
liminess
liming
limit
limitary
limited
limiteds
limiter
limiters
limites
limiting
limits
limmer
limmers
limn
limned
limner
limners
limnetic
limnic
limning
limns
limo
limonene
limonite
limos
limp
limpa
limpas
limped
limper
limpers
limpest
limpet
limpets
limpid
limpidly
limping
limpkin
limpkins
limply
limpness
limps
limpsey
limpsier
limpsy
limuli
limuloid
limulus
limy
lin
linable
linac
linacs
linage
linages
linalol
linalols
linalool
linchpin
lindane
lindanes
linden
lindens
lindies
lindy
line
lineable
lineage
lineages
lineal
lineally
linear
linearly
lineate
lineated
linebred
linecut
linecuts
lined
lineless
linelike
lineman
linemen
linen
linens
lineny
liner
liners
lines
linesman
linesmen
lineup
lineups
liney
ling
linga
lingam
lingams
lingas
lingcod
lingcods
linger
lingered
lingerer
lingerie
lingers
lingier
lingiest
lingo
lingoes
lings
lingua
linguae
lingual
linguals
linguine
linguini
linguist
lingy
linier
liniest
liniment
linin
lining
linings
linins
link
linkable
linkage
linkages
linkboy
linkboys
linked
linker
linkers
linking
linkman
linkmen
links
linksman
linksmen
linkup
linkups
linkwork
linky
linn
linnet
linnets
linns
lino
linocut
linocuts
linoleum
linos
lins
linsang
linsangs
linseed
linseeds
linsey
linseys
linstock
lint
lintel
lintels
linter
linters
lintier
lintiest
lintless
lintol
lintols
lints
linty
linum
linums
linuron
linurons
liny
lion
lioness
lionfish
lionise
lionised
lioniser
lionises
lionize
lionized
lionizer
lionizes
lionlike
lions
lip
lipase
lipases
lipid
lipide
lipides
lipidic
lipids
lipin
lipins
lipless
liplike
lipocyte
lipoid
lipoidal
lipoids
lipoma
lipomas
lipomata
liposome
lipped
lippen
lippened
lippens
lipper
lippered
lippers
lippier
lippiest
lipping
lippings
lippy
lips
lipstick
liquate
liquated
liquates
liquefy
liqueur
liqueurs
liquid
liquidly
liquids
liquify
liquor
liquored
liquors
lira
liras
lire
liri
liripipe
lirot
liroth
lis
lisente
lisle
lisles
lisp
lisped
lisper
lispers
lisping
lisps
lissom
lissome
lissomly
list
listable
listed
listee
listees
listel
listels
listen
listened
listener
listens
lister
listers
listing
listings
listless
lists
lit
litai
litanies
litany
litas
litchi
litchis
lite
liter
literacy
literal
literals
literary
literate
literati
liters
litharge
lithe
lithely
lithemia
lithemic
lither
lithest
lithia
lithias
lithic
lithify
lithium
lithiums
litho
lithoed
lithoid
lithoing
lithos
lithosol
litigant
litigate
litmus
litmuses
litoral
litotes
litotic
litre
litres
lits
litten
litter
littered
litterer
litters
littery
little
littler
littles
littlest
littlish
littoral
litu
liturgic
liturgy
livable
live
liveable
lived
livelier
livelily
livelong
lively
liven
livened
livener
liveners
liveness
livening
livens
liver
liveried
liveries
liverish
livers
livery
lives
livest
livetrap
livid
lividity
lividly
livier
liviers
living
livingly
livings
livre
livres
livyer
livyers
lixivia
lixivial
lixivium
lizard
lizards
llama
llamas
llano
llanos
lo
loach
loaches
load
loaded
loader
loaders
loading
loadings
loads
loadstar
loaf
loafed
loafer
loafers
loafing
loafs
loam
loamed
loamier
loamiest
loaming
loamless
loams
loamy
loan
loanable
loaned
loaner
loaners
loaning
loanings
loans
loanword
loath
loathe
loathed
loather
loathers
loathes
loathful
loathing
loathly
loaves
lob
lobar
lobate
lobated
lobately
lobation
lobbed
lobber
lobbers
lobbied
lobbies
lobbing
lobby
lobbyer
lobbyers
lobbygow
lobbying
lobbyism
lobbyist
lobe
lobed
lobefin
lobefins
lobelia
lobelias
lobeline
lobes
loblolly
lobo
lobos
lobotomy
lobs
lobster
lobsters
lobstick
lobular
lobulate
lobule
lobules
lobulose
lobworm
lobworms
loca
local
locale
locales
localise
localism
localist
localite
locality
localize
locally
locals
locate
located
locater
locaters
locates
locating
location
locative
locator
locators
loch
lochan
lochans
lochia
lochial
lochs
loci
lock
lockable
lockage
lockages
lockbox
lockdown
locked
locker
lockers
locket
lockets
locking
lockjaw
lockjaws
locknut
locknuts
lockout
lockouts
lockram
lockrams
locks
lockstep
lockup
lockups
loco
locoed
locoes
locofoco
locoing
locoism
locoisms
locomote
locos
locoweed
locular
loculate
locule
loculed
locules
loculi
loculus
locum
locums
locus
locust
locusta
locustae
locustal
locusts
locution
locutory
lode
loden
lodens
lodes
lodestar
lodge
lodged
lodger
lodgers
lodges
lodging
lodgings
lodgment
lodicule
loess
loessal
loesses
loessial
loft
lofted
lofter
lofters
loftier
loftiest
loftily
lofting
loftless
loftlike
lofts
lofty
log
logan
logania
logans
logbook
logbooks
loge
loges
loggats
logged
logger
loggers
loggets
loggia
loggias
loggie
loggier
loggiest
logging
loggings
loggy
logia
logic
logical
logician
logicise
logicize
logics
logier
logiest
logily
loginess
logion
logions
logistic
logjam
logjams
logo
logogram
logoi
logomach
logos
logotype
logotypy
logroll
logrolls
logs
logway
logways
logwood
logwoods
logy
loin
loins
loiter
loitered
loiterer
loiters
loll
lolled
loller
lollers
lollies
lolling
lollipop
lollop
lolloped
lollops
lolls
lolly
lollygag
lollypop
lomein
lomeins
loment
lomenta
loments
lomentum
lone
lonelier
lonelily
lonely
loneness
loner
loners
lonesome
long
longan
longans
longboat
longbow
longbows
longe
longed
longeing
longer
longeron
longers
longes
longest
longhair
longhand
longhead
longhorn
longies
longing
longings
longish
longleaf
longline
longly
longness
longs
longship
longsome
longspur
longtime
longueur
longways
longwise
loo
loobies
looby
looed
looey
looeys
loof
loofa
loofah
loofahs
loofas
loofs
looie
looies
looing
look
lookdown
looked
looker
lookers
looking
lookout
lookouts
looks
lookup
lookups
loom
loomed
looming
looms
loon
looney
looneys
loonier
loonies
looniest
loons
loony
loop
looped
looper
loopers
loophole
loopier
loopiest
looping
loops
loopy
loos
loose
loosed
loosely
loosen
loosened
loosener
loosens
looser
looses
loosest
loosing
loot
looted
looter
looters
looting
loots
lop
lope
loped
loper
lopers
lopes
loping
lopped
lopper
loppered
loppers
loppier
loppiest
lopping
loppy
lops
lopsided
lopstick
loquat
loquats
loral
loran
lorans
lord
lorded
lording
lordings
lordless
lordlier
lordlike
lordling
lordly
lordoma
lordomas
lordoses
lordosis
lordotic
lords
lordship
lore
loreal
lores
lorgnon
lorgnons
lorica
loricae
loricate
lories
lorikeet
lorimer
lorimers
loriner
loriners
loris
lorises
lorn
lornness
lorries
lorry
lory
losable
lose
losel
losels
loser
losers
loses
losing
losingly
losings
loss
losses
lossy
lost
lostness
lot
lota
lotah
lotahs
lotas
loth
lothario
lothsome
loti
lotic
lotion
lotions
lotos
lotoses
lots
lotte
lotted
lottery
lottes
lotting
lotto
lottos
lotus
lotuses
louche
loud
louden
loudened
loudens
louder
loudest
loudish
loudlier
loudly
loudness
lough
loughs
louie
louies
louis
lounge
lounged
lounger
loungers
lounges
lounging
loungy
loup
loupe
louped
loupen
loupes
louping
loups
lour
loured
louring
lours
loury
louse
loused
louses
lousier
lousiest
lousily
lousing
lousy
lout
louted
louting
loutish
louts
louver
louvered
louvers
louvre
louvred
louvres
lovable
lovably
lovage
lovages
lovat
lovats
love
loveable
loveably
lovebird
lovebug
lovebugs
loved
loveless
lovelier
lovelies
lovelily
lovelock
lovelorn
lovely
lover
loverly
lovers
loves
lovesick
lovesome
lovevine
loving
lovingly
low
lowball
lowballs
lowborn
lowboy
lowboys
lowbred
lowbrow
lowbrows
lowdown
lowdowns
lowe
lowed
lower
lowered
lowering
lowers
lowery
lowes
lowest
lowing
lowings
lowish
lowland
lowlands
lowlier
lowliest
lowlife
lowlifer
lowlifes
lowlight
lowlives
lowly
lown
lowness
lowrider
lows
lowse
lox
loxed
loxes
loxing
loyal
loyaler
loyalest
loyalism
loyalist
loyally
loyalty
lozenge
lozenges
luau
luaus
lubber
lubberly
lubbers
lube
lubes
lubric
lubrical
lucarne
lucarnes
luce
lucence
lucences
lucency
lucent
lucently
lucern
lucerne
lucernes
lucerns
luces
lucid
lucidity
lucidly
lucifer
lucifers
luck
lucked
luckie
luckier
luckies
luckiest
luckily
lucking
luckless
lucks
lucky
lucre
lucres
luculent
lude
ludes
ludic
lues
luetic
luetics
luff
luffa
luffas
luffed
luffing
luffs
lug
luge
luged
lugeing
luger
lugers
luges
luggage
luggages
lugged
lugger
luggers
luggie
luggies
lugging
lugs
lugsail
lugsails
lugworm
lugworms
lukewarm
lull
lullaby
lulled
lulling
lulls
lulu
lulus
lum
lumbago
lumbagos
lumbar
lumbars
lumber
lumbered
lumberer
lumbers
lumen
lumenal
lumens
lumina
luminal
luminary
luminism
luminist
luminous
lummox
lummoxes
lump
lumped
lumpen
lumpens
lumper
lumpers
lumpfish
lumpier
lumpiest
lumpily
lumping
lumpish
lumps
lumpy
lums
luna
lunacies
lunacy
lunar
lunarian
lunars
lunas
lunate
lunated
lunately
lunatic
lunatics
lunation
lunch
lunched
luncheon
luncher
lunchers
lunches
lunching
lune
lunes
lunet
lunets
lunette
lunettes
lung
lungan
lungans
lunge
lunged
lungee
lungees
lunger
lungers
lunges
lungfish
lungful
lungfuls
lungi
lunging
lungis
lungs
lungworm
lungwort
lungyi
lungyis
lunier
lunies
luniest
lunk
lunker
lunkers
lunkhead
lunks
lunt
lunted
lunting
lunts
lunula
lunulae
lunular
lunulate
lunule
lunules
luny
lupanar
lupanars
lupin
lupine
lupines
lupins
lupous
lupulin
lupulins
lupus
lupuses
lurch
lurched
lurcher
lurchers
lurches
lurching
lurdan
lurdane
lurdanes
lurdans
lure
lured
lurer
lurers
lures
lurid
luridly
luring
lurk
lurked
lurker
lurkers
lurking
lurks
luscious
lush
lushed
lusher
lushes
lushest
lushing
lushly
lushness
lust
lusted
luster
lustered
lusters
lustful
lustier
lustiest
lustily
lusting
lustra
lustral
lustrate
lustre
lustred
lustres
lustring
lustrous
lustrum
lustrums
lusts
lusty
lusus
lususes
lutanist
lute
lutea
luteal
lutecium
luted
lutefisk
lutein
luteins
lutenist
luteolin
luteous
lutes
lutetium
luteum
luthern
lutherns
luthier
luthiers
luting
lutings
lutist
lutists
lutz
lutzes
luv
luvs
lux
luxate
luxated
luxates
luxating
luxation
luxe
luxes
luxuries
luxury
lwei
lweis
lyard
lyart
lyase
lyases
lycea
lycee
lycees
lyceum
lyceums
lychee
lychees
lychnis
lycopene
lycopod
lycopods
lyddite
lyddites
lye
lyes
lying
lyingly
lyings
lymph
lymphoid
lymphoma
lymphs
lyncean
lynch
lynched
lyncher
lynchers
lynches
lynching
lynchpin
lynx
lynxes
lyophile
lyrate
lyrated
lyrately
lyre
lyrebird
lyres
lyric
lyrical
lyricise
lyricism
lyricist
lyricize
lyrics
lyriform
lyrism
lyrisms
lyrist
lyrists
lysate
lysates
lyse
lysed
lyses
lysin
lysine
lysines
lysing
lysins
lysis
lysogen
lysogens
lysogeny
lysosome
lysozyme
lyssa
lyssas
lytic
lytta
lyttae
lyttas
ma
maar
maars
mabe
mabes
mac
macaber
macabre
macaco
macacos
macadam
macadams
macaque
macaques
macaroni
macaroon
macaw
macaws
maccabaw
maccaboy
macchia
macchie
maccoboy
mace
maced
macer
macerate
macers
maces
mach
mache
maches
machete
machetes
machine
machined
machines
machismo
macho
machos
machree
machrees
machs
machzor
machzors
macing
mack
mackerel
mackinaw
mackle
mackled
mackles
mackling
macks
macle
macled
macles
macon
macons
macrame
macrames
macro
macron
macrons
macros
macrural
macruran
macs
macula
maculae
macular
maculas
maculate
macule
maculed
macules
maculing
macumba
macumbas
mad
madam
madame
madames
madams
madcap
madcaps
madded
madden
maddened
maddens
madder
madders
maddest
madding
maddish
made
madeira
madeiras
madhouse
madly
madman
madmen
madness
madonna
madonnas
madras
madrases
madre
madres
madrigal
madrona
madronas
madrone
madrones
madrono
madronos
mads
maduro
maduros
madwoman
madwomen
madwort
madworts
madzoon
madzoons
mae
maenad
maenades
maenadic
maenads
maes
maestoso
maestri
maestro
maestros
maffia
maffias
maffick
mafficks
mafia
mafias
mafic
mafiosi
mafioso
maftir
maftirs
mag
magazine
magdalen
mage
magenta
magentas
mages
maggot
maggots
maggoty
magi
magian
magians
magic
magical
magician
magicked
magics
magilp
magilps
magister
maglev
maglevs
magma
magmas
magmata
magmatic
magnate
magnates
magnesia
magnesic
magnet
magnetic
magneto
magneton
magnetos
magnets
magnific
magnify
magnolia
magnum
magnums
magot
magots
magpie
magpies
mags
maguey
magueys
magus
maharaja
maharani
mahatma
mahatmas
mahimahi
mahjong
mahjongg
mahjongs
mahoe
mahoes
mahogany
mahonia
mahonias
mahout
mahouts
mahuang
mahuangs
mahzor
mahzorim
mahzors
maid
maiden
maidenly
maidens
maidhood
maidish
maids
maieutic
maigre
maihem
maihems
mail
mailable
mailbag
mailbags
mailbox
maile
mailed
mailer
mailers
mailes
mailing
mailings
maill
mailless
maillot
maillots
maills
mailman
mailmen
mails
maim
maimed
maimer
maimers
maiming
maims
main
mainland
mainline
mainly
mainmast
mains
mainsail
mainstay
maintain
maintop
maintops
maiolica
mair
mairs
maist
maists
maize
maizes
majagua
majaguas
majestic
majesty
majolica
major
majored
majoring
majority
majorly
majors
makable
makar
makars
make
makeable
makebate
makefast
makeover
maker
makers
makes
makeup
makeups
makimono
making
makings
mako
makos
makuta
malacca
malaccas
maladies
malady
malaise
malaises
malamute
malanga
malangas
malapert
malaprop
malar
malaria
malarial
malarian
malarias
malarkey
malarky
malaroma
malars
malate
malates
male
maleate
maleates
maledict
malefic
malemiut
malemute
maleness
males
malfed
malgre
malic
malice
malices
malign
maligned
maligner
malignly
maligns
malihini
maline
malines
malinger
malison
malisons
malkin
malkins
mall
mallard
mallards
malled
mallee
mallees
mallei
malleoli
mallet
mallets
malleus
malling
mallow
mallows
malls
malm
malmier
malmiest
malms
malmsey
malmseys
malmy
malodor
malodors
maloti
malposed
malt
maltase
maltases
malted
malteds
maltha
malthas
maltier
maltiest
malting
maltol
maltols
maltose
maltoses
maltreat
malts
maltster
malty
malvasia
mama
mamaliga
mamas
mamba
mambas
mambo
mamboed
mamboes
mamboing
mambos
mameluke
mamey
mameyes
mameys
mamie
mamies
mamluk
mamluks
mamma
mammae
mammal
mammals
mammary
mammas
mammate
mammati
mammatus
mammee
mammees
mammer
mammered
mammers
mammet
mammets
mammey
mammeys
mammie
mammies
mammilla
mammitis
mammock
mammocks
mammon
mammons
mammoth
mammoths
mammy
man
mana
manacle
manacled
manacles
manage
managed
manager
managers
manages
managing
manakin
manakins
manana
mananas
manas
manatee
manatees
manatoid
manche
manches
manchet
manchets
manciple
mandala
mandalas
mandalic
mandamus
mandarin
mandate
mandated
mandates
mandator
mandible
mandioca
mandola
mandolas
mandolin
mandrake
mandrel
mandrels
mandril
mandrill
mandrils
mane
maned
manege
maneges
maneless
manes
maneuver
manful
manfully
mangabey
mangaby
manganic
mange
mangel
mangels
manger
mangers
manges
mangey
mangier
mangiest
mangily
mangle
mangled
mangler
manglers
mangles
mangling
mango
mangoes
mangold
mangolds
mangonel
mangos
mangrove
mangy
manhole
manholes
manhood
manhoods
manhunt
manhunts
mania
maniac
maniacal
maniacs
manias
manic
manics
manicure
manifest
manifold
manihot
manihots
manikin
manikins
manila
manilas
manilla
manillas
manille
manilles
manioc
manioca
maniocas
maniocs
maniple
maniples
manito
manitos
manitou
manitous
manitu
manitus
mankind
manless
manlier
manliest
manlike
manlily
manly
manmade
manna
mannan
mannans
mannas
manned
manner
mannered
mannerly
manners
mannikin
manning
mannish
mannite
mannites
mannitic
mannitol
mannose
mannoses
mano
manor
manorial
manors
manos
manpack
manpower
manque
manrope
manropes
mans
mansard
mansards
manse
manses
mansion
mansions
manta
mantas
manteau
manteaus
manteaux
mantel
mantelet
mantels
mantes
mantic
mantid
mantids
mantilla
mantis
mantises
mantissa
mantle
mantled
mantles
mantlet
mantlets
mantling
mantra
mantrap
mantraps
mantras
mantric
mantua
mantuas
manual
manually
manuals
manuary
manubria
manumit
manumits
manure
manured
manurer
manurers
manures
manurial
manuring
manus
manward
manwards
manwise
many
manyfold
map
maple
maples
maplike
mapmaker
mappable
mapped
mapper
mappers
mapping
mappings
maps
maquette
maqui
maquis
mar
marabou
marabous
marabout
maraca
maracas
maranta
marantas
marasca
marascas
marasmic
marasmus
marathon
maraud
marauded
marauder
marauds
maravedi
marble
marbled
marbler
marblers
marbles
marblier
marbling
marbly
marc
marcato
marcel
marcels
march
marched
marchen
marcher
marchers
marches
marchesa
marchese
marchesi
marching
marcs
mare
maremma
maremme
marengo
mares
margaric
margarin
margay
margays
marge
margent
margents
marges
margin
marginal
margined
margins
margrave
maria
mariachi
marigold
marimba
marimbas
marina
marinade
marinara
marinas
marinate
marine
mariner
mariners
marines
mariposa
marish
marishes
marital
maritime
marjoram
mark
markdown
marked
markedly
marker
markers
market
marketed
marketer
markets
markhoor
markhor
markhors
marking
markings
markka
markkaa
markkas
marks
marksman
marksmen
markup
markups
marl
marled
marlier
marliest
marlin
marline
marlines
marling
marlings
marlins
marlite
marlites
marlitic
marls
marly
marmite
marmites
marmoset
marmot
marmots
marocain
maroon
marooned
maroons
marplot
marplots
marque
marquee
marquees
marques
marquess
marquis
marquise
marram
marrams
marrano
marranos
marred
marrer
marrers
marriage
married
marrieds
marrier
marriers
marries
marring
marron
marrons
marrow
marrowed
marrows
marrowy
marry
marrying
mars
marsala
marsalas
marse
marses
marsh
marshal
marshall
marshals
marshes
marshier
marshy
marsupia
mart
martagon
marted
martello
marten
martens
martial
martian
martians
martin
martinet
marting
martini
martinis
martins
martlet
martlets
marts
martyr
martyred
martyrly
martyrs
martyry
marvel
marveled
marvels
marvy
maryjane
marzipan
mas
mascara
mascaras
mascon
mascons
mascot
mascots
maser
masers
mash
mashed
masher
mashers
mashes
mashie
mashies
mashing
mashy
masjid
masjids
mask
maskable
masked
maskeg
maskegs
masker
maskers
masking
maskings
masklike
masks
mason
masoned
masonic
masoning
masonry
masons
masque
masquer
masquers
masques
mass
massa
massacre
massage
massaged
massager
massages
massas
masscult
masse
massed
massedly
masses
masseter
masseur
masseurs
masseuse
massicot
massier
massiest
massif
massifs
massing
massive
massless
massy
mast
mastaba
mastabah
mastabas
masted
master
mastered
masterly
masters
mastery
masthead
mastic
mastiche
mastics
mastiff
mastiffs
masting
mastitic
mastitis
mastix
mastixes
mastless
mastlike
mastodon
mastoid
mastoids
masts
masurium
mat
matador
matadors
match
matchbox
matched
matcher
matchers
matches
matching
matchup
matchups
mate
mated
mateless
matelot
matelote
matelots
mater
material
materiel
maternal
maters
mates
mateship
matey
mateys
math
maths
matilda
matildas
matin
matinal
matinee
matinees
matiness
mating
matings
matins
matless
matrass
matres
matrices
matrix
matrixes
matron
matronal
matronly
matrons
mats
matsah
matsahs
matt
matte
matted
mattedly
matter
mattered
matters
mattery
mattes
mattin
matting
mattings
mattins
mattock
mattocks
mattoid
mattoids
mattrass
mattress
matts
maturate
mature
matured
maturely
maturer
matures
maturest
maturing
maturity
matza
matzah
matzahs
matzas
matzo
matzoh
matzohs
matzoon
matzoons
matzos
matzot
matzoth
maud
maudlin
mauds
mauger
maugre
maul
mauled
mauler
maulers
mauling
mauls
maumet
maumetry
maumets
maun
maund
maunder
maunders
maundies
maunds
maundy
mausolea
maut
mauts
mauve
mauves
maven
mavens
maverick
mavie
mavies
mavin
mavins
mavis
mavises
maw
mawed
mawing
mawkish
mawn
maws
max
maxes
maxi
maxicoat
maxilla
maxillae
maxillas
maxim
maxima
maximal
maximals
maximin
maximins
maximise
maximite
maximize
maxims
maximum
maximums
maxis
maxixe
maxixes
maxwell
maxwells
may
maya
mayan
mayapple
mayas
maybe
maybes
maybush
mayday
maydays
mayed
mayest
mayflies
mayfly
mayhap
mayhem
mayhems
maying
mayings
mayo
mayor
mayoral
mayoress
mayors
mayos
maypole
maypoles
maypop
maypops
mays
mayst
mayvin
mayvins
mayweed
mayweeds
mazaedia
mazard
mazards
maze
mazed
mazedly
mazelike
mazer
mazers
mazes
mazier
maziest
mazily
maziness
mazing
mazourka
mazuma
mazumas
mazurka
mazurkas
mazy
mazzard
mazzards
mbira
mbiras
me
mead
meadow
meadows
meadowy
meads
meager
meagerly
meagre
meagrely
meal
mealie
mealier
mealies
mealiest
mealless
meals
mealtime
mealworm
mealy
mealybug
mean
meander
meanders
meaner
meaners
meanest
meanie
meanies
meaning
meanings
meanly
meanness
means
meant
meantime
meany
measle
measled
measles
measlier
measly
measure
measured
measurer
measures
meat
meatal
meatball
meated
meathead
meatier
meatiest
meatily
meatless
meatloaf
meatman
meatmen
meats
meatus
meatuses
meaty
mecca
meccas
mechanic
meconium
med
medaka
medakas
medal
medaled
medaling
medalist
medalled
medallic
medals
meddle
meddled
meddler
meddlers
meddles
meddling
medevac
medevacs
medflies
medfly
media
mediacy
mediad
mediae
medial
medially
medials
median
medianly
medians
mediant
mediants
medias
mediate
mediated
mediates
mediator
medic
medicaid
medical
medicals
medicare
medicate
medicine
medick
medicks
medico
medicos
medics
medieval
medii
medina
medinas
mediocre
meditate
medium
mediums
medius
medlar
medlars
medley
medleys
medulla
medullae
medullar
medullas
medusa
medusae
medusal
medusan
medusans
medusas
medusoid
meed
meeds
meek
meeker
meekest
meekly
meekness
meerkat
meerkats
meet
meeter
meeters
meeting
meetings
meetly
meetness
meets
megabar
megabars
megabit
megabits
megabuck
megabyte
megacity
megadeal
megadose
megadyne
megahit
megahits
megalith
megalops
megapod
megapode
megapods
megass
megasse
megasses
megastar
megaton
megatons
megavolt
megawatt
megillah
megilp
megilph
megilphs
megilps
megohm
megohms
megrim
megrims
meikle
meinie
meinies
meiny
meioses
meiosis
meiotic
mel
melamdim
melamed
melamine
melange
melanges
melanian
melanic
melanics
melanin
melanins
melanism
melanist
melanite
melanize
melanoid
melanoma
melanous
meld
melded
melder
melders
melding
melds
melee
melees
melic
melilite
melilot
melilots
melinite
melisma
melismas
mell
melled
mellific
melling
mellow
mellowed
mellower
mellowly
mellows
mells
melodeon
melodia
melodias
melodic
melodica
melodies
melodise
melodist
melodize
melody
meloid
meloids
melon
melons
mels
melt
meltable
meltage
meltages
meltdown
melted
melter
melters
melting
melton
meltons
melts
mem
member
membered
members
membrane
memento
mementos
memo
memoir
memoirs
memorial
memories
memorise
memorize
memory
memos
mems
memsahib
men
menace
menaced
menacer
menacers
menaces
menacing
menad
menads
menage
menages
menarche
menazon
menazons
mend
mendable
mended
mender
menders
mendigo
mendigos
mending
mendings
mends
menfolk
menfolks
menhaden
menhir
menhirs
menial
menially
menials
meninges
meninx
meniscal
menisci
meniscus
meno
menology
menorah
menorahs
mensa
mensae
mensal
mensas
mensch
menschen
mensches
mense
mensed
menseful
menses
mensing
menstrua
mensural
menswear
menta
mental
mentally
menthene
menthol
menthols
mention
mentions
mentor
mentored
mentors
mentum
menu
menus
meou
meoued
meouing
meous
meow
meowed
meowing
meows
mephitic
mephitis
mercapto
mercer
mercers
mercery
merchant
mercies
merciful
mercuric
mercury
mercy
merde
merdes
mere
merely
merengue
merer
meres
merest
merge
merged
mergence
merger
mergers
merges
merging
meridian
meringue
merino
merinos
merises
merisis
meristem
meristic
merit
merited
meriting
merits
merk
merks
merl
merle
merles
merlin
merlins
merlon
merlons
merlot
merlots
merls
mermaid
mermaids
merman
mermen
meropia
meropias
meropic
merrier
merriest
merrily
merry
mesa
mesally
mesarch
mesas
mescal
mescals
mesdames
meseemed
meseems
mesh
meshed
meshes
meshier
meshiest
meshing
meshuga
meshugah
meshugga
meshugge
meshwork
meshy
mesial
mesially
mesian
mesic
mesmeric
mesnalty
mesne
mesnes
mesocarp
mesoderm
mesoglea
mesomere
meson
mesonic
mesons
mesophyl
mesosome
mesotron
mesquit
mesquite
mesquits
mess
message
messaged
messages
messan
messans
messed
messes
messiah
messiahs
messier
messiest
messily
messing
messman
messmate
messmen
messuage
messy
mestee
mestees
mesteso
mestesos
mestino
mestinos
mestiza
mestizas
mestizo
mestizos
met
meta
metage
metages
metal
metaled
metaling
metalise
metalist
metalize
metalled
metallic
metals
metamer
metamere
metamers
metaphor
metate
metates
metazoa
metazoal
metazoan
metazoic
metazoon
mete
meted
meteor
meteoric
meteors
metepa
metepas
meter
meterage
metered
metering
meters
metes
meth
methadon
methane
methanes
methanol
methinks
method
methodic
methods
methoxy
methoxyl
meths
methyl
methylal
methylic
methyls
meticais
metical
meticals
metier
metiers
meting
metis
metisse
metisses
metonym
metonyms
metonymy
metopae
metope
metopes
metopic
metopon
metopons
metre
metred
metres
metric
metrical
metrics
metrify
metring
metrist
metrists
metritis
metro
metros
mettle
mettled
mettles
metump
metumps
meuniere
mew
mewed
mewing
mewl
mewled
mewler
mewlers
mewling
mewls
mews
mezcal
mezcals
meze
mezereon
mezereum
mezes
mezquit
mezquite
mezquits
mezuza
mezuzah
mezuzahs
mezuzas
mezuzot
mezuzoth
mezzo
mezzos
mho
mhos
mi
miaou
miaoued
miaouing
miaous
miaow
miaowed
miaowing
miaows
miasm
miasma
miasmal
miasmas
miasmata
miasmic
miasms
miaul
miauled
miauling
miauls
mib
mibs
mica
micas
micawber
mice
micell
micella
micellae
micellar
micelle
micelles
micells
miche
miched
miches
miching
mick
mickey
mickeys
mickle
mickler
mickles
micklest
micks
micra
micrify
micro
microbar
microbe
microbes
microbic
microbus
microdot
microhm
microhms
microlux
micromho
micron
microns
micros
micrurgy
mid
midair
midairs
midbrain
midcult
midcults
midday
middays
midden
middens
middies
middle
middled
middler
middlers
middles
middling
middy
midfield
midge
midges
midget
midgets
midgut
midguts
midi
midiron
midirons
midis
midland
midlands
midleg
midlegs
midlife
midline
midlines
midlives
midmonth
midmost
midmosts
midnight
midnoon
midnoons
midpoint
midrange
midrash
midrib
midribs
midriff
midriffs
mids
midship
midships
midsize
midsized
midsole
midsoles
midspace
midst
midstory
midsts
midterm
midterms
midtown
midtowns
midwatch
midway
midways
midweek
midweeks
midwife
midwifed
midwifes
midwived
midwives
midyear
midyears
mien
miens
miff
miffed
miffier
miffiest
miffing
miffs
miffy
mig
migg
miggle
miggles
miggs
might
mightier
mightily
mights
mighty
mignon
mignonne
mignons
migraine
migrant
migrants
migrate
migrated
migrates
migrator
migs
mihrab
mihrabs
mijnheer
mikado
mikados
mike
miked
mikes
miking
mikra
mikron
mikrons
mikvah
mikvahs
mikveh
mikvehs
mikvoth
mil
miladi
miladies
miladis
milady
milage
milages
milch
milchig
mild
milden
mildened
mildens
milder
mildest
mildew
mildewed
mildews
mildewy
mildly
mildness
mile
mileage
mileages
milepost
miler
milers
miles
milesimo
milfoil
milfoils
milia
miliaria
miliary
milieu
milieus
milieux
militant
military
militate
militia
militias
milium
milk
milked
milker
milkers
milkfish
milkier
milkiest
milkily
milking
milkmaid
milkman
milkmen
milks
milkshed
milksop
milksops
milkweed
milkwood
milkwort
milky
mill
millable
millage
millages
millcake
milldam
milldams
mille
milled
milleped
miller
millers
milles
millet
millets
milliard
milliare
milliary
millibar
millieme
millier
milliers
milligal
millilux
millime
millimes
millimho
milline
milliner
millines
milling
millings
milliohm
million
millions
milliped
millirem
millpond
millrace
millrun
millruns
mills
millwork
milneb
milnebs
milo
milord
milords
milos
milpa
milpas
milreis
mils
milt
milted
milter
milters
miltier
miltiest
milting
milts
milty
mim
mimbar
mimbars
mime
mimed
mimeo
mimeoed
mimeoing
mimeos
mimer
mimers
mimes
mimesis
mimetic
mimetite
mimic
mimical
mimicked
mimicker
mimicry
mimics
miming
mimosa
mimosas
mina
minable
minacity
minae
minaret
minarets
minas
minatory
mince
minced
mincer
mincers
minces
mincier
minciest
mincing
mincy
mind
minded
minder
minders
mindful
minding
mindless
minds
mindset
mindsets
mine
mineable
mined
miner
mineral
minerals
miners
mines
mingier
mingiest
mingle
mingled
mingler
minglers
mingles
mingling
mingy
mini
minibike
minibus
minicab
minicabs
minicamp
minicar
minicars
minified
minifies
minify
minikin
minikins
minilab
minilabs
minim
minima
minimal
minimals
minimax
minimill
minimise
minimize
minims
minimum
minimums
mining
minings
minion
minions
minipark
minis
minish
minished
minishes
miniski
miniskis
minister
ministry
minium
miniums
minivan
minivans
miniver
minivers
mink
minke
minkes
minks
minnies
minnow
minnows
minny
minor
minorca
minorcas
minored
minoring
minority
minors
minster
minsters
minstrel
mint
mintage
mintages
minted
minter
minters
mintier
mintiest
minting
mints
minty
minuend
minuends
minuet
minuets
minus
minuses
minute
minuted
minutely
minuter
minutes
minutest
minutia
minutiae
minutial
minuting
minx
minxes
minxish
minyan
minyanim
minyans
mioses
miosis
miotic
miotics
miquelet
mir
miracle
miracles
mirador
miradors
mirage
mirages
mire
mired
mires
mirex
mirexes
miri
mirier
miriest
miriness
miring
mirk
mirker
mirkest
mirkier
mirkiest
mirkily
mirks
mirky
mirliton
mirror
mirrored
mirrors
mirs
mirth
mirthful
mirths
miry
mirza
mirzas
mis
misact
misacted
misacts
misadapt
misadd
misadded
misadds
misagent
misaim
misaimed
misaims
misalign
misally
misalter
misandry
misapply
misassay
misate
misatone
misaver
misavers
misaward
misbegan
misbegin
misbegot
misbegun
misbias
misbill
misbills
misbind
misbinds
misbound
misbrand
misbuild
misbuilt
miscall
miscalls
miscarry
miscast
miscasts
mischief
miscible
miscite
miscited
miscites
misclaim
misclass
miscode
miscoded
miscodes
miscoin
miscoins
miscolor
miscook
miscooks
miscopy
miscount
miscue
miscued
miscues
miscuing
miscut
miscuts
misdate
misdated
misdates
misdeal
misdeals
misdealt
misdeed
misdeeds
misdeem
misdeems
misdial
misdials
misdid
misdo
misdoer
misdoers
misdoes
misdoing
misdone
misdoubt
misdraw
misdrawn
misdraws
misdrew
misdrive
misdrove
mise
misease
miseases
miseat
miseaten
miseats
misedit
misedits
misenrol
misenter
misentry
miser
miserere
miseries
miserly
misers
misery
mises
misevent
misfaith
misfield
misfile
misfiled
misfiles
misfire
misfired
misfires
misfit
misfits
misfocus
misform
misforms
misframe
misgauge
misgave
misgive
misgiven
misgives
misgrade
misgraft
misgrew
misgrow
misgrown
misgrows
misguess
misguide
mishap
mishaps
mishear
misheard
mishears
mishit
mishits
mishmash
mishmosh
misinfer
misinter
misjoin
misjoins
misjudge
miskal
miskals
miskeep
miskeeps
miskept
miskick
miskicks
misknew
misknow
misknown
misknows
mislabel
mislabor
mislaid
mislain
mislay
mislayer
mislays
mislead
misleads
mislearn
misled
mislie
mislies
mislight
mislike
misliked
misliker
mislikes
mislit
mislive
mislived
mislives
mislodge
mislying
mismade
mismake
mismakes
mismark
mismarks
mismatch
mismate
mismated
mismates
mismeet
mismeets
mismet
mismove
mismoved
mismoves
misname
misnamed
misnames
misnomer
miso
misogamy
misogyny
misology
misorder
misos
mispage
mispaged
mispages
mispaint
misparse
mispart
misparts
mispatch
mispen
mispens
misplace
misplan
misplans
misplant
misplay
misplays
misplead
mispled
mispoint
mispoise
misprice
misprint
misprize
misquote
misraise
misrate
misrated
misrates
misread
misreads
misrefer
misrely
misroute
misrule
misruled
misrules
miss
missable
missaid
missal
missals
missay
missays
misseat
misseats
missed
missel
missels
missend
missends
missense
missent
misses
misset
missets
misshape
misshod
missies
missile
missiles
missilry
missing
mission
missions
missis
missises
missive
missives
missort
missorts
missound
missout
missouts
misspace
misspeak
misspell
misspelt
misspend
misspent
misspoke
misstart
misstate
missteer
misstep
missteps
misstop
misstops
misstyle
missuit
missuits
missus
missuses
missy
mist
mistake
mistaken
mistaker
mistakes
mistbow
mistbows
misteach
misted
mistend
mistends
mister
misterm
misterms
misters
misteuk
misthink
misthrew
misthrow
mistier
mistiest
mistily
mistime
mistimed
mistimes
misting
mistitle
mistook
mistouch
mistrace
mistrain
mistral
mistrals
mistreat
mistress
mistrial
mistrust
mistruth
mistryst
mists
mistune
mistuned
mistunes
mistutor
misty
mistype
mistyped
mistypes
misunion
misusage
misuse
misused
misuser
misusers
misuses
misusing
misvalue
misword
miswords
miswrit
miswrite
miswrote
misyoke
misyoked
misyokes
mite
miter
mitered
miterer
miterers
mitering
miters
mites
mither
mithers
miticide
mitier
mitiest
mitigate
mitis
mitises
mitogen
mitogens
mitoses
mitosis
mitotic
mitral
mitre
mitred
mitres
mitring
mitsvah
mitsvahs
mitsvoth
mitt
mitten
mittens
mittimus
mitts
mity
mitzvah
mitzvahs
mitzvoth
mix
mixable
mixed
mixer
mixers
mixes
mixible
mixing
mixology
mixt
mixture
mixtures
mixup
mixups
mizen
mizens
mizzen
mizzens
mizzle
mizzled
mizzles
mizzling
mizzly
mm
mnemonic
mo
moa
moan
moaned
moaner
moaners
moanful
moaning
moans
moas
moat
moated
moating
moatlike
moats
mob
mobbed
mobber
mobbers
mobbing
mobbish
mobcap
mobcaps
mobile
mobiles
mobilise
mobility
mobilize
mobled
mobocrat
mobs
mobster
mobsters
moc
moccasin
mocha
mochas
mochila
mochilas
mock
mockable
mocked
mocker
mockers
mockery
mocking
mocks
mockup
mockups
mocs
mod
modal
modality
modally
mode
model
modeled
modeler
modelers
modeling
modelist
modelled
modeller
models
modem
modems
moderate
moderato
modern
moderne
moderner
modernly
moderns
modes
modest
modester
modestly
modesty
modi
modica
modicum
modicums
modified
modifier
modifies
modify
modioli
modiolus
modish
modishly
modiste
modistes
mods
modular
modulate
module
modules
moduli
modulo
modulus
modus
mofette
mofettes
moffette
mog
mogged
moggie
moggies
mogging
moggy
mogs
mogul
moguls
mohair
mohairs
mohalim
mohel
mohelim
mohels
mohur
mohurs
moidore
moidores
moieties
moiety
moil
moiled
moiler
moilers
moiling
moils
moira
moirai
moire
moires
moist
moisten
moistens
moister
moistest
moistful
moistly
moisture
mojarra
mojarras
mojo
mojoes
mojos
moke
mokes
mol
mola
molal
molality
molar
molarity
molars
molas
molasses
mold
moldable
molded
molder
moldered
molders
moldier
moldiest
molding
moldings
molds
moldwarp
moldy
mole
molecule
molehill
moles
moleskin
molest
molested
molester
molests
molies
moline
moll
mollah
mollahs
mollie
mollies
mollify
molls
mollusc
molluscs
mollusk
mollusks
molly
moloch
molochs
mols
molt
molted
molten
moltenly
molter
molters
molting
molto
molts
moly
molybdic
mom
mome
moment
momenta
momently
momento
momentos
moments
momentum
momes
momi
momism
momisms
momma
mommas
mommies
mommy
moms
momser
momsers
momus
momuses
momzer
momzers
mon
monachal
monacid
monacids
monad
monadal
monades
monadic
monadism
monads
monandry
monarch
monarchs
monarchy
monarda
monardas
monas
monastic
monaural
monaxial
monaxon
monaxons
monazite
monde
mondes
mondo
mondos
monecian
monellin
moneran
monerans
monetary
monetise
monetize
money
moneybag
moneyed
moneyer
moneyers
moneyman
moneymen
moneys
mongeese
monger
mongered
mongers
mongo
mongoe
mongoes
mongol
mongols
mongoose
mongos
mongrel
mongrels
mongst
monicker
monie
monied
monies
moniker
monikers
monish
monished
monishes
monism
monisms
monist
monistic
monists
monition
monitive
monitor
monitors
monitory
monk
monkery
monkey
monkeyed
monkeys
monkfish
monkhood
monkish
monks
mono
monoacid
monocarp
monocle
monocled
monocles
monocot
monocots
monocrat
monocyte
monodic
monodies
monodist
monody
monoecy
monofil
monofils
monofuel
monogamy
monogeny
monogerm
monoglot
monogram
monogyny
monohull
monolith
monolog
monologs
monology
monomer
monomers
monomial
monopode
monopody
monopole
monopoly
monorail
monos
monosome
monosomy
monotint
monotone
monotony
monotype
monoxide
mons
monsieur
monsoon
monsoons
monster
monstera
monsters
montage
montaged
montages
montane
montanes
monte
monteith
montero
monteros
montes
month
monthly
months
monument
monuron
monurons
mony
moo
mooch
mooched
moocher
moochers
mooches
mooching
mood
moodier
moodiest
moodily
moods
moody
mooed
mooing
mool
moola
moolah
moolahs
moolas
mooley
mooleys
mools
moon
moonbeam
moonbow
moonbows
mooncalf
moondust
mooned
mooneye
mooneyes
moonfish
moonier
mooniest
moonily
mooning
moonish
moonless
moonlet
moonlets
moonlike
moonlit
moonport
moonrise
moons
moonsail
moonseed
moonset
moonsets
moonshot
moonwalk
moonward
moonwort
moony
moor
moorage
moorages
moorcock
moored
moorfowl
moorhen
moorhens
moorier
mooriest
mooring
moorings
moorish
moorland
moors
moorwort
moory
moos
moose
moot
mooted
mooter
mooters
mooting
moots
mop
mopboard
mope
moped
mopeds
moper
moperies
mopers
mopery
mopes
mopey
mopier
mopiest
moping
mopingly
mopish
mopishly
mopoke
mopokes
mopped
mopper
moppers
moppet
moppets
mopping
mops
mopy
moquette
mor
mora
morae
morainal
moraine
moraines
morainic
moral
morale
morales
moralise
moralism
moralist
morality
moralize
morally
morals
moras
morass
morasses
morassy
moratory
moray
morays
morbid
morbidly
morbific
morbilli
morceau
morceaux
mordancy
mordant
mordants
mordent
mordents
more
moreen
moreens
morel
morelle
morelles
morello
morellos
morels
moreover
mores
moresque
morgan
morgans
morgen
morgens
morgue
morgues
moribund
morion
morions
morn
morning
mornings
morns
morocco
moroccos
moron
moronic
moronism
moronity
morons
morose
morosely
morosity
morph
morpheme
morphia
morphias
morphic
morphin
morphine
morphins
morpho
morphos
morphs
morrion
morrions
morris
morrises
morro
morros
morrow
morrows
mors
morse
morsel
morseled
morsels
mort
mortal
mortally
mortals
mortar
mortared
mortars
mortary
mortgage
mortice
morticed
mortices
mortify
mortise
mortised
mortiser
mortises
mortmain
morts
mortuary
morula
morulae
morular
morulas
mos
mosaic
mosaics
mosasaur
moschate
mosey
moseyed
moseying
moseys
moshav
moshavim
mosk
mosks
mosque
mosques
mosquito
moss
mossback
mossed
mosser
mossers
mosses
mossier
mossiest
mossing
mosslike
mosso
mossy
most
moste
mostest
mostests
mostly
mosts
mot
mote
motel
motels
motes
motet
motets
motey
moth
mothball
mother
mothered
motherly
mothers
mothery
mothier
mothiest
mothlike
moths
mothy
motif
motific
motifs
motile
motiles
motility
motion
motional
motioned
motioner
motions
motivate
motive
motived
motives
motivic
motiving
motivity
motley
motleyer
motleys
motlier
motliest
motmot
motmots
motor
motorbus
motorcar
motordom
motored
motoric
motoring
motorise
motorist
motorize
motorman
motormen
motors
motorway
mots
mott
motte
mottes
mottle
mottled
mottler
mottlers
mottles
mottling
motto
mottoes
mottos
motts
mouch
mouched
mouches
mouching
mouchoir
moue
moues
moufflon
mouflon
mouflons
mouille
moujik
moujiks
moulage
moulages
mould
moulded
moulder
moulders
mouldier
moulding
moulds
mouldy
moulin
moulins
moult
moulted
moulter
moulters
moulting
moults
mound
mounded
mounding
mounds
mount
mountain
mounted
mounter
mounters
mounting
mounts
mourn
mourned
mourner
mourners
mournful
mourning
mourns
mouse
moused
mouser
mousers
mouses
mousey
mousier
mousiest
mousily
mousing
mousings
moussaka
mousse
moussed
mousses
moussing
mousy
mouth
mouthed
mouther
mouthers
mouthful
mouthier
mouthily
mouthing
mouths
mouthy
mouton
moutons
movable
movables
movably
move
moveable
moveably
moved
moveless
movement
mover
movers
moves
movie
moviedom
movieola
movies
moving
movingly
moviola
moviolas
mow
mowed
mower
mowers
mowing
mowings
mown
mows
moxa
moxas
moxie
moxies
mozetta
mozettas
mozette
mozo
mozos
mozzetta
mozzette
mridanga
mu
much
muchacho
muches
muchly
muchness
mucid
mucidity
mucilage
mucin
mucinoid
mucinous
mucins
muck
mucked
mucker
muckers
muckier
muckiest
muckily
mucking
muckle
muckles
muckluck
muckrake
mucks
muckworm
mucky
mucluc
muclucs
mucoid
mucoidal
mucoids
mucor
mucors
mucosa
mucosae
mucosal
mucosas
mucose
mucosity
mucous
mucro
mucrones
mucus
mucuses
mud
mudcap
mudcaps
mudcat
mudcats
mudded
mudder
mudders
muddied
muddier
muddies
muddiest
muddily
mudding
muddle
muddled
muddler
muddlers
muddles
muddling
muddly
muddy
muddying
mudfish
mudflat
mudflats
mudflow
mudflows
mudguard
mudhole
mudholes
mudlark
mudlarks
mudpack
mudpacks
mudpuppy
mudra
mudras
mudrock
mudrocks
mudroom
mudrooms
muds
mudsill
mudsills
mudslide
mudstone
mueddin
mueddins
muenster
muesli
mueslis
muezzin
muezzins
muff
muffed
muffin
muffing
muffins
muffle
muffled
muffler
mufflers
muffles
muffling
muffs
mufti
muftis
mug
mugful
mugfuls
mugg
muggar
muggars
mugged
muggee
muggees
mugger
muggers
muggier
muggiest
muggily
mugging
muggings
muggins
muggs
muggur
muggurs
muggy
mugs
mugwort
mugworts
mugwump
mugwumps
muhlies
muhly
mujik
mujiks
mukluk
mukluks
muktuk
muktuks
mulatto
mulattos
mulberry
mulch
mulched
mulches
mulching
mulct
mulcted
mulcting
mulcts
mule
muled
mules
muleta
muletas
muleteer
muley
muleys
muling
mulish
mulishly
mull
mulla
mullah
mullahs
mullas
mulled
mullein
mulleins
mullen
mullens
muller
mullers
mullet
mullets
mulley
mulleys
mulligan
mulling
mullion
mullions
mullite
mullites
mullock
mullocks
mullocky
mulls
multiage
multicar
multifid
multijet
multiped
multiple
multiply
multiton
multiuse
multure
multures
mum
mumble
mumbled
mumbler
mumblers
mumbles
mumbling
mumbly
mumm
mummed
mummer
mummers
mummery
mummied
mummies
mummify
mumming
mumms
mummy
mummying
mump
mumped
mumper
mumpers
mumping
mumps
mums
mumu
mumus
mun
munch
munched
muncher
munchers
munches
munchies
munching
munchkin
mundane
mundungo
mungo
mungoose
mungos
muni
muniment
munis
munition
munnion
munnions
muns
munster
munsters
muntin
munting
muntings
muntins
muntjac
muntjacs
muntjak
muntjaks
muon
muonic
muonium
muoniums
muons
mura
muraenid
mural
muralist
murals
muras
murder
murdered
murderee
murderer
murders
mure
mured
murein
mureins
mures
murex
murexes
muriate
muriated
muriates
muricate
murices
murid
murids
murine
murines
muring
murk
murker
murkest
murkier
murkiest
murkily
murkly
murks
murky
murmur
murmured
murmurer
murmurs
murphies
murphy
murr
murra
murrain
murrains
murras
murre
murrelet
murres
murrey
murreys
murrha
murrhas
murrhine
murries
murrine
murrs
murry
murther
murthers
mus
musca
muscadel
muscadet
muscae
muscat
muscatel
muscats
muscid
muscids
muscle
muscled
muscles
muscling
muscly
muscular
muse
mused
museful
muser
musers
muses
musette
musettes
museum
museums
mush
mushed
musher
mushers
mushes
mushier
mushiest
mushily
mushing
mushroom
mushy
music
musical
musicale
musicals
musician
musics
musing
musingly
musings
musjid
musjids
musk
muskeg
muskegs
musket
musketry
muskets
muskie
muskier
muskies
muskiest
muskily
muskit
muskits
muskrat
muskrats
musks
musky
muslin
muslins
muspike
muspikes
musquash
muss
mussed
mussel
mussels
musses
mussier
mussiest
mussily
mussing
mussy
must
mustache
mustang
mustangs
mustard
mustards
mustardy
musted
mustee
mustees
muster
mustered
musters
musth
musths
mustier
mustiest
mustily
musting
musts
musty
mut
mutable
mutably
mutagen
mutagens
mutant
mutants
mutase
mutases
mutate
mutated
mutates
mutating
mutation
mutative
mutch
mutches
mutchkin
mute
muted
mutedly
mutely
muteness
muter
mutes
mutest
muticous
mutilate
mutine
mutined
mutineer
mutines
muting
mutinied
mutinies
mutining
mutinous
mutiny
mutism
mutisms
muton
mutons
muts
mutt
mutter
muttered
mutterer
mutters
mutton
muttons
muttony
mutts
mutual
mutually
mutuel
mutuels
mutular
mutule
mutules
muumuu
muumuus
muzhik
muzhiks
muzjik
muzjiks
muzzier
muzziest
muzzily
muzzle
muzzled
muzzler
muzzlers
muzzles
muzzling
muzzy
my
myalgia
myalgias
myalgic
myases
myasis
mycele
myceles
mycelia
mycelial
mycelian
mycelium
myceloid
mycetoma
mycology
mycoses
mycosis
mycotic
myelin
myeline
myelines
myelinic
myelins
myelitis
myeloid
myeloma
myelomas
myiases
myiasis
mylonite
myna
mynah
mynahs
mynas
mynheer
mynheers
myoblast
myogenic
myograph
myoid
myologic
myology
myoma
myomas
myomata
myopathy
myope
myopes
myopia
myopias
myopic
myopies
myopy
myoscope
myoses
myosin
myosins
myosis
myositis
myosote
myosotes
myosotis
myotic
myotics
myotome
myotomes
myotonia
myotonic
myriad
myriads
myriapod
myrica
myricas
myriopod
myrmidon
myrrh
myrrhic
myrrhs
myrtle
myrtles
myself
mysid
mysids
mysost
mysosts
mystagog
mystery
mystic
mystical
mysticly
mystics
mystify
mystique
myth
mythic
mythical
mythier
mythiest
mythoi
mythos
myths
mythy
myxedema
myxocyte
myxoid
myxoma
myxomas
myxomata
na
naan
naans
nab
nabbed
nabber
nabbers
nabbing
nabe
nabes
nabis
nabob
nabobery
nabobess
nabobish
nabobism
nabobs
nabs
nacelle
nacelles
nachas
naches
nacho
nachos
nacre
nacred
nacreous
nacres
nada
nadas
nadir
nadiral
nadirs
nae
naething
naevi
naevoid
naevus
nag
nagana
naganas
nagged
nagger
naggers
naggier
naggiest
nagging
naggy
nags
nah
naiad
naiades
naiads
naif
naifs
nail
nailed
nailer
nailers
nailfold
nailhead
nailing
nails
nailset
nailsets
nainsook
naira
naive
naively
naiver
naives
naivest
naivete
naivetes
naivety
naked
nakeder
nakedest
nakedly
naled
naleds
naloxone
nam
namable
name
nameable
named
nameless
namely
namer
namers
names
namesake
nametag
nametags
naming
nan
nana
nanas
nance
nances
nancies
nancy
nandin
nandina
nandinas
nandins
nanism
nanisms
nankeen
nankeens
nankin
nankins
nannie
nannies
nanny
nanogram
nanowatt
nans
naoi
naos
nap
napalm
napalmed
napalms
nape
naperies
napery
napes
naphtha
naphthas
naphthol
naphthyl
naphtol
naphtols
napiform
napkin
napkins
napless
napoleon
nappe
napped
napper
nappers
nappes
nappie
nappier
nappies
nappiest
napping
nappy
naps
narc
narcein
narceine
narceins
narcism
narcisms
narcissi
narcist
narcists
narco
narcos
narcose
narcoses
narcosis
narcotic
narcs
nard
nardine
nards
nares
narghile
nargile
nargileh
nargiles
narial
naric
narine
naris
nark
narked
narking
narks
narky
narrate
narrated
narrater
narrates
narrator
narrow
narrowed
narrower
narrowly
narrows
narthex
narwal
narwals
narwhal
narwhale
narwhals
nary
nasal
nasalise
nasality
nasalize
nasally
nasals
nascence
nascency
nascent
nasial
nasion
nasions
nastic
nastier
nasties
nastiest
nastily
nasty
natal
natality
natant
natantly
natation
natatory
natch
nates
nathless
nation
national
nations
native
natively
natives
nativism
nativist
nativity
natrium
natriums
natron
natrons
natter
nattered
natters
nattier
nattiest
nattily
natty
natural
naturals
nature
natured
natures
naturism
naturist
naught
naughts
naughty
naumachy
nauplial
nauplii
nauplius
nausea
nauseant
nauseas
nauseate
nauseous
nautch
nautches
nautical
nautili
nautilus
navaid
navaids
naval
navally
navar
navars
nave
navel
navels
naves
navette
navettes
navicert
navies
navigate
navvies
navvy
navy
naw
nawab
nawabs
nay
nays
naysayer
nazi
nazified
nazifies
nazify
nazis
ne
neap
neaps
near
nearby
neared
nearer
nearest
nearing
nearlier
nearly
nearness
nears
nearside
neat
neaten
neatened
neatens
neater
neatest
neath
neatherd
neatly
neatness
neats
neb
nebbish
nebbishy
nebs
nebula
nebulae
nebular
nebulas
nebule
nebulise
nebulize
nebulose
nebulous
nebuly
neck
neckband
necked
necker
neckers
necking
neckings
necklace
neckless
necklike
neckline
necks
necktie
neckties
neckwear
necropsy
necrose
necrosed
necroses
necrosis
necrotic
nectar
nectars
nectary
nee
need
needed
needer
needers
needful
needfuls
needier
neediest
needily
needing
needle
needled
needler
needlers
needles
needless
needling
needs
needy
neem
neems
neep
neeps
negate
negated
negater
negaters
negates
negating
negation
negative
negaton
negatons
negator
negators
negatron
neglect
neglects
neglige
negligee
negliges
negroid
negroids
negroni
negronis
negus
neguses
neif
neifs
neigh
neighbor
neighed
neighing
neighs
neist
neither
nekton
nektonic
nektons
nellie
nellies
nelly
nelson
nelsons
nelumbo
nelumbos
nema
nemas
nematic
nematode
nemeses
nemesis
nene
neolith
neoliths
neologic
neology
neomorph
neomycin
neon
neonatal
neonate
neonates
neoned
neons
neophyte
neoplasm
neoprene
neotenic
neoteny
neoteric
neotype
neotypes
nepenthe
nephew
nephews
nephric
nephrism
nephrite
nephron
nephrons
nepotic
nepotism
nepotist
nerd
nerdier
nerdiest
nerdish
nerds
nerdy
nereid
nereides
nereids
nereis
neritic
nerol
neroli
nerolis
nerols
nerts
nertz
nervate
nerve
nerved
nerves
nervier
nerviest
nervily
nervine
nervines
nerving
nervings
nervous
nervule
nervules
nervure
nervures
nervy
nescient
ness
nesses
nest
nestable
nested
nester
nesters
nesting
nestle
nestled
nestler
nestlers
nestles
nestlike
nestling
nestor
nestors
nests
net
nether
netless
netlike
netop
netops
nets
netsuke
netsukes
nett
nettable
netted
netter
netters
nettier
nettiest
netting
nettings
nettle
nettled
nettler
nettlers
nettles
nettlier
nettling
nettly
netts
netty
network
networks
neuk
neuks
neum
neumatic
neume
neumes
neumic
neums
neural
neurally
neuraxon
neurine
neurines
neuritic
neuritis
neuroid
neuroma
neuromas
neuron
neuronal
neurone
neurones
neuronic
neurons
neurosal
neuroses
neurosis
neurotic
neurula
neurulae
neurulas
neuston
neustons
neuter
neutered
neuters
neutral
neutrals
neutrino
neutron
neutrons
neve
never
neves
nevi
nevoid
nevus
new
newborn
newborns
newcomer
newel
newels
newer
newest
newfound
newie
newies
newish
newly
newlywed
newmown
newness
news
newsboy
newsboys
newscast
newshawk
newsie
newsier
newsies
newsiest
newsless
newsman
newsmen
newspeak
newsreel
newsroom
newsy
newt
newton
newtons
newts
next
nextdoor
nexus
nexuses
ngultrum
ngwee
niacin
niacins
nib
nibbed
nibbing
nibble
nibbled
nibbler
nibblers
nibbles
nibbling
niblick
niblicks
niblike
nibs
nicad
nicads
nice
nicely
niceness
nicer
nicest
niceties
nicety
niche
niched
niches
niching
nick
nicked
nickel
nickeled
nickelic
nickels
nicker
nickered
nickers
nicking
nickle
nickled
nickles
nickling
nicknack
nickname
nicks
nicol
nicols
nicotin
nicotine
nicotins
nictate
nictated
nictates
nidal
nide
nided
nidering
nides
nidget
nidgets
nidi
nidified
nidifies
nidify
niding
nidus
niduses
niece
nieces
nielli
niellist
niello
nielloed
niellos
nieve
nieves
niffer
niffered
niffers
niftier
nifties
niftiest
niftily
nifty
niggard
niggards
nigger
niggers
niggle
niggled
niggler
nigglers
niggles
niggling
nigh
nighed
nigher
nighest
nighing
nighness
nighs
night
nightcap
nightie
nighties
nightjar
nightly
nights
nighty
nigrify
nigrosin
nihil
nihilism
nihilist
nihility
nihils
nil
nilgai
nilgais
nilgau
nilgaus
nilghai
nilghais
nilghau
nilghaus
nill
nilled
nilling
nills
nils
nim
nimbi
nimble
nimbler
nimblest
nimbly
nimbus
nimbused
nimbuses
nimiety
nimious
nimmed
nimming
nimrod
nimrods
nims
nine
ninebark
ninefold
ninepin
ninepins
nines
nineteen
nineties
ninety
ninja
ninjas
ninnies
ninny
ninnyish
ninon
ninons
ninth
ninthly
ninths
niobate
niobates
niobic
niobium
niobiums
niobous
nip
nipa
nipas
nipped
nipper
nippers
nippier
nippiest
nippily
nipping
nipple
nippled
nipples
nippy
nips
nirvana
nirvanas
nirvanic
nisei
niseis
nisi
nisus
nit
nitchie
nitchies
nite
niter
niterie
niteries
niters
nitery
nites
nitid
nitinol
nitinols
niton
nitons
nitpick
nitpicks
nitpicky
nitrate
nitrated
nitrates
nitrator
nitre
nitres
nitric
nitrid
nitride
nitrided
nitrides
nitrids
nitrify
nitril
nitrile
nitriles
nitrils
nitrite
nitrites
nitro
nitrogen
nitrolic
nitros
nitroso
nitrosyl
nitrous
nits
nittier
nittiest
nitty
nitwit
nitwits
nival
niveous
nix
nixe
nixed
nixes
nixie
nixies
nixing
nixy
nizam
nizamate
nizams
no
nob
nobbier
nobbiest
nobbily
nobble
nobbled
nobbler
nobblers
nobbles
nobbling
nobby
nobelium
nobility
noble
nobleman
noblemen
nobler
nobles
noblesse
noblest
nobly
nobodies
nobody
nobs
nocent
nock
nocked
nocking
nocks
noctuid
noctuids
noctule
noctules
noctuoid
nocturn
nocturne
nocturns
nocuous
nod
nodal
nodality
nodally
nodded
nodder
nodders
noddies
nodding
noddle
noddled
noddles
noddling
noddy
node
nodes
nodi
nodical
nodose
nodosity
nodous
nods
nodular
nodule
nodules
nodulose
nodulous
nodus
noel
noels
noes
noesis
noesises
noetic
nog
nogg
nogged
noggin
nogging
noggings
noggins
noggs
nogs
noh
nohow
noil
noils
noily
noir
noirish
noirs
noise
noised
noises
noisette
noisier
noisiest
noisily
noising
noisome
noisy
nolo
nolos
nom
noma
nomad
nomadic
nomadism
nomads
nomarch
nomarchs
nomarchy
nomas
nombles
nombril
nombrils
nome
nomen
nomes
nomina
nominal
nominals
nominate
nominee
nominees
nomism
nomisms
nomistic
nomogram
nomoi
nomology
nomos
noms
nona
nonacid
nonacids
nonactor
nonadult
nonage
nonages
nonagon
nonagons
nonart
nonarts
nonas
nonbank
nonbanks
nonbasic
nonbeing
nonblack
nonbody
nonbook
nonbooks
nonbrand
noncash
nonce
nonces
nonclass
noncling
noncola
noncolor
noncom
noncoms
noncrime
nondairy
nondance
nondrug
none
nonego
nonegos
nonelect
nonelite
nonempty
nonentry
nonequal
nones
nonesuch
nonet
nonets
nonevent
nonfact
nonfacts
nonfan
nonfans
nonfarm
nonfat
nonfatal
nonfatty
nonfinal
nonfluid
nonfocal
nonfood
nonfuel
nongame
nongay
nongays
nonglare
nongreen
nonguest
nonguilt
nonhardy
nonheme
nonhero
nonhome
nonhuman
nonideal
nonimage
nonionic
noniron
nonissue
nonjuror
nonjury
nonlabor
nonleafy
nonlegal
nonlife
nonlives
nonlocal
nonmajor
nonman
nonmeat
nonmen
nonmetal
nonmetro
nonmodal
nonmoney
nonmoral
nonmusic
nonnaval
nonnews
nonnovel
nonobese
nonohmic
nonoily
nonowner
nonpagan
nonpaid
nonpapal
nonpar
nonparty
nonpast
nonpasts
nonpeak
nonplay
nonplays
nonplus
nonpoint
nonpolar
nonpoor
nonprint
nonpros
nonquota
nonrated
nonrigid
nonrival
nonroyal
nonrural
nonself
nonsense
nonsked
nonskeds
nonskid
nonskier
nonslip
nonsolar
nonsolid
nonstick
nonstop
nonstory
nonstyle
nonsuch
nonsugar
nonsuit
nonsuits
nontax
nontaxes
nontidal
nontitle
nontonal
nontoxic
nontrump
nontruth
nonunion
nonuple
nonuples
nonurban
nonuse
nonuser
nonusers
nonuses
nonusing
nonvalid
nonviral
nonvocal
nonvoter
nonwar
nonwars
nonwhite
nonwoody
nonword
nonwords
nonwork
nonwoven
nonyl
nonyls
nonzero
noo
noodge
noodged
noodges
noodging
noodle
noodled
noodles
noodling
nook
nookies
nooklike
nooks
nooky
noon
noonday
noondays
nooning
noonings
noons
noontide
noontime
noose
noosed
nooser
noosers
nooses
noosing
nopal
nopals
nope
nor
nordic
nori
noria
norias
noris
norite
norites
noritic
norland
norlands
norm
normal
normalcy
normally
normals
normande
normed
normless
norms
north
norther
northern
northers
northing
norths
nos
nose
nosebag
nosebags
noseband
nosed
nosedive
nosegay
nosegays
noseless
noselike
noses
nosey
nosh
noshed
nosher
noshers
noshes
noshing
nosier
nosiest
nosily
nosiness
nosing
nosings
nosology
nostoc
nostocs
nostril
nostrils
nostrum
nostrums
nosy
not
nota
notable
notables
notably
notal
notarial
notaries
notarize
notary
notate
notated
notates
notating
notation
notch
notched
notcher
notchers
notches
notching
note
notebook
notecase
noted
notedly
noteless
notepad
notepads
noter
noters
notes
nother
nothing
nothings
notice
noticed
noticer
noticers
notices
noticing
notified
notifier
notifies
notify
noting
notion
notional
notions
notornis
notturni
notturno
notum
nougat
nougats
nought
noughts
noumena
noumenal
noumenon
noun
nounal
nounally
nounless
nouns
nourish
nous
nouses
nouveau
nouvelle
nova
novae
novalike
novas
novation
novel
novelise
novelist
novelize
novella
novellas
novelle
novelly
novels
novelty
novena
novenae
novenas
novercal
novice
novices
now
nowadays
noway
noways
nowhere
nowheres
nowise
nowness
nows
nowt
nowts
noxious
noyade
noyades
nozzle
nozzles
nth
nu
nuance
nuanced
nuances
nub
nubbier
nubbiest
nubbin
nubbins
nubble
nubbles
nubblier
nubbly
nubby
nubia
nubias
nubile
nubility
nubilose
nubilous
nubs
nucellar
nucelli
nucellus
nucha
nuchae
nuchal
nuchals
nucleal
nuclear
nuclease
nucleate
nuclei
nuclein
nucleins
nucleoid
nucleole
nucleoli
nucleon
nucleons
nucleus
nuclide
nuclides
nuclidic
nude
nudely
nudeness
nuder
nudes
nudest
nudge
nudged
nudger
nudgers
nudges
nudging
nudicaul
nudie
nudies
nudism
nudisms
nudist
nudists
nudities
nudity
nudnick
nudnicks
nudnik
nudniks
nudzh
nudzhed
nudzhes
nudzhing
nugatory
nugget
nuggets
nuggety
nuisance
nuke
nuked
nukes
nuking
null
nullah
nullahs
nulled
nullify
nulling
nullity
nulls
numb
numbat
numbats
numbed
number
numbered
numberer
numbers
numbest
numbfish
numbing
numbles
numbly
numbness
numbs
numen
numeracy
numeral
numerals
numerary
numerate
numeric
numerics
numerous
numina
numinous
nummary
nummular
numskull
nun
nunatak
nunataks
nunchaku
nuncio
nuncios
nuncle
nuncles
nunlike
nunnery
nunnish
nuns
nuptial
nuptials
nurd
nurds
nurl
nurled
nurling
nurls
nurse
nursed
nurser
nursers
nursery
nurses
nursing
nursings
nursling
nurtural
nurture
nurtured
nurturer
nurtures
nus
nut
nutant
nutate
nutated
nutates
nutating
nutation
nutbrown
nutcase
nutcases
nutgall
nutgalls
nutgrass
nuthatch
nuthouse
nutlet
nutlets
nutlike
nutmeat
nutmeats
nutmeg
nutmegs
nutpick
nutpicks
nutria
nutrias
nutrient
nuts
nutsedge
nutshell
nutsier
nutsiest
nutsy
nutted
nutter
nutters
nuttier
nuttiest
nuttily
nutting
nuttings
nutty
nutwood
nutwoods
nuzzle
nuzzled
nuzzler
nuzzlers
nuzzles
nuzzling
nyala
nyalas
nylghai
nylghais
nylghau
nylghaus
nylon
nylons
nymph
nympha
nymphae
nymphal
nymphean
nymphet
nymphets
nympho
nymphos
nymphs
nystatin
oaf
oafish
oafishly
oafs
oak
oaken
oaklike
oakmoss
oaks
oakum
oakums
oar
oared
oarfish
oaring
oarless
oarlike
oarlock
oarlocks
oars
oarsman
oarsmen
oases
oasis
oast
oasts
oat
oatcake
oatcakes
oaten
oater
oaters
oath
oaths
oatlike
oatmeal
oatmeals
oats
oaves
obconic
obduracy
obdurate
obe
obeah
obeahism
obeahs
obedient
obeisant
obeli
obelia
obelias
obelise
obelised
obelises
obelisk
obelisks
obelism
obelisms
obelize
obelized
obelizes
obelus
obes
obese
obesely
obesity
obey
obeyable
obeyed
obeyer
obeyers
obeying
obeys
obi
obia
obias
obiism
obiisms
obis
obit
obits
obituary
object
objected
objector
objects
objet
objets
oblast
oblasti
oblasts
oblate
oblately
oblates
oblation
oblatory
obligate
obligati
obligato
oblige
obliged
obligee
obligees
obliger
obligers
obliges
obliging
obligor
obligors
oblique
obliqued
obliques
oblivion
oblong
oblongly
oblongs
obloquy
oboe
oboes
oboist
oboists
obol
obole
oboles
oboli
obols
obolus
obovate
obovoid
obscene
obscener
obscure
obscured
obscurer
obscures
obsequy
observe
observed
observer
observes
obsess
obsessed
obsesses
obsessor
obsidian
obsolete
obstacle
obstruct
obtain
obtained
obtainer
obtains
obtect
obtected
obtest
obtested
obtests
obtrude
obtruded
obtruder
obtrudes
obtund
obtunded
obtunds
obturate
obtuse
obtusely
obtuser
obtusest
obtusity
obverse
obverses
obvert
obverted
obverts
obviable
obviate
obviated
obviates
obviator
obvious
obvolute
oca
ocarina
ocarinas
ocas
occasion
occident
occipita
occiput
occiputs
occlude
occluded
occludes
occlusal
occult
occulted
occulter
occultly
occults
occupant
occupied
occupier
occupies
occupy
occur
occurred
occurs
ocean
oceanaut
oceanic
oceans
ocellar
ocellate
ocelli
ocellus
oceloid
ocelot
ocelots
ocher
ochered
ochering
ocherous
ochers
ochery
ochone
ochre
ochrea
ochreae
ochred
ochreous
ochres
ochring
ochroid
ochrous
ochry
ocker
ockers
ocotillo
ocrea
ocreae
ocreate
octad
octadic
octads
octagon
octagons
octal
octan
octane
octanes
octangle
octanol
octanols
octans
octant
octantal
octants
octarchy
octaval
octave
octaves
octavo
octavos
octet
octets
octette
octettes
octonary
octopi
octopod
octopods
octopus
octoroon
octroi
octrois
octuple
octupled
octuples
octuplet
octuplex
octuply
octyl
octyls
ocular
ocularly
oculars
oculi
oculist
oculists
oculus
od
odalisk
odalisks
odd
oddball
oddballs
odder
oddest
oddish
oddities
oddity
oddly
oddment
oddments
oddness
odds
ode
odea
odeon
odeons
odes
odeum
odeums
odic
odious
odiously
odist
odists
odium
odiums
odograph
odometer
odometry
odonate
odonates
odontoid
odor
odorant
odorants
odored
odorful
odorize
odorized
odorizes
odorless
odorous
odors
odour
odourful
odours
ods
odyl
odyle
odyles
odyls
odyssey
odysseys
oe
oecology
oedema
oedemas
oedemata
oedipal
oedipean
oeillade
oenology
oenomel
oenomels
oersted
oersteds
oes
oestrin
oestrins
oestriol
oestrone
oestrous
oestrum
oestrums
oestrus
oeuvre
oeuvres
of
ofay
ofays
off
offal
offals
offbeat
offbeats
offcast
offcasts
offcut
offcuts
offed
offence
offences
offend
offended
offender
offends
offense
offenses
offer
offered
offerer
offerers
offering
offeror
offerors
offers
offhand
office
officer
officers
offices
official
offing
offings
offish
offishly
offkey
offload
offloads
offprint
offramp
offramps
offs
offset
offsets
offshoot
offshore
offside
offsides
offstage
offtrack
oft
often
oftener
oftenest
ofter
oftest
ofttimes
ogam
ogams
ogdoad
ogdoads
ogee
ogees
ogham
oghamic
oghamist
oghams
ogival
ogive
ogives
ogle
ogled
ogler
oglers
ogles
ogling
ogre
ogreish
ogreism
ogreisms
ogres
ogress
ogresses
ogrish
ogrishly
ogrism
ogrisms
oh
ohed
ohia
ohias
ohing
ohm
ohmage
ohmages
ohmic
ohmmeter
ohms
oho
ohs
oidia
oidium
oil
oilbird
oilbirds
oilcamp
oilcamps
oilcan
oilcans
oilcloth
oilcup
oilcups
oiled
oiler
oilers
oilhole
oilholes
oilier
oiliest
oilily
oiliness
oiling
oilman
oilmen
oilpaper
oilproof
oils
oilseed
oilseeds
oilskin
oilskins
oilstone
oiltight
oilway
oilways
oily
oink
oinked
oinking
oinks
oinology
oinomel
oinomels
ointment
oiticica
oka
okapi
okapis
okas
okay
okayed
okaying
okays
oke
okeh
okehs
okes
okeydoke
okra
okras
old
olden
older
oldest
oldie
oldies
oldish
oldness
olds
oldsquaw
oldster
oldsters
oldstyle
oldwife
oldwives
oldy
ole
olea
oleander
oleaster
oleate
oleates
olefin
olefine
olefines
olefinic
olefins
oleic
olein
oleine
oleines
oleins
oleo
oleos
oles
oleum
oleums
olibanum
oligarch
oligomer
oliguria
olio
olios
olivary
olive
olives
olivine
olivines
olivinic
olla
ollas
ologies
ologist
ologists
ology
oloroso
olorosos
olympiad
om
omasa
omasum
omber
ombers
ombre
ombres
omega
omegas
omelet
omelets
omelette
omen
omened
omening
omens
omenta
omental
omentum
omentums
omer
omers
omicron
omicrons
omikron
omikrons
ominous
omission
omissive
omit
omits
omitted
omitter
omitters
omitting
omniarch
omnibus
omnific
omniform
omnimode
omnivora
omnivore
omophagy
omphali
omphalos
oms
on
onager
onagers
onagri
onanism
onanisms
onanist
onanists
onboard
once
oncidium
oncogene
oncology
oncoming
ondogram
one
onefold
oneiric
oneness
onerier
oneriest
onerous
onery
ones
oneself
onetime
ongoing
onion
onions
oniony
onium
onlooker
only
onrush
onrushes
ons
onset
onsets
onshore
onside
onstage
onstream
ontic
onto
ontogeny
ontology
onus
onuses
onward
onwards
onyx
onyxes
oocyst
oocysts
oocyte
oocytes
oodles
oodlins
oogamete
oogamies
oogamous
oogamy
oogenies
oogeny
oogonia
oogonial
oogonium
ooh
oohed
oohing
oohs
oolachan
oolite
oolites
oolith
ooliths
oolitic
oologic
oologies
oologist
oology
oolong
oolongs
oomiac
oomiack
oomiacks
oomiacs
oomiak
oomiaks
oompah
oompahed
oompahs
oomph
oomphs
oophyte
oophytes
oophytic
oops
oorali
ooralis
oorie
oosperm
oosperms
oosphere
oospore
oospores
oosporic
oot
ootheca
oothecae
oothecal
ootid
ootids
oots
ooze
oozed
oozes
oozier
ooziest
oozily
ooziness
oozing
oozy
op
opacify
opacity
opah
opahs
opal
opalesce
opaline
opalines
opals
opaque
opaqued
opaquely
opaquer
opaques
opaquest
opaquing
ope
oped
open
openable
opencast
opened
opener
openers
openest
opening
openings
openly
openness
opens
openwork
opera
operable
operably
operand
operands
operant
operants
operas
operate
operated
operates
operatic
operator
opercele
opercula
opercule
operetta
operon
operons
operose
opes
ophidian
ophite
ophites
ophitic
opiate
opiated
opiates
opiating
opine
opined
opines
oping
opining
opinion
opinions
opioid
opioids
opium
opiumism
opiums
opossum
opossums
oppidan
oppidans
oppilant
oppilate
opponent
oppose
opposed
opposer
opposers
opposes
opposing
opposite
oppress
oppugn
oppugned
oppugner
oppugns
ops
opsin
opsins
opsonic
opsonify
opsonin
opsonins
opsonize
opt
optative
opted
optic
optical
optician
opticist
optics
optima
optimal
optime
optimes
optimise
optimism
optimist
optimize
optimum
optimums
opting
option
optional
optioned
optionee
options
opts
opulence
opulency
opulent
opuntia
opuntias
opus
opuscula
opuscule
opuses
oquassa
oquassas
or
ora
orach
orache
oraches
oracle
oracles
oracular
orad
oral
oralism
oralisms
oralist
oralists
orality
orally
orals
orang
orange
orangery
oranges
orangey
orangier
orangish
orangs
orangy
orate
orated
orates
orating
oration
orations
orator
oratorio
orators
oratory
oratress
oratrix
orb
orbed
orbier
orbiest
orbing
orbit
orbital
orbitals
orbited
orbiter
orbiters
orbiting
orbits
orbs
orby
orc
orca
orcas
orcein
orceins
orchard
orchards
orchid
orchids
orchil
orchils
orchis
orchises
orchitic
orchitis
orcin
orcinol
orcinols
orcins
orcs
ordain
ordained
ordainer
ordains
ordeal
ordeals
order
ordered
orderer
orderers
ordering
orderly
orders
ordinal
ordinals
ordinand
ordinary
ordinate
ordines
ordnance
ordo
ordos
ordure
ordures
ore
oread
oreads
orectic
orective
oregano
oreganos
oreide
oreides
ores
orfray
orfrays
organ
organa
organdie
organdy
organic
organics
organise
organism
organist
organize
organon
organons
organs
organum
organums
organza
organzas
orgasm
orgasmic
orgasms
orgastic
orgeat
orgeats
orgiac
orgic
orgies
orgone
orgones
orgulous
orgy
oribatid
oribi
oribis
oriel
oriels
orient
oriental
oriented
orients
orifice
orifices
origami
origamis
origan
origans
origanum
origin
original
origins
orinasal
oriole
orioles
orison
orisons
orle
orles
orlop
orlops
ormer
ormers
ormolu
ormolus
ornament
ornate
ornately
ornerier
ornery
ornis
ornithes
ornithic
orogenic
orogeny
oroide
oroides
orology
orometer
orotund
orphan
orphaned
orphans
orphic
orphical
orphrey
orphreys
orpiment
orpin
orpine
orpines
orpins
orra
orreries
orrery
orrice
orrices
orris
orrises
ors
ort
orthicon
ortho
orthodox
orthoepy
orthoses
orthosis
orthotic
ortolan
ortolans
orts
oryx
oryxes
orzo
orzos
os
osar
oscine
oscines
oscinine
oscitant
oscula
osculant
oscular
osculate
oscule
oscules
osculum
ose
oses
osier
osiers
osmatic
osmic
osmics
osmious
osmium
osmiums
osmol
osmolal
osmolar
osmole
osmoles
osmols
osmose
osmosed
osmoses
osmosing
osmosis
osmotic
osmous
osmund
osmunda
osmundas
osmunds
osnaburg
osprey
ospreys
ossa
ossein
osseins
osseous
ossia
ossicle
ossicles
ossific
ossified
ossifier
ossifies
ossify
ossuary
osteal
osteitic
osteitis
osteoid
osteoids
osteoma
osteomas
osteoses
osteosis
ostia
ostiary
ostinato
ostiolar
ostiole
ostioles
ostium
ostler
ostlers
ostmark
ostmarks
ostomies
ostomy
ostoses
ostosis
ostraca
ostracod
ostracon
ostrich
otalgia
otalgias
otalgic
otalgies
otalgy
other
others
otic
otiose
otiosely
otiosity
otitic
otitides
otitis
otocyst
otocysts
otolith
otoliths
otology
otoscope
otoscopy
ototoxic
ottar
ottars
ottava
ottavas
otter
otters
otto
ottoman
ottomans
ottos
ouabain
ouabains
ouch
ouched
ouches
ouching
oud
ouds
ought
oughted
oughting
oughts
ouguiya
ouistiti
ounce
ounces
ouph
ouphe
ouphes
ouphs
our
ourang
ourangs
ourari
ouraris
ourebi
ourebis
ourie
ours
ourself
ousel
ousels
oust
ousted
ouster
ousters
ousting
ousts
out
outact
outacted
outacts
outadd
outadded
outadds
outage
outages
outargue
outask
outasked
outasks
outate
outback
outbacks
outbake
outbaked
outbakes
outbark
outbarks
outbawl
outbawls
outbeam
outbeams
outbeg
outbegs
outbid
outbids
outbitch
outblaze
outbleat
outbless
outbloom
outbluff
outblush
outboard
outboast
outbound
outbox
outboxed
outboxes
outbrag
outbrags
outbrave
outbrawl
outbreak
outbred
outbreed
outbribe
outbuild
outbuilt
outbulk
outbulks
outbully
outburn
outburns
outburnt
outburst
outbuy
outbuys
outby
outbye
outcaper
outcast
outcaste
outcasts
outcatch
outcavil
outcharm
outcheat
outchid
outchide
outclass
outclimb
outclomb
outcoach
outcome
outcomes
outcook
outcooks
outcount
outcrawl
outcried
outcries
outcrop
outcrops
outcross
outcrow
outcrows
outcry
outcurse
outcurve
outdance
outdare
outdared
outdares
outdate
outdated
outdates
outdid
outdo
outdodge
outdoer
outdoers
outdoes
outdoing
outdone
outdoor
outdoors
outdrag
outdrags
outdrank
outdraw
outdrawn
outdraws
outdream
outdress
outdrew
outdrink
outdrive
outdrop
outdrops
outdrove
outdrunk
outduel
outduels
outearn
outearns
outeat
outeaten
outeats
outecho
outed
outer
outers
outfable
outface
outfaced
outfaces
outfall
outfalls
outfast
outfasts
outfawn
outfawns
outfeast
outfeel
outfeels
outfelt
outfield
outfight
outfind
outfinds
outfire
outfired
outfires
outfish
outfit
outfits
outflank
outflew
outflies
outflow
outflown
outflows
outfly
outfool
outfools
outfoot
outfoots
outfound
outfox
outfoxed
outfoxes
outfrown
outgain
outgains
outgas
outgave
outgive
outgiven
outgives
outglare
outglow
outglows
outgnaw
outgnawn
outgnaws
outgo
outgoes
outgoing
outgone
outgrew
outgrin
outgrins
outgross
outgroup
outgrow
outgrown
outgrows
outguess
outguide
outgun
outguns
outgush
outhaul
outhauls
outhear
outheard
outhears
outhit
outhits
outhomer
outhouse
outhowl
outhowls
outhumor
outhunt
outhunts
outing
outings
outjinx
outjump
outjumps
outjut
outjuts
outkeep
outkeeps
outkept
outkick
outkicks
outkill
outkills
outkiss
outlaid
outlain
outland
outlands
outlast
outlasts
outlaugh
outlaw
outlawed
outlawry
outlaws
outlay
outlays
outleap
outleaps
outleapt
outlearn
outlet
outlets
outlie
outlier
outliers
outlies
outline
outlined
outliner
outlines
outlive
outlived
outliver
outlives
outlook
outlooks
outlove
outloved
outloves
outlying
outman
outmans
outmarch
outmatch
outmode
outmoded
outmodes
outmost
outmove
outmoved
outmoves
outpace
outpaced
outpaces
outpaint
outpass
outpitch
outpity
outplan
outplans
outplay
outplays
outplod
outplods
outplot
outplots
outpoint
outpoll
outpolls
outport
outports
outpost
outposts
outpour
outpours
outpower
outpray
outprays
outpreen
outpress
outprice
outpull
outpulls
outpunch
outpush
output
outputs
outquote
outrace
outraced
outraces
outrage
outraged
outrages
outraise
outran
outrance
outrang
outrange
outrank
outranks
outrate
outrated
outrates
outrave
outraved
outraves
outre
outreach
outread
outreads
outride
outrider
outrides
outright
outring
outrings
outrival
outroar
outroars
outrock
outrocks
outrode
outroll
outrolls
outroot
outroots
outrow
outrowed
outrows
outrun
outrung
outruns
outrush
outs
outsail
outsails
outsang
outsat
outsavor
outsaw
outscold
outscoop
outscore
outscorn
outsee
outseen
outsees
outsell
outsells
outsert
outserts
outserve
outset
outsets
outshame
outshine
outshone
outshoot
outshot
outshout
outside
outsider
outsides
outsight
outsin
outsing
outsings
outsins
outsit
outsits
outsize
outsized
outsizes
outskate
outskirt
outsleep
outslept
outslick
outsmart
outsmile
outsmoke
outsnore
outsoar
outsoars
outsold
outsole
outsoles
outspan
outspans
outspeak
outsped
outspeed
outspell
outspelt
outspend
outspent
outspoke
outstand
outstare
outstart
outstate
outstay
outstays
outsteer
outstood
outstrip
outstudy
outstunt
outsulk
outsulks
outsung
outswam
outsware
outswear
outswim
outswims
outswore
outsworn
outswum
outtake
outtakes
outtalk
outtalks
outtask
outtasks
outtell
outtells
outthank
outthink
outthrew
outthrob
outthrow
outtold
outtower
outtrade
outtrick
outtrot
outtrots
outtrump
outturn
outturns
outvalue
outvaunt
outvie
outvied
outvies
outvoice
outvote
outvoted
outvotes
outvying
outwait
outwaits
outwalk
outwalks
outwar
outward
outwards
outwars
outwash
outwaste
outwatch
outwear
outwears
outweary
outweep
outweeps
outweigh
outwent
outwept
outwhirl
outwile
outwiled
outwiles
outwill
outwills
outwind
outwinds
outwish
outwit
outwits
outwore
outwork
outworks
outworn
outwrit
outwrite
outwrote
outyell
outyells
outyelp
outyelps
outyield
ouzel
ouzels
ouzo
ouzos
ova
oval
ovality
ovally
ovalness
ovals
ovarial
ovarian
ovaries
ovariole
ovaritis
ovary
ovate
ovately
ovation
ovations
oven
ovenbird
ovenlike
ovens
ovenware
over
overable
overact
overacts
overage
overaged
overages
overall
overalls
overapt
overarch
overarm
overate
overawe
overawed
overawes
overbake
overbear
overbeat
overbed
overbet
overbets
overbid
overbids
overbig
overbill
overbite
overblew
overblow
overboil
overbold
overbook
overbore
overborn
overbred
overburn
overbusy
overbuy
overbuys
overcall
overcame
overcast
overcoat
overcold
overcome
overcook
overcool
overcoy
overcram
overcrop
overcure
overcut
overcuts
overdare
overdear
overdeck
overdid
overdo
overdoer
overdoes
overdog
overdogs
overdone
overdose
overdraw
overdrew
overdry
overdub
overdubs
overdue
overdye
overdyed
overdyes
overeasy
overeat
overeats
overed
overedit
overfar
overfast
overfat
overfear
overfed
overfeed
overfill
overfish
overflew
overflow
overfly
overfond
overfoul
overfree
overfull
overfund
overgild
overgilt
overgird
overgirt
overglad
overgoad
overgrew
overgrow
overhand
overhang
overhard
overhate
overhaul
overhead
overheap
overhear
overheat
overheld
overhigh
overhold
overholy
overhope
overhot
overhung
overhunt
overhype
overidle
overing
overjoy
overjoys
overjust
overkeen
overkill
overkind
overlade
overlaid
overlain
overland
overlap
overlaps
overlate
overlax
overlay
overlays
overleaf
overleap
overlend
overlent
overlet
overlets
overlewd
overlie
overlies
overlit
overlive
overload
overlong
overlook
overlord
overloud
overlove
overlush
overly
overman
overmans
overmany
overmeek
overmelt
overmen
overmild
overmilk
overmine
overmix
overmuch
overnear
overneat
overnew
overnice
overpaid
overpass
overpast
overpay
overpays
overpert
overplan
overplay
overplot
overplus
overply
overpump
overran
overrank
overrash
overrate
overrich
override
overrife
overripe
overrode
overrude
overruff
overrule
overrun
overruns
overs
oversad
oversale
oversalt
oversave
oversaw
oversea
overseas
oversee
overseed
overseen
overseer
oversees
oversell
overset
oversets
oversew
oversewn
oversews
overshoe
overshot
oversick
overside
oversize
overslip
overslow
oversoak
oversoft
oversold
oversoon
oversoul
overspin
overstay
overstep
overstir
oversuds
oversup
oversups
oversure
overt
overtake
overtalk
overtame
overtart
overtask
overtax
overthin
overtime
overtip
overtips
overtire
overtly
overtoil
overtone
overtook
overtop
overtops
overtrim
overture
overturn
overurge
overuse
overused
overuses
overview
overvote
overwarm
overwary
overweak
overwear
overween
overwet
overwets
overwide
overwily
overwind
overwise
overword
overwore
overwork
overworn
overzeal
ovibos
ovicidal
ovicide
ovicides
oviducal
oviduct
oviducts
oviform
ovine
ovines
ovipara
oviposit
ovisac
ovisacs
ovoid
ovoidal
ovoids
ovoli
ovolo
ovolos
ovonic
ovonics
ovular
ovulary
ovulate
ovulated
ovulates
ovule
ovules
ovum
ow
owe
owed
owes
owing
owl
owlet
owlets
owlish
owlishly
owllike
owls
own
ownable
owned
owner
owners
owning
owns
owse
owsen
ox
oxalate
oxalated
oxalates
oxalic
oxalis
oxalises
oxazepam
oxazine
oxazines
oxblood
oxbloods
oxbow
oxbows
oxcart
oxcarts
oxen
oxes
oxeye
oxeyes
oxford
oxfords
oxheart
oxhearts
oxid
oxidable
oxidant
oxidants
oxidase
oxidases
oxidasic
oxidate
oxidated
oxidates
oxide
oxides
oxidic
oxidise
oxidised
oxidiser
oxidises
oxidize
oxidized
oxidizer
oxidizes
oxids
oxim
oxime
oximes
oxims
oxlip
oxlips
oxo
oxpecker
oxtail
oxtails
oxter
oxters
oxtongue
oxy
oxyacid
oxyacids
oxygen
oxygenic
oxygens
oxymora
oxymoron
oxyphil
oxyphile
oxyphils
oxysalt
oxysalts
oxysome
oxysomes
oxytocic
oxytocin
oxytone
oxytones
oy
oyer
oyers
oyes
oyesses
oyez
oyster
oystered
oysterer
oysters
ozonate
ozonated
ozonates
ozone
ozones
ozonic
ozonide
ozonides
ozonise
ozonised
ozonises
ozonize
ozonized
ozonizer
ozonizes
ozonous
pa
pablum
pablums
pabular
pabulum
pabulums
pac
paca
pacas
pace
paced
pacer
pacers
paces
pacha
pachadom
pachalic
pachas
pachinko
pachisi
pachisis
pachouli
pachuco
pachucos
pacific
pacified
pacifier
pacifies
pacifism
pacifist
pacify
pacing
pack
packable
package
packaged
packager
packages
packed
packer
packers
packet
packeted
packets
packing
packings
packly
packman
packmen
packness
packs
packsack
packwax
pacs
pact
paction
pactions
pacts
pad
padauk
padauks
padded
padder
padders
paddies
padding
paddings
paddle
paddled
paddler
paddlers
paddles
paddling
paddock
paddocks
paddy
padi
padis
padishah
padle
padles
padlock
padlocks
padnag
padnags
padouk
padouks
padre
padres
padri
padrone
padrones
padroni
pads
padshah
padshahs
paduasoy
paean
paeanism
paeans
paella
paellas
paeon
paeons
paesan
paesani
paesano
paesanos
paesans
pagan
pagandom
paganise
paganish
paganism
paganist
paganize
pagans
page
pageant
pageants
pageboy
pageboys
paged
pager
pagers
pages
paginal
paginate
paging
pagings
pagod
pagoda
pagodas
pagods
pagurian
pagurid
pagurids
pah
pahlavi
pahlavis
pahoehoe
paid
paik
paiked
paiking
paiks
pail
pailful
pailfuls
paillard
pails
pailsful
pain
painch
painches
pained
painful
paining
painless
pains
paint
painted
painter
painters
paintier
painting
paints
painty
pair
paired
pairing
pairings
pairs
paisa
paisan
paisana
paisanas
paisano
paisanos
paisans
paisas
paise
paisley
paisleys
pajama
pajamaed
pajamas
pakeha
pakehas
pal
palabra
palabras
palace
palaced
palaces
paladin
paladins
palais
palatal
palatals
palate
palates
palatial
palatine
palaver
palavers
palazzi
palazzo
palazzos
pale
palea
paleae
paleal
paled
paleface
palely
paleness
paleosol
paler
pales
palest
palestra
palet
paletot
paletots
palets
palette
palettes
paleways
palewise
palfrey
palfreys
palier
paliest
palikar
palikars
palimony
paling
palings
palinode
palisade
palish
pall
palladia
palladic
palled
pallet
pallets
pallette
pallia
pallial
palliate
pallid
pallidly
pallier
palliest
palling
pallium
palliums
pallor
pallors
palls
pally
palm
palmar
palmary
palmate
palmated
palmed
palmer
palmers
palmette
palmetto
palmier
palmiest
palming
palmist
palmists
palmitin
palmlike
palms
palmy
palmyra
palmyras
palomino
palooka
palookas
palp
palpable
palpably
palpal
palpate
palpated
palpates
palpator
palpebra
palpi
palps
palpus
pals
palship
palships
palsied
palsies
palsy
palsying
palter
paltered
palterer
palters
paltrier
paltrily
paltry
paludal
paludism
paly
pam
pampa
pampas
pampean
pampeans
pamper
pampered
pamperer
pampero
pamperos
pampers
pamphlet
pams
pan
panacea
panacean
panaceas
panache
panaches
panada
panadas
panama
panamas
panatela
panbroil
pancake
pancaked
pancakes
pancetta
panchax
pancreas
panda
pandani
pandanus
pandas
pandect
pandects
pandemic
pander
pandered
panderer
panders
pandied
pandies
pandit
pandits
pandoor
pandoors
pandora
pandoras
pandore
pandores
pandour
pandours
pandowdy
pandura
panduras
pandy
pandying
pane
paned
panel
paneled
paneling
panelist
panelled
panels
panes
panetela
panfish
panfried
panfries
panfry
panful
panfuls
pang
panga
pangas
panged
pangen
pangene
pangenes
pangens
panging
pangolin
pangs
panhuman
panic
panicked
panicky
panicle
panicled
panicles
panics
panicum
panicums
panier
paniers
panmixes
panmixia
panmixis
panne
panned
pannes
pannier
panniers
pannikin
panning
panocha
panochas
panoche
panoches
panoply
panoptic
panorama
panpipe
panpipes
pans
pansies
pansophy
pansy
pant
panted
pantheon
panther
panthers
pantie
panties
pantile
pantiled
pantiles
panting
panto
pantofle
pantos
pantoum
pantoums
pantries
pantry
pants
pantsuit
panty
panzer
panzers
pap
papa
papacies
papacy
papain
papains
papal
papally
papas
papaw
papaws
papaya
papayan
papayas
paper
paperboy
papered
paperer
paperers
papering
papers
papery
paphian
paphians
papilla
papillae
papillar
papillon
papist
papistic
papistry
papists
papoose
papooses
pappi
pappier
pappies
pappiest
pappoose
pappose
pappous
pappus
pappy
paprica
papricas
paprika
paprikas
paps
papula
papulae
papular
papule
papules
papulose
papyral
papyri
papyrian
papyrine
papyrus
par
para
parable
parables
parabola
parachor
parade
paraded
parader
paraders
parades
paradigm
parading
paradise
parador
paradors
parados
paradox
paradrop
paraffin
paraform
paragoge
paragon
paragons
parakeet
parakite
parallax
parallel
paralyse
paralyze
parament
paramo
paramos
paramour
parang
parangs
paranoea
paranoia
paranoic
paranoid
parapet
parapets
paraph
paraphs
paraquat
paraquet
paras
parasang
parashah
parasite
parasol
parasols
paravane
parawing
parazoan
parboil
parboils
parcel
parceled
parcels
parcener
parch
parched
parches
parchesi
parching
parchisi
pard
pardah
pardahs
pardee
pardi
pardie
pardine
pardner
pardners
pardon
pardoned
pardoner
pardons
pards
pardy
pare
parecism
pared
pareira
pareiras
parent
parental
parented
parents
pareo
pareos
parer
parerga
parergon
parers
pares
pareses
paresis
paretic
paretics
pareu
pareus
pareve
parfait
parfaits
parflesh
parfocal
parge
parged
parges
parget
pargeted
pargets
parging
pargings
pargo
pargos
parhelia
parhelic
pariah
pariahs
parian
parians
paries
parietal
parietes
paring
parings
paris
parises
parish
parishes
parities
parity
park
parka
parkas
parked
parker
parkers
parking
parkings
parkland
parklike
parks
parkway
parkways
parlance
parlando
parlante
parlay
parlayed
parlays
parle
parled
parles
parley
parleyed
parleyer
parleys
parling
parlor
parlors
parlour
parlours
parlous
parodic
parodied
parodies
parodist
parodoi
parodos
parody
parol
parole
paroled
parolee
parolees
paroles
paroling
parols
paronym
paronyms
paroquet
parotic
parotid
parotids
parotoid
parous
paroxysm
parquet
parquets
parr
parral
parrals
parred
parrel
parrels
parridge
parried
parries
parring
parritch
parroket
parrot
parroted
parroter
parrots
parroty
parrs
parry
parrying
pars
parsable
parse
parsec
parsecs
parsed
parser
parsers
parses
parsing
parsley
parsleys
parslied
parsnip
parsnips
parson
parsonic
parsons
part
partake
partaken
partaker
partakes
partan
partans
parted
parterre
partial
partials
partible
particle
partied
partier
partiers
parties
parting
partings
partisan
partita
partitas
partite
partizan
partlet
partlets
partly
partner
partners
parton
partons
partook
parts
partway
party
partyer
partyers
partying
parura
paruras
parure
parures
parve
parvenu
parvenue
parvenus
parvis
parvise
parvises
parvo
parvolin
parvos
pas
pascal
pascals
paschal
paschals
pase
paseo
paseos
pases
pash
pasha
pashadom
pashalic
pashalik
pashas
pashed
pashes
pashing
pasquil
pasquils
pass
passable
passably
passade
passades
passado
passados
passage
passaged
passages
passant
passband
passbook
passe
passed
passee
passel
passels
passer
passerby
passers
passes
passible
passim
passing
passings
passion
passions
passive
passives
passkey
passkeys
passless
passover
passport
passus
passuses
password
past
pasta
pastas
paste
pasted
pastel
pastels
paster
pastern
pasterns
pasters
pastes
pasteup
pasteups
pasticci
pastiche
pastie
pastier
pasties
pastiest
pastil
pastille
pastils
pastime
pastimes
pastina
pastinas
pasting
pastis
pastises
pastless
pastness
pastor
pastoral
pastored
pastors
pastrami
pastries
pastromi
pastry
pasts
pastural
pasture
pastured
pasturer
pastures
pasty
pat
pataca
patacas
patagia
patagial
patagium
patamar
patamars
patch
patched
patcher
patchers
patches
patchier
patchily
patching
patchy
pate
pated
patella
patellae
patellar
patellas
paten
patency
patens
patent
patented
patentee
patently
patentor
patents
pater
paternal
paters
pates
path
pathetic
pathless
pathogen
pathos
pathoses
paths
pathway
pathways
patience
patient
patients
patin
patina
patinae
patinas
patinate
patine
patined
patines
patining
patinize
patins
patio
patios
patly
patness
patois
patriot
patriots
patrol
patrols
patron
patronal
patronly
patrons
patroon
patroons
pats
patsies
patsy
pattamar
patted
pattee
patten
pattens
patter
pattered
patterer
pattern
patterns
patters
pattie
patties
patting
patty
pattypan
patulent
patulous
paty
patzer
patzers
paucity
paughty
pauldron
paulin
paulins
paunch
paunched
paunches
paunchy
pauper
paupered
paupers
pausal
pause
paused
pauser
pausers
pauses
pausing
pavan
pavane
pavanes
pavans
pave
paved
paveed
pavement
paver
pavers
paves
pavid
pavilion
pavillon
pavin
paving
pavings
pavins
pavior
paviors
paviour
paviours
pavis
pavise
paviser
pavisers
pavises
pavlova
pavlovas
pavonine
paw
pawed
pawer
pawers
pawing
pawkier
pawkiest
pawkily
pawky
pawl
pawls
pawn
pawnable
pawnage
pawnages
pawned
pawnee
pawnees
pawner
pawners
pawning
pawnor
pawnors
pawns
pawnshop
pawpaw
pawpaws
paws
pax
paxes
paxwax
paxwaxes
pay
payable
payables
payably
payback
paybacks
paycheck
payday
paydays
payed
payee
payees
payer
payers
paygrade
paying
payload
payloads
payment
payments
paynim
paynims
payoff
payoffs
payola
payolas
payor
payors
payout
payouts
payroll
payrolls
pays
pazazz
pazazzes
pe
pea
peace
peaced
peaceful
peacenik
peaces
peach
peached
peacher
peachers
peaches
peachier
peaching
peachy
peacing
peacoat
peacoats
peacock
peacocks
peacocky
peafowl
peafowls
peag
peage
peages
peags
peahen
peahens
peak
peaked
peakier
peakiest
peaking
peakish
peakless
peaklike
peaks
peaky
peal
pealed
pealike
pealing
peals
pean
peans
peanut
peanuts
pear
pearl
pearlash
pearled
pearler
pearlers
pearlier
pearling
pearlite
pearls
pearly
pearmain
pears
peart
pearter
peartest
peartly
peas
peasant
peasants
peascod
peascods
pease
peasecod
peasen
peases
peat
peatier
peatiest
peats
peaty
peavey
peaveys
peavies
peavy
pebble
pebbled
pebbles
pebblier
pebbling
pebbly
pec
pecan
pecans
peccable
peccancy
peccant
peccary
peccavi
peccavis
pech
pechan
pechans
peched
peching
pechs
peck
pecked
pecker
peckers
peckier
peckiest
pecking
peckish
pecks
pecky
pecorini
pecorino
pecs
pectase
pectases
pectate
pectates
pecten
pectens
pectic
pectin
pectines
pectins
pectize
pectized
pectizes
pectoral
peculate
peculia
peculiar
peculium
ped
pedagog
pedagogs
pedagogy
pedal
pedaled
pedalfer
pedalier
pedaling
pedalled
pedalo
pedalos
pedals
pedant
pedantic
pedantry
pedants
pedate
pedately
peddle
peddled
peddler
peddlers
peddlery
peddles
peddling
pederast
pedes
pedestal
pedicab
pedicabs
pedicel
pedicels
pedicle
pedicled
pedicles
pedicure
pediform
pedigree
pediment
pedipalp
pedlar
pedlars
pedlary
pedler
pedlers
pedlery
pedocal
pedocals
pedology
pedro
pedros
peds
peduncle
pee
peebeen
peebeens
peed
peeing
peek
peekaboo
peeked
peeking
peeks
peel
peelable
peeled
peeler
peelers
peeling
peelings
peels
peen
peened
peening
peens
peep
peeped
peeper
peepers
peephole
peeping
peeps
peepshow
peepul
peepuls
peer
peerage
peerages
peered
peeress
peerie
peeries
peering
peerless
peers
peery
pees
peesweep
peetweet
peeve
peeved
peeves
peeving
peevish
peewee
peewees
peewit
peewits
peg
pegboard
pegbox
pegboxes
pegged
pegging
pegless
peglike
pegs
peh
pehs
peignoir
pein
peined
peining
peins
peise
peised
peises
peising
pekan
pekans
peke
pekes
pekin
pekins
pekoe
pekoes
pelage
pelages
pelagial
pelagic
pele
pelerine
peles
pelf
pelfs
pelican
pelicans
pelisse
pelisses
pelite
pelites
pelitic
pellagra
pellet
pelletal
pelleted
pellets
pellicle
pellmell
pellucid
pelmet
pelmets
pelon
peloria
pelorian
pelorias
peloric
pelorus
pelota
pelotas
pelt
peltast
peltasts
peltate
pelted
pelter
peltered
pelters
pelting
peltries
peltry
pelts
pelves
pelvic
pelvics
pelvis
pelvises
pembina
pembinas
pemican
pemicans
pemmican
pemoline
pemphix
pen
penal
penalise
penality
penalize
penally
penalty
penance
penanced
penances
penang
penangs
penates
pence
pencel
pencels
penchant
pencil
penciled
penciler
pencils
pend
pendant
pendants
pended
pendency
pendent
pendents
pending
pends
pendular
pendulum
penes
pengo
pengos
penguin
penguins
penial
penicil
penicils
penile
penis
penises
penitent
penknife
penlight
penlite
penlites
penman
penmen
penna
pennae
penname
pennames
pennant
pennants
pennate
pennated
penne
penned
penner
penners
penni
pennia
pennies
pennine
pennines
penning
pennis
pennon
pennoned
pennons
penny
penoche
penoches
penology
penoncel
penpoint
pens
pensee
pensees
pensil
pensile
pensils
pension
pensione
pensions
pensive
penster
pensters
penstock
pent
pentacle
pentad
pentads
pentagon
pentane
pentanes
pentanol
pentarch
pentene
pentenes
pentode
pentodes
pentomic
pentosan
pentose
pentoses
pentyl
pentyls
penuche
penuches
penuchi
penuchis
penuchle
penuckle
penult
penults
penumbra
penuries
penury
peon
peonage
peonages
peones
peonies
peonism
peonisms
peons
peony
people
peopled
peopler
peoplers
peoples
peopling
pep
peperoni
pepla
peplos
peploses
peplum
peplumed
peplums
peplus
pepluses
pepo
peponida
peponium
pepos
pepped
pepper
peppered
pepperer
peppers
peppery
peppier
peppiest
peppily
pepping
peppy
peps
pepsin
pepsine
pepsines
pepsins
peptic
peptics
peptid
peptide
peptides
peptidic
peptids
peptize
peptized
peptizer
peptizes
peptone
peptones
peptonic
per
peracid
peracids
percale
percales
perceive
percent
percents
percept
percepts
perch
perched
percher
perchers
perches
perching
percoid
percoids
percuss
perdie
perdu
perdue
perdues
perdure
perdured
perdures
perdus
perdy
perea
peregrin
pereia
pereion
pereon
pereopod
perfect
perfecta
perfecto
perfects
perfidy
perforce
perform
performs
perfume
perfumed
perfumer
perfumes
perfuse
perfused
perfuses
pergola
pergolas
perhaps
peri
perianth
periapt
periapts
periblem
pericarp
pericope
periderm
peridia
peridial
peridium
peridot
peridots
perigeal
perigean
perigee
perigees
perigon
perigons
perigyny
peril
periled
periling
perilla
perillas
perilled
perilous
perils
perilune
perinea
perineal
perineum
period
periodic
periodid
periods
periotic
peripety
peripter
perique
periques
peris
perisarc
perish
perished
perishes
periwig
periwigs
perjure
perjured
perjurer
perjures
perjury
perk
perked
perkier
perkiest
perkily
perking
perkish
perks
perky
perlite
perlites
perlitic
perm
permeant
permease
permeate
permed
perming
permit
permits
perms
permute
permuted
permutes
peroneal
peroral
perorate
peroxid
peroxide
peroxids
peroxy
perpend
perpends
perpent
perpents
perplex
perries
perron
perrons
perry
persalt
persalts
perse
perses
persist
persists
person
persona
personae
personal
personas
persons
perspire
perspiry
persuade
pert
pertain
pertains
perter
pertest
pertly
pertness
perturb
perturbs
peruke
peruked
perukes
perusal
perusals
peruse
perused
peruser
perusers
peruses
perusing
pervade
pervaded
pervader
pervades
perverse
pervert
perverts
pervious
pes
pesade
pesades
peseta
pesetas
pesewa
pesewas
peskier
peskiest
peskily
pesky
peso
pesos
pessary
pest
pester
pestered
pesterer
pesters
pesthole
pestier
pestiest
pestle
pestled
pestles
pestling
pesto
pestos
pests
pesty
pet
petal
petaled
petaline
petalled
petalody
petaloid
petalous
petals
petard
petards
petasos
petasus
petcock
petcocks
petechia
peter
petered
petering
peters
petiolar
petiole
petioled
petioles
petit
petite
petites
petition
petnap
petnaps
petrale
petrales
petrel
petrels
petrify
petrol
petrolic
petrols
petronel
petrosal
petrous
pets
petsai
petsais
petted
pettedly
petter
petters
petti
pettier
pettiest
pettifog
pettily
petting
pettings
pettish
pettle
pettled
pettles
pettling
petto
petty
petulant
petunia
petunias
petuntse
petuntze
pew
pewee
pewees
pewit
pewits
pews
pewter
pewterer
pewters
peyote
peyotes
peyotl
peyotls
peytral
peytrals
peytrel
peytrels
pfennig
pfennige
pfennigs
pfft
pfui
phaeton
phaetons
phage
phages
phalange
phalanx
phalli
phallic
phallism
phallist
phallus
phantasm
phantast
phantasy
phantom
phantoms
pharaoh
pharaohs
pharisee
pharmacy
pharos
pharoses
pharynx
phase
phaseal
phased
phaseout
phases
phasic
phasing
phasis
phasmid
phasmids
phat
phatic
pheasant
phellem
phellems
phelonia
phenate
phenates
phenazin
phenetic
phenetol
phenix
phenixes
phenol
phenolic
phenols
phenom
phenoms
phenoxy
phenyl
phenylic
phenyls
phew
phi
phial
phials
philabeg
philibeg
philomel
philter
philters
philtra
philtre
philtred
philtres
philtrum
phimoses
phimosis
phimotic
phis
phiz
phizes
phlegm
phlegms
phlegmy
phloem
phloems
phlox
phloxes
phobia
phobias
phobic
phobics
phocine
phoebe
phoebes
phoebus
phoenix
phon
phonal
phonate
phonated
phonates
phone
phoned
phoneme
phonemes
phonemic
phones
phonetic
phoney
phoneyed
phoneys
phonic
phonics
phonied
phonier
phonies
phoniest
phonily
phoning
phono
phonon
phonons
phonos
phons
phony
phonying
phooey
phorate
phorates
phoronid
phosgene
phosphid
phosphin
phosphor
phot
photic
photics
photo
photoed
photog
photogs
photoing
photomap
photon
photonic
photons
photopia
photopic
photos
photoset
phots
phpht
phrasal
phrase
phrased
phrases
phrasing
phratral
phratric
phratry
phreatic
phrenic
phrensy
pht
phthalic
phthalin
phthises
phthisic
phthisis
phut
phuts
phyla
phylae
phylar
phylaxis
phyle
phyleses
phylesis
phyletic
phylic
phyllary
phyllite
phyllo
phyllode
phylloid
phyllome
phyllos
phylon
phylum
physed
physeds
physes
physic
physical
physics
physique
physis
phytane
phytanes
phytoid
phytol
phytols
phyton
phytonic
phytons
pi
pia
piacular
piaffe
piaffed
piaffer
piaffers
piaffes
piaffing
pial
pian
pianic
pianism
pianisms
pianist
pianists
piano
pianos
pians
pias
piasaba
piasabas
piasava
piasavas
piassaba
piassava
piaster
piasters
piastre
piastres
piazza
piazzas
piazze
pibal
pibals
pibroch
pibrochs
pic
pica
picacho
picachos
picador
picadors
pical
picara
picaras
picaro
picaroon
picaros
picas
picayune
piccolo
piccolos
pice
piceous
piciform
pick
pickadil
pickax
pickaxe
pickaxed
pickaxes
picked
pickeer
pickeers
picker
pickerel
pickers
picket
picketed
picketer
pickets
pickier
pickiest
picking
pickings
pickle
pickled
pickles
pickling
picklock
pickoff
pickoffs
picks
pickup
pickups
pickwick
picky
picloram
picnic
picnicky
picnics
picogram
picolin
picoline
picolins
picomole
picot
picoted
picotee
picotees
picoting
picots
picquet
picquets
picrate
picrated
picrates
picric
picrite
picrites
picritic
pics
picture
pictured
pictures
picul
piculs
piddle
piddled
piddler
piddlers
piddles
piddling
piddly
piddock
piddocks
pidgin
pidgins
pie
piebald
piebalds
piece
pieced
piecer
piecers
pieces
piecing
piecings
piecrust
pied
piedfort
piedmont
piefort
pieforts
pieing
pieplant
pier
pierce
pierced
piercer
piercers
pierces
piercing
pierogi
pierrot
pierrots
piers
pies
pieta
pietas
pieties
pietism
pietisms
pietist
pietists
piety
piffle
piffled
piffles
piffling
pig
pigboat
pigboats
pigeon
pigeons
pigfish
pigged
piggery
piggie
piggier
piggies
piggiest
piggin
pigging
piggins
piggish
piggy
piglet
piglets
piglike
pigment
pigments
pigmies
pigmy
pignoli
pignolia
pignolis
pignora
pignus
pignut
pignuts
pigout
pigouts
pigpen
pigpens
pigs
pigskin
pigskins
pigsney
pigsneys
pigstick
pigsties
pigsty
pigtail
pigtails
pigweed
pigweeds
piing
pika
pikake
pikakes
pikas
pike
piked
pikeman
pikemen
piker
pikers
pikes
piki
piking
pikis
pilaf
pilaff
pilaffs
pilafs
pilar
pilaster
pilau
pilaus
pilaw
pilaws
pilchard
pile
pilea
pileate
pileated
piled
pilei
pileless
pileous
piles
pileum
pileup
pileups
pileus
pilewort
pilfer
pilfered
pilferer
pilfers
pilgrim
pilgrims
pili
piliform
piling
pilings
pilis
pill
pillage
pillaged
pillager
pillages
pillar
pillared
pillars
pillbox
pilled
pilling
pillion
pillions
pillory
pillow
pillowed
pillows
pillowy
pills
pilose
pilosity
pilot
pilotage
piloted
piloting
pilots
pilous
pilsener
pilsner
pilsners
pilular
pilule
pilules
pilus
pily
pima
pimas
pimento
pimentos
pimiento
pimp
pimped
pimping
pimple
pimpled
pimples
pimplier
pimply
pimps
pin
pina
pinafore
pinang
pinangs
pinas
pinaster
pinata
pinatas
pinball
pinballs
pinbone
pinbones
pincer
pincers
pinch
pinchbug
pincheck
pinched
pincher
pinchers
pinches
pinching
pinder
pinders
pindling
pine
pineal
pineals
pinecone
pined
pineland
pinelike
pinene
pinenes
pineries
pinery
pines
pinesap
pinesaps
pineta
pinetum
pinewood
piney
pinfish
pinfold
pinfolds
ping
pinged
pinger
pingers
pinging
pingo
pingos
pingrass
pings
pinguid
pinhead
pinheads
pinhole
pinholes
pinier
piniest
pining
pinion
pinioned
pinions
pinite
pinites
pinitol
pinitols
pink
pinked
pinken
pinkened
pinkens
pinker
pinkers
pinkest
pinkey
pinkeye
pinkeyes
pinkeys
pinkie
pinkies
pinking
pinkings
pinkish
pinkly
pinkness
pinko
pinkoes
pinkos
pinkroot
pinks
pinky
pinna
pinnace
pinnaces
pinnacle
pinnae
pinnal
pinnas
pinnate
pinnated
pinned
pinner
pinners
pinnies
pinning
pinniped
pinnula
pinnulae
pinnular
pinnule
pinnules
pinny
pinochle
pinocle
pinocles
pinole
pinoles
pinon
pinones
pinons
pinot
pinots
pinpoint
pinprick
pins
pinscher
pint
pinta
pintada
pintadas
pintado
pintados
pintail
pintails
pintano
pintanos
pintas
pintle
pintles
pinto
pintoes
pintos
pints
pintsize
pinup
pinups
pinwale
pinwales
pinweed
pinweeds
pinwheel
pinwork
pinworks
pinworm
pinworms
piny
pinyin
pinyon
pinyons
piolet
piolets
pion
pioneer
pioneers
pionic
pions
piosity
pious
piously
pip
pipage
pipages
pipal
pipals
pipe
pipeage
pipeages
piped
pipefish
pipeful
pipefuls
pipeless
pipelike
pipeline
piper
piperine
pipers
pipes
pipestem
pipet
pipets
pipette
pipetted
pipettes
pipier
pipiest
pipiness
piping
pipingly
pipings
pipit
pipits
pipkin
pipkins
pipped
pippin
pipping
pippins
pips
pipy
piquance
piquancy
piquant
pique
piqued
piques
piquet
piquets
piquing
piracies
piracy
piragua
piraguas
pirana
piranas
piranha
piranhas
pirarucu
pirate
pirated
pirates
piratic
pirating
piraya
pirayas
piriform
pirn
pirns
pirog
pirogen
piroghi
pirogi
pirogies
pirogue
pirogues
pirojki
piroque
piroques
piroshki
pirozhki
pirozhok
pis
piscary
piscator
piscina
piscinae
piscinal
piscinas
piscine
pisco
piscos
pish
pished
pishes
pishing
pishoge
pishoges
pishogue
pisiform
pismire
pismires
piso
pisolite
pisos
piss
pissant
pissants
pissed
pisser
pissers
pisses
pissing
pissoir
pissoirs
pistache
piste
pistes
pistil
pistils
pistol
pistole
pistoled
pistoles
pistols
piston
pistons
pit
pita
pitapat
pitapats
pitas
pitch
pitched
pitcher
pitchers
pitches
pitchier
pitchily
pitching
pitchman
pitchmen
pitchout
pitchy
piteous
pitfall
pitfalls
pith
pithead
pitheads
pithed
pithier
pithiest
pithily
pithing
pithless
piths
pithy
pitiable
pitiably
pitied
pitier
pitiers
pities
pitiful
pitiless
pitman
pitmans
pitmen
piton
pitons
pits
pitsaw
pitsaws
pittance
pitted
pitting
pittings
pity
pitying
piu
pivot
pivotal
pivoted
pivoting
pivotman
pivotmen
pivots
pix
pixel
pixels
pixes
pixie
pixieish
pixies
pixiness
pixy
pixyish
pizazz
pizazzes
pizazzy
pizza
pizzas
pizzeria
pizzle
pizzles
placable
placably
placard
placards
placate
placated
placater
placates
place
placebo
placebos
placed
placeman
placemen
placenta
placer
placers
places
placet
placets
placid
placidly
placing
plack
placket
plackets
placks
placoid
placoids
plafond
plafonds
plagal
plage
plages
plagiary
plague
plagued
plaguer
plaguers
plagues
plaguey
plaguily
plaguing
plaguy
plaice
plaices
plaid
plaided
plaids
plain
plained
plainer
plainest
plaining
plainly
plains
plaint
plaints
plaister
plait
plaited
plaiter
plaiters
plaiting
plaits
plan
planar
planaria
planate
planch
planche
planches
planchet
plane
planed
planer
planers
planes
planet
planets
planform
plangent
planing
planish
plank
planked
planking
planks
plankter
plankton
planless
planned
planner
planners
planning
planosol
plans
plant
plantain
plantar
planted
planter
planters
planting
plantlet
plants
planula
planulae
planular
plaque
plaques
plash
plashed
plasher
plashers
plashes
plashier
plashing
plashy
plasm
plasma
plasmas
plasmic
plasmid
plasmids
plasmin
plasmins
plasmoid
plasmon
plasmons
plasms
plaster
plasters
plastery
plastic
plastics
plastid
plastids
plastral
plastron
plastrum
plat
platan
platane
platanes
platans
plate
plateau
plateaus
plateaux
plated
plateful
platelet
platen
platens
plater
platers
plates
platform
platier
platies
platiest
platina
platinas
plating
platings
platinic
platinum
platonic
platoon
platoons
plats
platted
platter
platters
platting
platy
platypi
platypus
platys
plaudit
plaudits
plausive
play
playa
playable
playact
playacts
playas
playback
playbill
playbook
playboy
playboys
playdate
playday
playdays
playdown
played
player
players
playful
playgirl
playgoer
playing
playland
playless
playlet
playlets
playlike
playlist
playmate
playoff
playoffs
playpen
playpens
playroom
plays
playsuit
playtime
playwear
plaza
plazas
plea
pleach
pleached
pleaches
plead
pleaded
pleader
pleaders
pleading
pleads
pleas
pleasant
please
pleased
pleaser
pleasers
pleases
pleasing
pleasure
pleat
pleated
pleater
pleaters
pleating
pleats
pleb
plebe
plebeian
plebes
plebs
plectra
plectron
plectrum
pled
pledge
pledged
pledgee
pledgees
pledgeor
pledger
pledgers
pledges
pledget
pledgets
pledging
pledgor
pledgors
pleiad
pleiades
pleiads
plena
plenary
plench
plenches
plenish
plenism
plenisms
plenist
plenists
plenties
plenty
plenum
plenums
pleonasm
pleopod
pleopods
plessor
plessors
plethora
pleura
pleurae
pleural
pleuras
pleurisy
pleuron
pleuston
plew
plews
plexal
plexor
plexors
plexus
plexuses
pliable
pliably
pliancy
pliant
pliantly
plica
plicae
plical
plicate
plicated
plie
plied
plier
pliers
plies
plight
plighted
plighter
plights
plimsol
plimsole
plimsoll
plimsols
plink
plinked
plinker
plinkers
plinking
plinks
plinth
plinths
pliotron
pliskie
pliskies
plisky
plisse
plisses
plod
plodded
plodder
plodders
plodding
plods
ploidies
ploidy
plonk
plonked
plonking
plonks
plop
plopped
plopping
plops
plosion
plosions
plosive
plosives
plot
plotless
plotline
plots
plottage
plotted
plotter
plotters
plottier
plotties
plotting
plotty
plotz
plotzed
plotzes
plotzing
plough
ploughed
plougher
ploughs
plover
plovers
plow
plowable
plowback
plowboy
plowboys
plowed
plower
plowers
plowhead
plowing
plowland
plowman
plowmen
plows
ploy
ployed
ploying
ploys
pluck
plucked
plucker
pluckers
pluckier
pluckily
plucking
plucks
plucky
plug
plugged
plugger
pluggers
plugging
plugless
plugola
plugolas
plugs
plugugly
plum
plumage
plumaged
plumages
plumate
plumb
plumbago
plumbed
plumber
plumbers
plumbery
plumbic
plumbing
plumbism
plumbous
plumbs
plumbum
plumbums
plume
plumed
plumelet
plumeria
plumes
plumier
plumiest
pluming
plumiped
plumlike
plummet
plummets
plummier
plummy
plumose
plump
plumped
plumpen
plumpens
plumper
plumpers
plumpest
plumping
plumpish
plumply
plumps
plums
plumular
plumule
plumules
plumy
plunder
plunders
plunge
plunged
plunger
plungers
plunges
plunging
plunk
plunked
plunker
plunkers
plunking
plunks
plural
plurally
plurals
plus
pluses
plush
plusher
plushes
plushest
plushier
plushily
plushly
plushy
plussage
plusses
plutei
pluteus
pluton
plutonic
plutons
pluvial
pluvials
pluvian
pluviose
pluvious
ply
plyer
plyers
plying
plyingly
plywood
plywoods
pneuma
pneumas
poaceous
poach
poached
poacher
poachers
poaches
poachier
poaching
poachy
pochard
pochards
pock
pocked
pocket
pocketed
pocketer
pockets
pockier
pockiest
pockily
pocking
pockmark
pocks
pocky
poco
pocosin
pocosins
pod
podagra
podagral
podagras
podagric
podded
podding
podesta
podestas
podgier
podgiest
podgily
podgy
podia
podiatry
podite
podites
poditic
podium
podiums
podlike
podocarp
podomere
pods
podsol
podsolic
podsols
podzol
podzolic
podzols
poechore
poem
poems
poesies
poesy
poet
poetess
poetic
poetical
poetics
poetise
poetised
poetiser
poetises
poetize
poetized
poetizer
poetizes
poetless
poetlike
poetries
poetry
poets
pogey
pogeys
pogies
pogonia
pogonias
pogonip
pogonips
pogrom
pogromed
pogroms
pogy
poh
poi
poignant
poilu
poilus
poind
poinded
poinding
poinds
point
pointe
pointed
pointer
pointers
pointes
pointier
pointing
pointman
pointmen
points
pointy
pois
poise
poised
poiser
poisers
poises
poisha
poising
poison
poisoned
poisoner
poisons
poitrel
poitrels
poke
poked
poker
pokeroot
pokers
pokes
pokeweed
pokey
pokeys
pokier
pokies
pokiest
pokily
pokiness
poking
poky
pol
polar
polarise
polarity
polarize
polaron
polarons
polars
polder
polders
pole
poleax
poleaxe
poleaxed
poleaxes
polecat
polecats
poled
poleis
poleless
polemic
polemics
polemist
polemize
polenta
polentas
poler
polers
poles
polestar
poleward
poleyn
poleyns
police
policed
polices
policies
policing
policy
poling
polio
polios
polis
polish
polished
polisher
polishes
polite
politely
politer
politest
politic
politick
politico
politics
polities
polity
polka
polkaed
polkaing
polkas
poll
pollack
pollacks
pollard
pollards
polled
pollee
pollees
pollen
pollened
pollens
poller
pollers
pollex
pollical
pollices
polling
pollinia
pollinic
pollist
pollists
polliwog
pollock
pollocks
polls
pollster
pollute
polluted
polluter
pollutes
pollywog
polo
poloist
poloists
polonium
polos
pols
poltroon
poly
polybrid
polycot
polycots
polyene
polyenes
polyenic
polygala
polygamy
polygene
polyglot
polygon
polygons
polygony
polygyny
polymath
polymer
polymers
polynya
polynyas
polynyi
polyoma
polyomas
polyp
polypary
polypi
polypide
polypnea
polypod
polypods
polypody
polypoid
polypore
polypous
polyps
polypus
polys
polysemy
polysome
polytene
polyteny
polytype
polyuria
polyuric
polyzoan
polyzoic
pom
pomace
pomaces
pomade
pomaded
pomades
pomading
pomander
pomatum
pomatums
pome
pomelo
pomelos
pomes
pomfret
pomfrets
pommee
pommel
pommeled
pommels
pommie
pommies
pommy
pomology
pomp
pompano
pompanos
pompom
pompoms
pompon
pompons
pompous
pomps
poms
ponce
ponced
ponces
poncho
ponchos
poncing
pond
ponded
ponder
pondered
ponderer
ponders
ponding
ponds
pondweed
pone
ponent
pones
pong
ponged
pongee
pongees
pongid
pongids
ponging
pongs
poniard
poniards
ponied
ponies
pons
pontes
pontifex
pontiff
pontiffs
pontific
pontil
pontils
pontine
ponton
pontons
pontoon
pontoons
pony
ponying
ponytail
pooch
pooched
pooches
pooching
pood
poodle
poodles
poods
poof
poofs
pooftah
pooftahs
poofter
poofters
poofy
pooh
poohed
poohing
poohs
pool
pooled
poolhall
pooling
poolroom
pools
poolside
poon
poons
poop
pooped
pooping
poops
poor
poorer
poorest
poori
pooris
poorish
poorly
poorness
poortith
poove
pooves
pop
popcorn
popcorns
pope
popedom
popedoms
popeless
popelike
poperies
popery
popes
popeyed
popgun
popguns
popinjay
popish
popishly
poplar
poplars
poplin
poplins
poplitic
popover
popovers
poppa
poppas
popped
popper
poppers
poppet
poppets
poppied
poppies
popping
popple
poppled
popples
poppling
poppy
pops
popsie
popsies
popsy
populace
popular
populate
populism
populist
populous
porch
porches
porcine
porcini
porcino
pore
pored
pores
porgies
porgy
poring
porism
porisms
pork
porker
porkers
porkier
porkies
porkiest
porkpie
porkpies
porks
porkwood
porky
porn
pornier
porniest
porno
pornos
porns
porny
porose
porosity
porous
porously
porphyry
porpoise
porrect
porridge
porridgy
port
portable
portably
portage
portaged
portages
portal
portaled
portals
portance
portapak
ported
portend
portends
portent
portents
porter
portered
porters
porthole
portico
porticos
portiere
porting
portion
portions
portless
portlier
portly
portrait
portray
portrays
portress
ports
posada
posadas
pose
posed
poser
posers
poses
poseur
poseurs
posh
posher
poshest
poshly
poshness
posies
posing
posingly
posit
posited
positing
position
positive
positron
posits
posology
posse
posses
possess
posset
possets
possible
possibly
possum
possums
post
postage
postages
postal
postally
postals
postanal
postbag
postbags
postbase
postbox
postboy
postboys
postburn
postcard
postcava
postcode
postcoup
postdate
postdive
postdoc
postdocs
postdrug
posted
posteen
posteens
poster
postern
posterns
posters
postface
postfire
postfix
postform
postgame
postheat
posthole
postiche
postin
posting
postings
postins
postique
postlude
postman
postmark
postmen
postoral
postpaid
postpone
postrace
postriot
posts
postshow
postsync
posttax
postteen
posttest
postural
posture
postured
posturer
postures
postwar
posy
pot
potable
potables
potage
potages
potamic
potash
potashes
potassic
potation
potato
potatoes
potatory
potbelly
potboil
potboils
potboy
potboys
poteen
poteens
potence
potences
potency
potent
potently
potful
potfuls
pothead
potheads
potheen
potheens
pother
potherb
potherbs
pothered
pothers
pothole
potholed
potholes
pothook
pothooks
pothouse
potiche
potiches
potion
potions
potlach
potlache
potlatch
potlike
potline
potlines
potluck
potlucks
potman
potmen
potpie
potpies
pots
potshard
potsherd
potshot
potshots
potsie
potsies
potstone
potsy
pottage
pottages
potted
potteen
potteens
potter
pottered
potterer
potters
pottery
pottier
potties
pottiest
potting
pottle
pottles
potto
pottos
potty
potzer
potzers
pouch
pouched
pouches
pouchier
pouching
pouchy
pouf
poufed
pouff
pouffe
pouffed
pouffes
pouffs
poufs
poulard
poularde
poulards
poult
poulter
poulters
poultice
poultry
poults
pounce
pounced
pouncer
pouncers
pounces
pouncing
pound
poundage
poundal
poundals
pounded
pounder
pounders
pounding
pounds
pour
pourable
poured
pourer
pourers
pouring
pours
poussie
poussies
pout
pouted
pouter
pouters
poutful
poutier
poutiest
pouting
pouts
pouty
poverty
pow
powder
powdered
powderer
powders
powdery
power
powered
powerful
powering
powers
pows
powter
powters
powwow
powwowed
powwows
pox
poxed
poxes
poxing
poxvirus
poyou
poyous
pozzolan
praam
praams
practic
practice
practise
praecipe
praedial
praefect
praelect
praetor
praetors
prahu
prahus
prairie
prairies
praise
praised
praiser
praisers
praises
praising
praline
pralines
pram
prams
prance
pranced
prancer
prancers
prances
prancing
prandial
prang
pranged
pranging
prangs
prank
pranked
pranking
prankish
pranks
prao
praos
prase
prases
prat
prate
prated
prater
praters
prates
pratfall
prating
pratique
prats
prattle
prattled
prattler
prattles
prau
praus
prawn
prawned
prawner
prawners
prawning
prawns
praxes
praxis
praxises
pray
prayed
prayer
prayers
praying
prays
preach
preached
preacher
preaches
preachy
preact
preacted
preacts
preadapt
preadmit
preadopt
preadult
preaged
preallot
preamble
preamp
preamps
preanal
prearm
prearmed
prearms
preaudit
preaver
preavers
preaxial
prebake
prebaked
prebakes
prebasal
prebend
prebends
prebill
prebills
prebind
prebinds
prebless
preboil
preboils
prebook
prebooks
preboom
prebound
precast
precasts
precava
precavae
precaval
precede
preceded
precedes
precent
precents
precept
precepts
precess
precheck
prechill
precieux
precinct
precious
precipe
precipes
precis
precise
precised
preciser
precises
precited
preclean
preclear
preclude
precode
precoded
precodes
precook
precooks
precool
precools
precoup
precrash
precure
precured
precures
precut
precuts
predate
predated
predates
predator
predawn
predawns
predial
predict
predicts
predive
predrill
predusk
predusks
pree
preed
preedit
preedits
preeing
preelect
preemie
preemies
preempt
preempts
preen
preenact
preened
preener
preeners
preening
preens
preerect
prees
preexist
prefab
prefabs
preface
prefaced
prefacer
prefaces
prefade
prefaded
prefades
prefect
prefects
prefer
prefers
prefight
prefile
prefiled
prefiles
prefire
prefired
prefires
prefix
prefixal
prefixed
prefixes
preflame
prefocus
preform
preforms
prefrank
prefroze
pregame
preggers
pregnant
preheat
preheats
prehuman
prejudge
prelacy
prelate
prelates
prelatic
prelect
prelects
prelegal
prelife
prelim
prelimit
prelims
prelives
prelude
preluded
preluder
preludes
prelunch
premade
preman
premeal
premed
premedic
premeds
premeet
premen
premie
premier
premiere
premiers
premies
premise
premised
premises
premiss
premium
premiums
premix
premixed
premixes
premixt
premolar
premold
premolds
premolt
premoral
premorse
premune
prename
prenames
prenatal
prenomen
prenoon
prentice
preorder
prep
prepack
prepacks
prepaid
prepare
prepared
preparer
prepares
prepaste
prepay
prepays
prepense
prepill
preplace
preplan
preplans
preplant
prepped
preppie
preppier
preppies
preppily
prepping
preppy
prepreg
prepregs
preprice
preprint
preps
prepuce
prepuces
prepunch
prepupal
prequel
prequels
prerace
prerenal
prerinse
preriot
prerock
presa
presage
presaged
presager
presages
presale
prescind
prescore
prese
presell
presells
presence
present
presents
preserve
preset
presets
preshape
preshow
preshown
preshows
preside
presided
presider
presides
presidia
presidio
presift
presifts
presleep
preslice
presoak
presoaks
presold
presong
presort
presorts
presplit
press
pressed
presser
pressers
presses
pressing
pressman
pressmen
pressor
pressors
pressrun
pressure
prest
prestamp
prester
presters
prestige
presto
prestos
prests
presume
presumed
presumer
presumes
pretape
pretaped
pretapes
pretaste
pretax
preteen
preteens
pretence
pretend
pretends
pretense
preterit
preterm
pretest
pretests
pretext
pretexts
pretor
pretors
pretrain
pretreat
pretrial
pretrim
pretrims
prettied
prettier
pretties
prettify
prettily
pretty
pretype
pretyped
pretypes
pretzel
pretzels
preunion
preunite
prevail
prevails
prevent
prevents
preview
previews
previous
previse
prevised
previses
previsor
prevue
prevued
prevues
prevuing
prewar
prewarm
prewarms
prewarn
prewarns
prewash
prework
prewrap
prewraps
prex
prexes
prexies
prexy
prey
preyed
preyer
preyers
preying
preys
prez
prezes
priapean
priapi
priapic
priapism
priapus
price
priced
pricer
pricers
prices
pricey
pricier
priciest
pricing
prick
pricked
pricker
prickers
pricket
prickets
prickier
pricking
prickle
prickled
prickles
prickly
pricks
pricky
pricy
pride
prided
prideful
prides
priding
pried
priedieu
prier
priers
pries
priest
priested
priestly
priests
prig
prigged
priggery
prigging
priggish
priggism
prigs
prill
prilled
prilling
prills
prim
prima
primacy
primage
primages
primal
primary
primas
primatal
primate
primates
prime
primed
primely
primer
primero
primeros
primers
primes
primeval
primi
primine
primines
priming
primings
primly
primmed
primmer
primmest
primming
primness
primo
primos
primp
primped
primping
primps
primrose
prims
primsie
primula
primulas
primus
primuses
prince
princely
princes
princess
principe
principi
princock
princox
prink
prinked
prinker
prinkers
prinking
prinks
print
printed
printer
printers
printery
printing
printout
prints
prion
prions
prior
priorate
prioress
priories
priority
priorly
priors
priory
prise
prised
prisere
priseres
prises
prising
prism
prismoid
prisms
prison
prisoned
prisoner
prisons
priss
prissed
prisses
prissier
prissies
prissily
prissing
prissy
pristane
pristine
prithee
privacy
private
privater
privates
privet
privets
privier
privies
priviest
privily
privity
privy
prize
prized
prizer
prizers
prizes
prizing
pro
proa
proas
probable
probably
proband
probands
probang
probangs
probate
probated
probates
probe
probed
prober
probers
probes
probing
probit
probits
probity
problem
problems
procaine
procarp
procarps
proceed
proceeds
process
prochain
prochein
proclaim
proctor
proctors
procural
procure
procured
procurer
procures
prod
prodded
prodder
prodders
prodding
prodigal
prodigy
prodrome
prods
produce
produced
producer
produces
product
products
proem
proemial
proems
proette
proettes
prof
profane
profaned
profaner
profanes
profess
proffer
proffers
profile
profiled
profiler
profiles
profit
profited
profiter
profits
profound
profs
profuse
prog
progeny
progeria
progged
progger
proggers
progging
prognose
prograde
program
programs
progress
progs
prohibit
project
projects
projet
projets
prolabor
prolamin
prolan
prolans
prolapse
prolate
prole
proleg
prolegs
proles
prolific
proline
prolines
prolix
prolixly
prolog
prologed
prologs
prologue
prolong
prolonge
prolongs
prom
promine
promines
promise
promised
promisee
promiser
promises
promisor
promo
promos
promote
promoted
promoter
promotes
prompt
prompted
prompter
promptly
prompts
proms
promulge
pronate
pronated
pronates
pronator
prone
pronely
prong
pronged
pronging
prongs
pronota
pronotum
pronoun
pronouns
pronto
proof
proofed
proofer
proofers
proofing
proofs
prop
propane
propanes
propel
propels
propend
propends
propene
propenes
propenol
propense
propenyl
proper
properer
properly
propers
property
prophage
prophase
prophecy
prophesy
prophet
prophets
propine
propined
propines
propjet
propjets
propman
propmen
propolis
propone
proponed
propones
proposal
propose
proposed
proposer
proposes
propound
propped
propping
props
propyl
propyla
propylic
propylon
propyls
prorate
prorated
prorates
prorogue
pros
prosaic
prosaism
prosaist
prose
prosect
prosects
prosed
proser
prosers
proses
prosier
prosiest
prosily
prosing
prosit
proso
prosodic
prosody
prosoma
prosomal
prosomas
prosos
prospect
prosper
prospers
pross
prosses
prossie
prossies
prost
prostate
prostie
prosties
prostyle
prosy
protamin
protases
protasis
protatic
protea
protean
proteans
proteas
protease
protect
protects
protege
protegee
proteges
protei
proteid
proteide
proteids
protein
proteins
protend
protends
proteose
protest
protests
proteus
protist
protists
protium
protiums
protocol
proton
protonic
protons
protopod
protoxid
protozoa
protract
protrude
protyl
protyle
protyles
protyls
proud
prouder
proudest
proudful
proudly
prounion
provable
provably
prove
proved
proven
provenly
prover
proverb
proverbs
provers
proves
provide
provided
provider
provides
province
proving
proviral
provirus
proviso
provisos
provoke
provoked
provoker
provokes
provost
provosts
prow
prowar
prower
prowess
prowest
prowl
prowled
prowler
prowlers
prowling
prowls
prows
proxemic
proxies
proximal
proximo
proxy
prude
prudence
prudent
prudery
prudes
prudish
pruinose
prunable
prune
pruned
prunella
prunelle
prunello
pruner
pruners
prunes
pruning
prunus
prunuses
prurient
prurigo
prurigos
pruritic
pruritus
prussic
pruta
prutah
prutot
prutoth
pry
pryer
pryers
prying
pryingly
prythee
psalm
psalmed
psalmic
psalming
psalmist
psalmody
psalms
psalter
psalters
psaltery
psaltry
psammite
psammon
psammons
pschent
pschents
psephite
pseud
pseudo
pseudos
pseuds
pshaw
pshawed
pshawing
pshaws
psi
psilocin
psiloses
psilosis
psilotic
psis
psoae
psoai
psoas
psoatic
psocid
psocids
psoralea
psoralen
psst
psych
psyche
psyched
psyches
psychic
psychics
psyching
psycho
psychos
psychs
psylla
psyllas
psyllid
psyllids
psyllium
psywar
psywars
pterin
pterins
pteropod
pterygia
pteryla
pterylae
ptisan
ptisans
ptomain
ptomaine
ptomains
ptoses
ptosis
ptotic
ptyalin
ptyalins
ptyalism
pub
puberal
pubertal
puberty
pubes
pubic
pubis
public
publican
publicly
publics
publish
pubs
puccoon
puccoons
puce
puces
puck
pucka
pucker
puckered
puckerer
puckers
puckery
puckish
pucks
pud
pudding
puddings
puddle
puddled
puddler
puddlers
puddles
puddlier
puddling
puddly
pudency
pudenda
pudendal
pudendum
pudgier
pudgiest
pudgily
pudgy
pudibund
pudic
puds
pueblo
pueblos
puerile
puff
puffball
puffed
puffer
puffers
puffery
puffier
puffiest
puffily
puffin
puffing
puffins
puffs
puffy
pug
pugaree
pugarees
puggaree
pugged
puggier
puggiest
pugging
puggish
puggree
puggrees
puggries
puggry
puggy
pugh
pugilism
pugilist
pugmark
pugmarks
pugree
pugrees
pugs
puisne
puisnes
puissant
puja
pujah
pujahs
pujas
puke
puked
pukes
puking
pukka
pul
pula
pule
puled
puler
pulers
pules
puli
pulicene
pulicide
pulik
puling
pulingly
pulings
pulis
pull
pullback
pulled
puller
pullers
pullet
pullets
pulley
pulleys
pulling
pullman
pullmans
pullout
pullouts
pullover
pulls
pullup
pullups
pulmonic
pulmotor
pulp
pulpal
pulpally
pulped
pulper
pulpers
pulpier
pulpiest
pulpily
pulping
pulpit
pulpital
pulpits
pulpless
pulpous
pulps
pulpwood
pulpy
pulque
pulques
puls
pulsant
pulsar
pulsars
pulsate
pulsated
pulsates
pulsator
pulse
pulsed
pulsejet
pulser
pulsers
pulses
pulsing
pulsion
pulsions
pulsojet
pulvilli
pulvinar
pulvini
pulvinus
puma
pumas
pumelo
pumelos
pumice
pumiced
pumicer
pumicers
pumices
pumicing
pumicite
pummel
pummeled
pummelo
pummelos
pummels
pump
pumped
pumper
pumpers
pumping
pumpkin
pumpkins
pumpless
pumplike
pumps
pun
puna
punas
punch
punched
puncheon
puncher
punchers
punches
punchier
punchily
punching
punchy
punctate
punctual
puncture
pundit
punditic
punditry
pundits
pung
pungency
pungent
pungle
pungled
pungles
pungling
pungs
punier
puniest
punily
puniness
punish
punished
punisher
punishes
punition
punitive
punitory
punk
punka
punkah
punkahs
punkas
punker
punkers
punkest
punkey
punkeys
punkie
punkier
punkies
punkiest
punkin
punkins
punkish
punks
punky
punned
punner
punners
punnet
punnets
punnier
punniest
punning
punny
puns
punster
punsters
punt
punted
punter
punters
punties
punting
punto
puntos
punts
punty
puny
pup
pupa
pupae
pupal
puparia
puparial
puparium
pupas
pupate
pupated
pupates
pupating
pupation
pupfish
pupil
pupilage
pupilar
pupilary
pupils
pupped
puppet
puppetry
puppets
puppies
pupping
puppy
puppydom
puppyish
pups
pur
purana
puranas
puranic
purblind
purchase
purda
purdah
purdahs
purdas
pure
purebred
puree
pureed
pureeing
purees
purely
pureness
purer
purest
purfle
purfled
purfles
purfling
purge
purged
purger
purgers
purges
purging
purgings
puri
purified
purifier
purifies
purify
purin
purine
purines
purins
puris
purism
purisms
purist
puristic
purists
puritan
puritans
purities
purity
purl
purled
purlieu
purlieus
purlin
purline
purlines
purling
purlins
purloin
purloins
purls
purple
purpled
purpler
purples
purplest
purpling
purplish
purply
purport
purports
purpose
purposed
purposes
purpura
purpuras
purpure
purpures
purpuric
purpurin
purr
purred
purring
purrs
purs
purse
pursed
purser
pursers
purses
pursier
pursiest
pursily
pursing
purslane
pursuant
pursue
pursued
pursuer
pursuers
pursues
pursuing
pursuit
pursuits
pursy
purulent
purvey
purveyed
purveyor
purveys
purview
purviews
pus
puses
push
pushball
pushcart
pushdown
pushed
pusher
pushers
pushes
pushful
pushier
pushiest
pushily
pushing
pushover
pushpin
pushpins
pushrod
pushrods
pushup
pushups
pushy
pusley
pusleys
puslike
puss
pusses
pussier
pussies
pussiest
pussley
pussleys
pusslies
pusslike
pussly
pussy
pussycat
pustular
pustule
pustuled
pustules
put
putamen
putamina
putative
putlog
putlogs
putoff
putoffs
puton
putons
putout
putouts
putrefy
putrid
putridly
puts
putsch
putsches
putt
putted
puttee
puttees
putter
puttered
putterer
putters
putti
puttied
puttier
puttiers
putties
putting
putto
putts
putty
puttying
putz
putzed
putzes
putzing
puzzle
puzzled
puzzler
puzzlers
puzzles
puzzling
pya
pyaemia
pyaemias
pyaemic
pyas
pycnidia
pycnoses
pycnosis
pycnotic
pye
pyelitic
pyelitis
pyemia
pyemias
pyemic
pyes
pygidia
pygidial
pygidium
pygmaean
pygmean
pygmies
pygmoid
pygmy
pygmyish
pygmyism
pyic
pyin
pyins
pyjamas
pyknic
pyknics
pyknoses
pyknosis
pyknotic
pylon
pylons
pylori
pyloric
pylorus
pyoderma
pyogenic
pyoid
pyorrhea
pyoses
pyosis
pyralid
pyralids
pyramid
pyramids
pyran
pyranoid
pyranose
pyrans
pyre
pyrene
pyrenes
pyrenoid
pyres
pyretic
pyrexia
pyrexial
pyrexias
pyrexic
pyric
pyridic
pyridine
pyriform
pyrite
pyrites
pyritic
pyritous
pyrogen
pyrogens
pyrola
pyrolas
pyrolize
pyrology
pyrolyze
pyrone
pyrones
pyronine
pyrope
pyropes
pyrosis
pyrostat
pyroxene
pyrrhic
pyrrhics
pyrrol
pyrrole
pyrroles
pyrrolic
pyrrols
pyruvate
python
pythonic
pythons
pyuria
pyurias
pyx
pyxes
pyxides
pyxidia
pyxidium
pyxie
pyxies
pyxis
qaid
qaids
qanat
qanats
qat
qats
qindar
qindarka
qindars
qintar
qintars
qiviut
qiviuts
qoph
qophs
qua
quaalude
quack
quacked
quackery
quacking
quackish
quackism
quacks
quad
quadded
quadding
quadplex
quadrans
quadrant
quadrat
quadrate
quadrats
quadric
quadrics
quadriga
quadroon
quads
quaere
quaeres
quaestor
quaff
quaffed
quaffer
quaffers
quaffing
quaffs
quag
quagga
quaggas
quaggier
quaggy
quagmire
quagmiry
quags
quahaug
quahaugs
quahog
quahogs
quai
quaich
quaiches
quaichs
quaigh
quaighs
quail
quailed
quailing
quails
quaint
quainter
quaintly
quais
quake
quaked
quaker
quakers
quakes
quakier
quakiest
quakily
quaking
quaky
quale
qualia
qualify
quality
qualm
qualmier
qualmish
qualms
qualmy
quamash
quandang
quandary
quandong
quango
quangos
quant
quanta
quantal
quanted
quantic
quantics
quantify
quantile
quanting
quantity
quantize
quantong
quants
quantum
quare
quark
quarks
quarrel
quarrels
quarried
quarrier
quarries
quarry
quart
quartan
quartans
quarte
quarter
quartern
quarters
quartes
quartet
quartets
quartic
quartics
quartile
quarto
quartos
quarts
quartz
quartzes
quasar
quasars
quash
quashed
quasher
quashers
quashes
quashing
quasi
quass
quasses
quassia
quassias
quassin
quassins
quate
quatorze
quatrain
quatre
quatres
quaver
quavered
quaverer
quavers
quavery
quay
quayage
quayages
quaylike
quays
quayside
quean
queans
queasier
queasily
queasy
queazier
queazy
queen
queendom
queened
queening
queenly
queens
queer
queered
queerer
queerest
queering
queerish
queerly
queers
quell
quelled
queller
quellers
quelling
quells
quench
quenched
quencher
quenches
quenelle
quercine
querida
queridas
queried
querier
queriers
queries
querist
querists
quern
querns
query
querying
quest
quested
quester
questers
questing
question
questor
questors
quests
quetzal
quetzals
queue
queued
queueing
queuer
queuers
queues
queuing
quey
queys
quezal
quezales
quezals
quibble
quibbled
quibbler
quibbles
quiche
quiches
quick
quicken
quickens
quicker
quickest
quickie
quickies
quickly
quicks
quickset
quid
quiddity
quidnunc
quids
quiet
quieted
quieten
quietens
quieter
quieters
quietest
quieting
quietism
quietist
quietly
quiets
quietude
quietus
quiff
quiffs
quill
quillai
quillaia
quillais
quillaja
quilled
quillet
quillets
quilling
quills
quilt
quilted
quilter
quilters
quilting
quilts
quin
quinary
quinate
quince
quinces
quincunx
quinela
quinelas
quinella
quinic
quiniela
quinin
quinina
quininas
quinine
quinines
quinins
quinnat
quinnats
quinoa
quinoas
quinoid
quinoids
quinol
quinolin
quinols
quinone
quinones
quins
quinsies
quinsy
quint
quinta
quintain
quintal
quintals
quintan
quintans
quintar
quintars
quintas
quinte
quintes
quintet
quintets
quintic
quintics
quintile
quintin
quintins
quints
quip
quipped
quipper
quippers
quipping
quippish
quippu
quippus
quips
quipster
quipu
quipus
quire
quired
quires
quiring
quirk
quirked
quirkier
quirkily
quirking
quirkish
quirks
quirky
quirt
quirted
quirting
quirts
quisling
quit
quitch
quitches
quite
quitrent
quits
quitted
quitter
quitters
quitting
quittor
quittors
quiver
quivered
quiverer
quivers
quivery
quixote
quixotes
quixotic
quixotry
quiz
quizzed
quizzer
quizzers
quizzes
quizzing
quod
quods
quohog
quohogs
quoin
quoined
quoining
quoins
quoit
quoited
quoiting
quoits
quokka
quokkas
quomodo
quomodos
quondam
quorum
quorums
quota
quotable
quotably
quotas
quote
quoted
quoter
quoters
quotes
quoth
quotha
quotient
quoting
qursh
qurshes
qurush
qurushes
qwerty
qwertys
rabat
rabato
rabatos
rabats
rabbet
rabbeted
rabbets
rabbi
rabbies
rabbin
rabbinic
rabbins
rabbis
rabbit
rabbited
rabbiter
rabbitry
rabbits
rabbity
rabble
rabbled
rabbler
rabblers
rabbles
rabbling
rabboni
rabbonis
rabic
rabid
rabidity
rabidly
rabies
rabietic
raccoon
raccoons
race
raced
racemate
raceme
racemed
racemes
racemic
racemism
racemize
racemoid
racemose
racemous
racer
racers
races
raceway
raceways
rachet
rachets
rachial
rachides
rachilla
rachis
rachises
rachitic
rachitis
racial
racially
racier
raciest
racily
raciness
racing
racings
racism
racisms
racist
racists
rack
racked
racker
rackers
racket
racketed
rackets
rackety
rackful
rackfuls
racking
rackle
racks
rackwork
raclette
racon
racons
racoon
racoons
racquet
racquets
racy
rad
radar
radars
radded
radding
raddle
raddled
raddles
raddling
radiable
radial
radiale
radialia
radially
radials
radian
radiance
radiancy
radians
radiant
radiants
radiate
radiated
radiates
radiator
radical
radicals
radicand
radicate
radicel
radicels
radices
radicle
radicles
radii
radio
radioed
radioing
radioman
radiomen
radios
radish
radishes
radium
radiums
radius
radiuses
radix
radixes
radome
radomes
radon
radons
rads
radula
radulae
radular
radulas
radwaste
raff
raffia
raffias
raffish
raffle
raffled
raffler
rafflers
raffles
raffling
raffs
raft
rafted
rafter
raftered
rafters
rafting
rafts
raftsman
raftsmen
rag
raga
ragas
ragbag
ragbags
rage
raged
ragee
ragees
rages
ragged
raggeder
raggedly
raggedy
raggee
raggees
raggies
ragging
raggle
raggles
raggy
ragi
raging
ragingly
ragis
raglan
raglans
ragman
ragmen
ragout
ragouted
ragouts
rags
ragtag
ragtags
ragtime
ragtimes
ragtop
ragtops
ragweed
ragweeds
ragwort
ragworts
rah
raia
raias
raid
raided
raider
raiders
raiding
raids
rail
railbird
railbus
railcar
railcars
railed
railer
railers
railhead
railing
railings
raillery
railroad
rails
railway
railways
raiment
raiments
rain
rainband
rainbird
rainbow
rainbows
raincoat
raindrop
rained
rainfall
rainier
rainiest
rainily
raining
rainless
rainout
rainouts
rains
rainwash
rainwear
rainy
raisable
raise
raised
raiser
raisers
raises
raisin
raising
raisings
raisins
raisiny
raisonne
raj
raja
rajah
rajahs
rajas
rajes
rake
raked
rakee
rakees
rakehell
rakeoff
rakeoffs
raker
rakers
rakes
raki
raking
rakis
rakish
rakishly
rale
rales
rallied
rallier
ralliers
rallies
ralline
rally
rallye
rallyes
rallying
rallyist
ralph
ralphed
ralphing
ralphs
ram
ramate
ramble
rambled
rambler
ramblers
rambles
rambling
rambutan
ramee
ramees
ramekin
ramekins
ramenta
ramentum
ramequin
ramet
ramets
rami
ramie
ramies
ramified
ramifies
ramiform
ramify
ramilie
ramilies
ramillie
ramjet
ramjets
rammed
rammer
rammers
rammier
rammiest
ramming
rammish
rammy
ramose
ramosely
ramosity
ramous
ramp
rampage
rampaged
rampager
rampages
rampancy
rampant
rampart
ramparts
ramped
rampike
rampikes
ramping
rampion
rampions
rampole
rampoles
ramps
ramrod
ramrods
rams
ramshorn
ramson
ramsons
ramtil
ramtils
ramulose
ramulous
ramus
ran
rance
rances
ranch
ranched
rancher
ranchero
ranchers
ranches
ranching
ranchman
ranchmen
rancho
ranchos
rancid
rancidly
rancor
rancored
rancors
rancour
rancours
rand
randan
randans
randier
randies
randiest
random
randomly
randoms
rands
randy
ranee
ranees
rang
range
ranged
ranger
rangers
ranges
rangier
rangiest
ranging
rangy
rani
ranid
ranids
ranis
rank
ranked
ranker
rankers
rankest
ranking
rankings
rankish
rankle
rankled
rankles
rankling
rankly
rankness
ranks
ranpike
ranpikes
ransack
ransacks
ransom
ransomed
ransomer
ransoms
rant
ranted
ranter
ranters
ranting
rants
ranula
ranulas
rap
rapacity
rape
raped
raper
rapers
rapes
rapeseed
raphae
raphe
raphes
raphia
raphias
raphide
raphides
raphis
rapid
rapider
rapidest
rapidity
rapidly
rapids
rapier
rapiered
rapiers
rapine
rapines
raping
rapini
rapist
rapists
rapparee
rapped
rappee
rappees
rappel
rappeled
rappels
rappen
rapper
rappers
rapping
rappini
rapport
rapports
raps
rapt
raptly
raptness
raptor
raptors
rapture
raptured
raptures
rare
rarebit
rarebits
rared
rarefied
rarefier
rarefies
rarefy
rarely
rareness
rarer
rareripe
rares
rarest
rarified
rarifies
rarify
raring
rarities
rarity
ras
rasbora
rasboras
rascal
rascally
rascals
rase
rased
raser
rasers
rases
rash
rasher
rashers
rashes
rashest
rashlike
rashly
rashness
rasing
rasorial
rasp
rasped
rasper
raspers
raspier
raspiest
rasping
raspish
rasps
raspy
rassle
rassled
rassles
rassling
raster
rasters
rasure
rasures
rat
ratable
ratably
ratafee
ratafees
ratafia
ratafias
ratal
ratals
ratan
ratanies
ratans
ratany
rataplan
ratatat
ratatats
ratbag
ratbags
ratch
ratches
ratchet
ratchets
rate
rateable
rateably
rated
ratel
ratels
rater
raters
rates
ratfink
ratfinks
ratfish
rath
rathe
rather
rathole
ratholes
raticide
ratified
ratifier
ratifies
ratify
ratine
ratines
rating
ratings
ratio
ration
rational
rationed
rations
ratios
ratite
ratites
ratlike
ratlin
ratline
ratlines
ratlins
rato
ratoon
ratooned
ratooner
ratoons
ratos
rats
ratsbane
rattail
rattails
rattan
rattans
ratted
ratteen
ratteens
ratten
rattened
rattener
rattens
ratter
ratters
rattier
rattiest
ratting
rattish
rattle
rattled
rattler
rattlers
rattles
rattling
rattly
ratton
rattons
rattoon
rattoons
rattrap
rattraps
ratty
raucity
raucous
raunch
raunches
raunchy
ravage
ravaged
ravager
ravagers
ravages
ravaging
rave
raved
ravel
raveled
raveler
ravelers
ravelin
raveling
ravelins
ravelled
raveller
ravelly
ravels
raven
ravened
ravener
raveners
ravening
ravenous
ravens
raver
ravers
raves
ravigote
ravin
ravine
ravined
ravines
raving
ravingly
ravings
ravining
ravins
ravioli
raviolis
ravish
ravished
ravisher
ravishes
raw
rawboned
rawer
rawest
rawhide
rawhided
rawhides
rawin
rawins
rawish
rawly
rawness
raws
rax
raxed
raxes
raxing
ray
raya
rayah
rayahs
rayas
rayed
raygrass
raying
rayless
raylike
rayon
rayons
rays
raze
razed
razee
razeed
razeeing
razees
razer
razers
razes
razing
razor
razored
razoring
razors
razz
razzed
razzes
razzing
re
reabsorb
reaccede
reaccent
reaccept
reaccuse
reach
reached
reacher
reachers
reaches
reaching
react
reactant
reacted
reacting
reaction
reactive
reactor
reactors
reacts
read
readable
readably
readapt
readapts
readd
readded
readdict
readding
readds
reader
readerly
readers
readied
readier
readies
readiest
readily
reading
readings
readjust
readmit
readmits
readopt
readopts
readorn
readorns
readout
readouts
reads
ready
readying
reaffirm
reaffix
reagent
reagents
reagin
reaginic
reagins
real
realer
reales
realest
realgar
realgars
realia
realign
realigns
realise
realised
realiser
realises
realism
realisms
realist
realists
reality
realize
realized
realizer
realizes
reallot
reallots
really
realm
realms
realness
reals
realter
realters
realties
realty
ream
reamed
reamer
reamers
reaming
reams
reannex
reanoint
reap
reapable
reaped
reaper
reapers
reaphook
reaping
reappear
reapply
reaps
rear
reared
rearer
rearers
reargue
reargued
reargues
rearing
rearm
rearmed
rearmice
rearming
rearmost
rearms
rearouse
rearrest
rears
rearward
reascend
reascent
reason
reasoned
reasoner
reasons
reassail
reassert
reassess
reassign
reassort
reassume
reassure
reata
reatas
reattach
reattack
reattain
reavail
reavails
reave
reaved
reaver
reavers
reaves
reaving
reavow
reavowed
reavows
reawake
reawaked
reawaken
reawakes
reawoke
reawoken
reb
rebait
rebaited
rebaits
rebar
rebars
rebate
rebated
rebater
rebaters
rebates
rebating
rebato
rebatos
rebbe
rebbes
rebec
rebeck
rebecks
rebecs
rebegan
rebegin
rebegins
rebegun
rebel
rebeldom
rebelled
rebels
rebid
rebidden
rebids
rebill
rebilled
rebills
rebind
rebinds
rebirth
rebirths
reblend
reblends
rebloom
reblooms
reboant
reboard
reboards
rebodied
rebodies
rebody
reboil
reboiled
reboils
rebook
rebooked
rebooks
reboot
rebooted
reboots
rebop
rebops
rebore
rebored
rebores
reboring
reborn
rebottle
rebought
rebound
rebounds
rebozo
rebozos
rebranch
rebred
rebreed
rebreeds
rebs
rebuff
rebuffed
rebuffs
rebuild
rebuilds
rebuilt
rebuke
rebuked
rebuker
rebukers
rebukes
rebuking
reburial
reburied
reburies
rebury
rebus
rebuses
rebut
rebuts
rebuttal
rebutted
rebutter
rebutton
rebuy
rebuying
rebuys
rec
recall
recalled
recaller
recalls
recamier
recane
recaned
recanes
recaning
recant
recanted
recanter
recants
recap
recapped
recaps
recarry
recast
recasts
recce
recces
recede
receded
recedes
receding
receipt
receipts
receive
received
receiver
receives
recency
recent
recenter
recently
recept
receptor
recepts
recess
recessed
recesses
rechange
recharge
rechart
recharts
recheat
recheats
recheck
rechecks
rechew
rechewed
rechews
rechoose
rechose
rechosen
recipe
recipes
recircle
recision
recital
recitals
recite
recited
reciter
reciters
recites
reciting
reck
recked
recking
reckless
reckon
reckoned
reckoner
reckons
recks
reclad
reclaim
reclaims
reclame
reclames
reclasp
reclasps
reclean
recleans
recline
reclined
recliner
reclines
reclothe
recluse
recluses
recoal
recoaled
recoals
recock
recocked
recocks
recode
recoded
recodes
recodify
recoding
recoil
recoiled
recoiler
recoils
recoin
recoined
recoins
recolor
recolors
recomb
recombed
recombs
recommit
recon
recons
reconvey
recook
recooked
recooks
recopied
recopies
recopy
record
recorded
recorder
records
recork
recorked
recorks
recount
recounts
recoup
recoupe
recouped
recouple
recoups
recourse
recover
recovers
recovery
recrate
recrated
recrates
recreant
recreate
recross
recrown
recrowns
recruit
recruits
recs
recta
rectal
rectally
recti
rectify
recto
rector
rectors
rectory
rectos
rectrix
rectum
rectums
rectus
recur
recurred
recurs
recurve
recurved
recurves
recusal
recusals
recusant
recuse
recused
recuses
recusing
recut
recuts
recycle
recycled
recycler
recycles
red
redact
redacted
redactor
redacts
redamage
redan
redans
redargue
redate
redated
redates
redating
redbait
redbaits
redbay
redbays
redbird
redbirds
redbone
redbones
redbrick
redbud
redbuds
redbug
redbugs
redcap
redcaps
redcoat
redcoats
redd
redded
redden
reddened
reddens
redder
redders
reddest
redding
reddish
reddle
reddled
reddles
reddling
redds
rede
redear
redears
redecide
reded
redeem
redeemed
redeemer
redeems
redefeat
redefect
redefied
redefies
redefine
redefy
redemand
redenied
redenies
redeny
redeploy
redes
redesign
redeye
redeyes
redfin
redfins
redfish
redhead
redheads
redhorse
redia
rediae
redial
redialed
redials
redias
redid
redigest
reding
redip
redipped
redips
redipt
redirect
redivide
redleg
redlegs
redline
redlined
redlines
redly
redneck
rednecks
redness
redo
redock
redocked
redocks
redoes
redoing
redolent
redon
redone
redonned
redons
redos
redouble
redoubt
redoubts
redound
redounds
redout
redouts
redowa
redowas
redox
redoxes
redpoll
redpolls
redraft
redrafts
redraw
redrawer
redrawn
redraws
redream
redreams
redreamt
redress
redrew
redried
redries
redrill
redrills
redrive
redriven
redrives
redroot
redroots
redrove
redry
redrying
reds
redshank
redshift
redshirt
redskin
redskins
redstart
redtail
redtails
redtop
redtops
redub
redubbed
redubs
reduce
reduced
reducer
reducers
reduces
reducing
reductor
reduviid
redux
redware
redwares
redwing
redwings
redwood
redwoods
redye
redyed
redyeing
redyes
ree
reearn
reearned
reearns
reechier
reecho
reechoed
reechoes
reechy
reed
reedbird
reedbuck
reeded
reedier
reediest
reedify
reedily
reeding
reedings
reedit
reedited
reedits
reedlike
reedling
reedman
reedmen
reeds
reedy
reef
reefable
reefed
reefer
reefers
reefier
reefiest
reefing
reefs
reefy
reeject
reejects
reek
reeked
reeker
reekers
reekier
reekiest
reeking
reeks
reeky
reel
reelable
reelect
reelects
reeled
reeler
reelers
reeling
reels
reembark
reembody
reemerge
reemit
reemits
reemploy
reenact
reenacts
reendow
reendows
reengage
reenjoy
reenjoys
reenlist
reenroll
reenter
reenters
reentry
reequip
reequips
reerect
reerects
rees
reest
reested
reesting
reests
reeve
reeved
reeves
reeving
reevoke
reevoked
reevokes
reexpel
reexpels
reexport
reexpose
ref
reface
refaced
refaces
refacing
refall
refallen
refalls
refasten
refect
refected
refects
refed
refeed
refeeds
refeel
refeels
refel
refell
refelled
refels
refelt
refence
refenced
refences
refer
referee
refereed
referees
referent
referral
referred
referrer
refers
reffed
reffing
refight
refights
refigure
refile
refiled
refiles
refiling
refill
refilled
refills
refilm
refilmed
refilms
refilter
refind
refinds
refine
refined
refiner
refiners
refinery
refines
refining
refinish
refire
refired
refires
refiring
refit
refits
refitted
refix
refixed
refixes
refixing
reflate
reflated
reflates
reflect
reflects
reflet
reflets
reflew
reflex
reflexed
reflexes
reflexly
reflies
refloat
refloats
reflood
refloods
reflow
reflowed
reflower
reflown
reflows
refluent
reflux
refluxed
refluxes
refly
reflying
refocus
refold
refolded
refolds
reforest
reforge
reforged
reforges
reform
reformat
reformed
reformer
reforms
refought
refound
refounds
refract
refracts
refrain
refrains
reframe
reframed
reframes
refreeze
refresh
refried
refries
refront
refronts
refroze
refrozen
refry
refrying
refs
reft
refuel
refueled
refuels
refuge
refuged
refugee
refugees
refuges
refugia
refuging
refugium
refund
refunded
refunder
refunds
refusal
refusals
refuse
refused
refuser
refusers
refuses
refusing
refusnik
refutal
refutals
refute
refuted
refuter
refuters
refutes
refuting
reg
regain
regained
regainer
regains
regal
regale
regaled
regaler
regalers
regales
regalia
regaling
regality
regally
regard
regarded
regards
regather
regatta
regattas
regauge
regauged
regauges
regave
regear
regeared
regears
regelate
regency
regent
regental
regents
reges
reggae
reggaes
regicide
regild
regilded
regilds
regilt
regime
regimen
regimens
regiment
regimes
regina
reginae
reginal
reginas
region
regional
regions
register
registry
regius
regive
regiven
regives
regiving
reglaze
reglazed
reglazes
reglet
reglets
regloss
reglow
reglowed
reglows
reglue
reglued
reglues
regluing
regma
regmata
regna
regnal
regnancy
regnant
regnum
regolith
regorge
regorged
regorges
regosol
regosols
regrade
regraded
regrades
regraft
regrafts
regrant
regrants
regrate
regrated
regrates
regreen
regreens
regreet
regreets
regress
regret
regrets
regrew
regrind
regrinds
regroom
regrooms
regroove
reground
regroup
regroups
regrow
regrown
regrows
regrowth
regs
regular
regulars
regulate
reguli
reguline
regulus
rehab
rehabbed
rehabber
rehabs
rehammer
rehandle
rehang
rehanged
rehangs
reharden
rehash
rehashed
rehashes
rehear
reheard
rehears
rehearse
reheat
reheated
reheater
reheats
reheel
reheeled
reheels
rehem
rehemmed
rehems
rehinge
rehinged
rehinges
rehire
rehired
rehires
rehiring
rehoboam
rehouse
rehoused
rehouses
rehung
rei
reif
reified
reifier
reifiers
reifies
reifs
reify
reifying
reign
reigned
reigning
reignite
reigns
reimage
reimaged
reimages
reimport
reimpose
rein
reincite
reincur
reincurs
reindeer
reindex
reindict
reinduce
reinduct
reined
reinfect
reinform
reinfuse
reining
reinject
reinjure
reinjury
reink
reinked
reinking
reinks
reinless
reins
reinsert
reinsman
reinsmen
reinsure
reinter
reinters
reinvade
reinvent
reinvest
reinvite
reinvoke
reis
reissue
reissued
reissuer
reissues
reitbok
reitboks
reive
reived
reiver
reivers
reives
reiving
rejacket
reject
rejected
rejectee
rejecter
rejector
rejects
rejigger
rejoice
rejoiced
rejoicer
rejoices
rejoin
rejoined
rejoins
rejudge
rejudged
rejudges
rejuggle
rekey
rekeyed
rekeying
rekeys
rekindle
reknit
reknits
relabel
relabels
relace
relaced
relaces
relacing
relaid
relapse
relapsed
relapser
relapses
relate
related
relater
relaters
relates
relating
relation
relative
relator
relators
relaunch
relax
relaxant
relaxed
relaxer
relaxers
relaxes
relaxin
relaxing
relaxins
relay
relayed
relaying
relays
relearn
relearns
relearnt
release
released
releaser
releases
relegate
relend
relends
relent
relented
relents
relet
relets
reletter
relevant
releve
releves
reliable
reliably
reliance
reliant
relic
relics
relict
relicts
relied
relief
reliefs
relier
reliers
relies
relieve
relieved
reliever
relieves
relievo
relievos
relight
relights
religion
reline
relined
relines
relining
relink
relinked
relinks
relique
reliques
relish
relished
relishes
relist
relisted
relists
relit
relive
relived
relives
reliving
reload
reloaded
reloader
reloads
reloan
reloaned
reloans
relocate
relock
relocked
relocks
relook
relooked
relooks
relucent
reluct
relucted
relucts
relume
relumed
relumes
relumine
reluming
rely
relying
rem
remade
remail
remailed
remails
remain
remained
remains
remake
remaker
remakers
remakes
remaking
reman
remand
remanded
remands
remanent
remanned
remans
remap
remapped
remaps
remark
remarked
remarker
remarket
remarks
remarque
remarry
remaster
rematch
remate
remated
remates
remating
remedial
remedied
remedies
remedy
remeet
remeets
remelt
remelted
remelts
remember
remend
remended
remends
remerge
remerged
remerges
remet
remex
remiges
remigial
remind
reminded
reminder
reminds
remint
reminted
remints
remise
remised
remises
remising
remiss
remissly
remit
remits
remittal
remitted
remitter
remittor
remix
remixed
remixes
remixing
remixt
remnant
remnants
remodel
remodels
remodify
remolade
remold
remolded
remolds
remora
remoras
remorid
remorse
remorses
remote
remotely
remoter
remotes
remotest
remotion
remount
remounts
removal
removals
remove
removed
remover
removers
removes
removing
rems
remuda
remudas
renail
renailed
renails
renal
rename
renamed
renames
renaming
renature
rend
rended
render
rendered
renderer
renders
rendible
rending
rends
rendzina
renegade
renegado
renege
reneged
reneger
renegers
reneges
reneging
renest
renested
renests
renew
renewal
renewals
renewed
renewer
renewers
renewing
renews
reniform
renig
renigged
renigs
renin
renins
renitent
renminbi
rennase
rennases
rennet
rennets
rennin
rennins
renogram
renotify
renounce
renovate
renown
renowned
renowns
rent
rentable
rental
rentals
rente
rented
renter
renters
rentes
rentier
rentiers
renting
rents
renumber
renvoi
renvois
reobject
reobtain
reoccupy
reoccur
reoccurs
reoffer
reoffers
reoil
reoiled
reoiling
reoils
reopen
reopened
reopens
reoppose
reordain
reorder
reorders
reorient
reoutfit
reovirus
rep
repacify
repack
repacked
repacks
repaid
repaint
repaints
repair
repaired
repairer
repairs
repand
repandly
repanel
repanels
repaper
repapers
repark
reparked
reparks
repartee
repass
repassed
repasses
repast
repasted
repasts
repatch
repave
repaved
repaves
repaving
repay
repaying
repays
repeal
repealed
repealer
repeals
repeat
repeated
repeater
repeats
repeg
repegged
repegs
repel
repelled
repeller
repels
repent
repented
repenter
repents
repeople
reperk
reperked
reperks
repetend
rephrase
repin
repine
repined
repiner
repiners
repines
repining
repinned
repins
replace
replaced
replacer
replaces
replan
replans
replant
replants
replate
replated
replates
replay
replayed
replays
replead
repleads
repled
repledge
replete
replevin
replevy
replica
replicas
replicon
replied
replier
repliers
replies
replot
replots
replumb
replumbs
replunge
reply
replying
repo
repolish
repoll
repolled
repolls
report
reported
reporter
reports
repos
reposal
reposals
repose
reposed
reposer
reposers
reposes
reposing
reposit
reposits
repot
repots
repotted
repour
repoured
repours
repousse
repower
repowers
repp
repped
repps
repress
reprice
repriced
reprices
reprieve
reprint
reprints
reprisal
reprise
reprised
reprises
repro
reproach
reprobe
reprobed
reprobes
reproof
reproofs
repros
reproval
reprove
reproved
reprover
reproves
reps
reptant
reptile
reptiles
reptilia
republic
repugn
repugned
repugns
repulse
repulsed
repulser
repulses
repump
repumped
repumps
repurify
repursue
repute
reputed
reputes
reputing
request
requests
requiem
requiems
requin
requins
require
required
requirer
requires
requital
requite
requited
requiter
requites
rerack
reracked
reracks
reraise
reraised
reraises
reran
reread
rereads
rerecord
reredos
reremice
reremind
rerepeat
rereview
rereward
rerig
rerigged
rerigs
rerise
rerisen
rerises
rerising
reroll
rerolled
reroller
rerolls
reroof
reroofed
reroofs
rerose
reroute
rerouted
reroutes
rerun
reruns
res
resaddle
resaid
resail
resailed
resails
resale
resales
resalute
resample
resaw
resawed
resawing
resawn
resaws
resay
resaying
resays
rescale
rescaled
rescales
reschool
rescind
rescinds
rescore
rescored
rescores
rescreen
rescript
rescue
rescued
rescuer
rescuers
rescues
rescuing
resculpt
reseal
resealed
reseals
research
reseason
reseat
reseated
reseats
reseau
reseaus
reseaux
resect
resected
resects
resecure
reseda
resedas
resee
reseed
reseeded
reseeds
reseeing
reseek
reseeks
reseen
resees
reseize
reseized
reseizes
resell
reseller
resells
resemble
resend
resends
resent
resented
resents
reserve
reserved
reserver
reserves
reset
resets
resetter
resettle
resew
resewed
resewing
resewn
resews
resh
reshape
reshaped
reshaper
reshapes
reshave
reshaved
reshaven
reshaves
reshes
reshine
reshined
reshines
reship
reships
reshod
reshoe
reshoes
reshone
reshoot
reshoots
reshot
reshow
reshowed
reshown
reshows
resid
reside
resided
resident
resider
residers
resides
residing
resids
residua
residual
residue
residues
residuum
resift
resifted
resifts
resight
resights
resign
resigned
resigner
resigns
resile
resiled
resiles
resiling
resilver
resin
resinate
resined
resinify
resining
resinoid
resinous
resins
resiny
resist
resisted
resister
resistor
resists
resite
resited
resites
resiting
resize
resized
resizes
resizing
resketch
reslate
reslated
reslates
resmelt
resmelts
resmooth
resoak
resoaked
resoaks
resod
resodded
resods
resojet
resojets
resold
resolder
resole
resoled
resoles
resoling
resolute
resolve
resolved
resolver
resolves
resonant
resonate
resorb
resorbed
resorbs
resorcin
resort
resorted
resorter
resorts
resought
resound
resounds
resource
resow
resowed
resowing
resown
resows
respace
respaced
respaces
respade
respaded
respades
respeak
respeaks
respect
respects
respell
respells
respelt
respire
respired
respires
respite
respited
respites
resplice
resplit
resplits
respoke
respoken
respond
responds
responsa
response
respot
respots
resprang
respray
resprays
respread
respring
resprout
resprung
rest
restack
restacks
restaff
restaffs
restage
restaged
restages
restamp
restamps
restart
restarts
restate
restated
restates
rested
rester
resters
restful
resting
restitch
restive
restless
restock
restocks
restoke
restoked
restokes
restoral
restore
restored
restorer
restores
restrain
restress
restrict
restrike
restring
restrive
restroom
restrove
restruck
restrung
rests
restudy
restuff
restuffs
restyle
restyled
restyles
resubmit
result
resulted
results
resume
resumed
resumer
resumers
resumes
resuming
resummon
resupine
resupply
resurge
resurged
resurges
resurvey
ret
retable
retables
retack
retacked
retackle
retacks
retag
retagged
retags
retail
retailed
retailer
retailor
retails
retain
retained
retainer
retains
retake
retaken
retaker
retakers
retakes
retaking
retape
retaped
retapes
retaping
retard
retarded
retarder
retards
retarget
retaste
retasted
retastes
retaught
retax
retaxed
retaxes
retaxing
retch
retched
retches
retching
rete
reteach
reteam
reteamed
reteams
retear
retears
retell
retells
retem
retemper
retems
retene
retenes
retest
retested
retests
rethink
rethinks
rethread
retia
retial
retiarii
retiary
reticent
reticle
reticles
reticula
reticule
retie
retied
reties
retiform
retile
retiled
retiles
retiling
retime
retimed
retimes
retiming
retina
retinae
retinal
retinals
retinas
retine
retinene
retines
retinite
retinoid
retinol
retinols
retint
retinted
retints
retinue
retinued
retinues
retinula
retirant
retire
retired
retiree
retirees
retirer
retirers
retires
retiring
retitle
retitled
retitles
retold
retook
retool
retooled
retools
retore
retorn
retort
retorted
retorter
retorts
retouch
retrace
retraced
retraces
retrack
retracks
retract
retracts
retrain
retrains
retral
retrally
retread
retreads
retreat
retreats
retrench
retrial
retrials
retried
retries
retrieve
retrim
retrims
retro
retroact
retrofit
retrorse
retros
retry
retrying
rets
retsina
retsinas
retted
retting
retune
retuned
retunes
retuning
return
returned
returnee
returner
returns
retuse
retwist
retwists
retying
retype
retyped
retypes
retyping
reunify
reunion
reunions
reunite
reunited
reuniter
reunites
reusable
reuse
reused
reuses
reusing
reutter
reutters
rev
revalue
revalued
revalues
revamp
revamped
revamper
revamps
revanche
reveal
revealed
revealer
reveals
revehent
reveille
revel
reveled
reveler
revelers
reveling
revelled
reveller
revelry
revels
revenant
revenge
revenged
revenger
revenges
revenual
revenue
revenued
revenuer
revenues
reverb
reverbed
reverbs
revere
revered
reverend
reverent
reverer
reverers
reveres
reverie
reveries
reverify
revering
revers
reversal
reverse
reversed
reverser
reverses
reverso
reversos
revert
reverted
reverter
reverts
revery
revest
revested
revests
revet
revets
revetted
review
reviewal
reviewed
reviewer
reviews
revile
reviled
reviler
revilers
reviles
reviling
revisal
revisals
revise
revised
reviser
revisers
revises
revising
revision
revisit
revisits
revisor
revisors
revisory
revival
revivals
revive
revived
reviver
revivers
revives
revivify
reviving
revoice
revoiced
revoices
revoke
revoked
revoker
revokers
revokes
revoking
revolt
revolted
revolter
revolts
revolute
revolve
revolved
revolver
revolves
revote
revoted
revotes
revoting
revs
revue
revues
revuist
revuists
revulsed
revved
revving
rewake
rewaked
rewaken
rewakens
rewakes
rewaking
rewan
reward
rewarded
rewarder
rewards
rewarm
rewarmed
rewarms
rewash
rewashed
rewashes
rewax
rewaxed
rewaxes
rewaxing
reweave
reweaved
reweaves
rewed
rewedded
reweds
reweigh
reweighs
reweld
rewelded
rewelds
rewet
rewets
rewetted
rewiden
rewidens
rewin
rewind
rewinded
rewinder
rewinds
rewins
rewire
rewired
rewires
rewiring
rewoke
rewoken
rewon
reword
reworded
rewords
rework
reworked
reworks
rewound
rewove
rewoven
rewrap
rewraps
rewrapt
rewrite
rewriter
rewrites
rewrote
rex
rexes
reynard
reynards
rezone
rezoned
rezones
rezoning
rhabdom
rhabdome
rhabdoms
rhachis
rhamnose
rhamnus
rhaphae
rhaphe
rhaphes
rhapsode
rhapsody
rhatany
rhea
rheas
rhebok
rheboks
rhematic
rhenium
rheniums
rheobase
rheology
rheophil
rheostat
rhesus
rhesuses
rhetor
rhetoric
rhetors
rheum
rheumic
rheumier
rheums
rheumy
rhinal
rhinitis
rhino
rhinos
rhizobia
rhizoid
rhizoids
rhizoma
rhizome
rhizomes
rhizomic
rhizopi
rhizopod
rhizopus
rho
rhodamin
rhodic
rhodium
rhodiums
rhodora
rhodoras
rhomb
rhombi
rhombic
rhomboid
rhombs
rhombus
rhonchal
rhonchi
rhonchus
rhos
rhubarb
rhubarbs
rhumb
rhumba
rhumbaed
rhumbas
rhumbs
rhus
rhuses
rhyme
rhymed
rhymer
rhymers
rhymes
rhyming
rhyolite
rhyta
rhythm
rhythmic
rhythms
rhyton
rhytons
ria
rial
rials
rialto
rialtos
riant
riantly
rias
riata
riatas
rib
ribald
ribaldly
ribaldry
ribalds
riband
ribands
ribband
ribbands
ribbed
ribber
ribbers
ribbier
ribbiest
ribbing
ribbings
ribbon
ribboned
ribbons
ribbony
ribby
ribes
ribgrass
ribier
ribiers
ribless
riblet
riblets
riblike
ribose
riboses
ribosome
ribs
ribwort
ribworts
rice
ricebird
riced
ricer
ricercar
ricers
rices
rich
richen
richened
richens
richer
riches
richest
richly
richness
richweed
ricin
ricing
ricins
ricinus
rick
ricked
rickets
rickety
rickey
rickeys
ricking
rickrack
ricks
ricksha
rickshas
rickshaw
ricochet
ricotta
ricottas
ricrac
ricracs
rictal
rictus
rictuses
rid
ridable
riddance
ridded
ridden
ridder
ridders
ridding
riddle
riddled
riddler
riddlers
riddles
riddling
ride
rideable
rident
rider
riders
rides
ridge
ridged
ridgel
ridgels
ridges
ridgier
ridgiest
ridgil
ridgils
ridging
ridgling
ridgy
ridicule
riding
ridings
ridley
ridleys
ridotto
ridottos
rids
riel
riels
riesling
riever
rievers
rif
rifampin
rife
rifely
rifeness
rifer
rifest
riff
riffed
riffing
riffle
riffled
riffler
rifflers
riffles
riffling
riffraff
riffs
rifle
rifled
rifleman
riflemen
rifler
riflers
riflery
rifles
rifling
riflings
rifs
rift
rifted
rifting
riftless
rifts
rig
rigadoon
rigatoni
rigaudon
rigged
rigger
riggers
rigging
riggings
right
righted
righter
righters
rightest
rightful
righties
righting
rightism
rightist
rightly
righto
rights
righty
rigid
rigidify
rigidity
rigidly
rigor
rigorism
rigorist
rigorous
rigors
rigour
rigours
rigs
rikisha
rikishas
rikshaw
rikshaws
rile
riled
riles
riley
rilievi
rilievo
riling
rill
rille
rilled
rilles
rillet
rillets
rilling
rills
rim
rime
rimed
rimer
rimers
rimes
rimester
rimfire
rimfires
rimier
rimiest
riminess
riming
rimland
rimlands
rimless
rimmed
rimmer
rimmers
rimming
rimose
rimosely
rimosity
rimous
rimple
rimpled
rimples
rimpling
rimrock
rimrocks
rims
rimy
rin
rind
rinded
rinds
ring
ringbark
ringbolt
ringbone
ringdove
ringed
ringent
ringer
ringers
ringgit
ringgits
ringhals
ringing
ringlet
ringlets
ringlike
ringneck
rings
ringside
ringtail
ringtaw
ringtaws
ringtoss
ringworm
rink
rinks
rinning
rins
rinsable
rinse
rinsed
rinser
rinsers
rinses
rinsible
rinsing
rinsings
rioja
riojas
riot
rioted
rioter
rioters
rioting
riotous
riots
rip
riparian
ripcord
ripcords
ripe
riped
ripely
ripen
ripened
ripener
ripeners
ripeness
ripening
ripens
riper
ripes
ripest
ripieni
ripieno
ripienos
riping
ripoff
ripoffs
ripost
riposte
riposted
ripostes
riposts
rippable
ripped
ripper
rippers
ripping
ripple
rippled
rippler
ripplers
ripples
ripplet
ripplets
ripplier
rippling
ripply
riprap
ripraps
rips
ripsaw
ripsaws
ripstop
ripstops
riptide
riptides
rise
risen
riser
risers
rises
rishi
rishis
risible
risibles
risibly
rising
risings
risk
risked
risker
riskers
riskier
riskiest
riskily
risking
riskless
risks
risky
risotto
risottos
risque
rissole
rissoles
risus
risuses
ritard
ritards
rite
rites
ritter
ritters
ritual
ritually
rituals
ritz
ritzes
ritzier
ritziest
ritzily
ritzy
rivage
rivages
rival
rivaled
rivaling
rivalled
rivalry
rivals
rive
rived
riven
river
riverbed
riverine
rivers
rives
rivet
riveted
riveter
riveters
riveting
rivets
rivetted
riviera
rivieras
riviere
rivieres
riving
rivulet
rivulets
rivulose
riyal
riyals
roach
roached
roaches
roaching
road
roadbed
roadbeds
roadeo
roadeos
roadie
roadies
roadkill
roadless
roads
roadshow
roadside
roadster
roadway
roadways
roadwork
roam
roamed
roamer
roamers
roaming
roams
roan
roans
roar
roared
roarer
roarers
roaring
roarings
roars
roast
roasted
roaster
roasters
roasting
roasts
rob
robalo
robalos
roband
robands
robbed
robber
robbers
robbery
robbin
robbing
robbins
robe
robed
robes
robin
robing
robins
roble
robles
roborant
robot
robotic
robotics
robotism
robotize
robotry
robots
robs
robust
robusta
robustas
robuster
robustly
roc
rocaille
rochet
rochets
rock
rockaby
rockabye
rockaway
rocked
rocker
rockers
rockery
rocket
rocketed
rocketer
rocketry
rockets
rockfall
rockfish
rockier
rockiest
rocking
rockless
rocklike
rockling
rockoon
rockoons
rockrose
rocks
rockweed
rockwork
rocky
rococo
rococos
rocs
rod
rodded
rodding
rode
rodent
rodents
rodeo
rodeoed
rodeoing
rodeos
rodless
rodlike
rodman
rodmen
rods
rodsman
rodsmen
roe
roebuck
roebucks
roentgen
roes
rogation
rogatory
roger
rogers
rogue
rogued
rogueing
roguery
rogues
roguing
roguish
roil
roiled
roilier
roiliest
roiling
roils
roily
roister
roisters
rolamite
role
roles
rolf
rolfed
rolfer
rolfers
rolfing
rolfs
roll
rollaway
rollback
rolled
roller
rollers
rollick
rollicks
rollicky
rolling
rollings
rollmop
rollmops
rollout
rollouts
rollover
rolls
rolltop
rollway
rollways
rom
romaine
romaines
roman
romance
romanced
romancer
romances
romanise
romanize
romano
romanos
romans
romantic
romaunt
romaunts
romeo
romeos
romp
romped
romper
rompers
romping
rompish
romps
roms
rondeau
rondeaux
rondel
rondelet
rondelle
rondels
rondo
rondos
rondure
rondures
ronion
ronions
ronnel
ronnels
rontgen
rontgens
ronyon
ronyons
rood
roods
roof
roofed
roofer
roofers
roofing
roofings
roofless
rooflike
roofline
roofs
rooftop
rooftops
rooftree
rook
rooked
rookery
rookie
rookier
rookies
rookiest
rooking
rooks
rooky
room
roomed
roomer
roomers
roomette
roomful
roomfuls
roomie
roomier
roomies
roomiest
roomily
rooming
roommate
rooms
roomy
roorbach
roorback
roose
roosed
rooser
roosers
rooses
roosing
roost
roosted
rooster
roosters
roosting
roosts
root
rootage
rootages
rooted
rooter
rooters
roothold
rootier
rootiest
rooting
rootless
rootlet
rootlets
rootlike
roots
rooty
ropable
rope
roped
ropelike
roper
roperies
ropers
ropery
ropes
ropewalk
ropeway
ropeways
ropey
ropier
ropiest
ropily
ropiness
roping
ropy
roque
roques
roquet
roqueted
roquets
rorqual
rorquals
rosaria
rosarian
rosaries
rosarium
rosary
roscoe
roscoes
rose
roseate
rosebay
rosebays
rosebud
rosebuds
rosebush
rosed
rosefish
roselike
roselle
roselles
rosemary
roseola
roseolar
roseolas
roseries
roseroot
rosery
roses
roseslug
roset
rosets
rosette
rosettes
rosewood
rosier
rosiest
rosily
rosin
rosined
rosiness
rosing
rosining
rosinol
rosinols
rosinous
rosins
rosiny
rosolio
rosolios
rostella
roster
rosters
rostra
rostral
rostrate
rostrum
rostrums
rosulate
rosy
rot
rota
rotaries
rotary
rotas
rotate
rotated
rotates
rotating
rotation
rotative
rotator
rotators
rotatory
rotch
rotche
rotches
rote
rotenone
rotes
rotgut
rotguts
roti
rotifer
rotifers
rotiform
rotis
rotl
rotls
roto
rotor
rotors
rotos
rototill
rots
rotte
rotted
rotten
rottener
rottenly
rotter
rotters
rottes
rotting
rotund
rotunda
rotundas
rotundly
roturier
rouble
roubles
rouche
rouches
roue
rouen
rouens
roues
rouge
rouged
rouges
rough
roughage
roughdry
roughed
roughen
roughens
rougher
roughers
roughest
roughhew
roughing
roughish
roughleg
roughly
roughs
rouging
rouille
rouilles
roulade
roulades
rouleau
rouleaus
rouleaux
roulette
round
rounded
roundel
roundels
rounder
rounders
roundest
rounding
roundish
roundlet
roundly
rounds
roundup
roundups
roup
rouped
roupet
roupier
roupiest
roupily
rouping
roups
roupy
rouse
roused
rouser
rousers
rouses
rousing
rousseau
roust
rousted
rouster
rousters
rousting
rousts
rout
route
routed
routeman
routemen
router
routers
routes
routeway
routh
rouths
routine
routines
routing
routs
roux
rove
roved
roven
rover
rovers
roves
roving
rovingly
rovings
row
rowable
rowan
rowans
rowboat
rowboats
rowdier
rowdies
rowdiest
rowdily
rowdy
rowdyish
rowdyism
rowed
rowel
roweled
roweling
rowelled
rowels
rowen
rowens
rower
rowers
rowing
rowings
rowlock
rowlocks
rows
rowth
rowths
royal
royalism
royalist
royally
royals
royalty
royster
roysters
rozzer
rozzers
ruana
ruanas
rub
rubaboo
rubaboos
rubace
rubaces
rubaiyat
rubasse
rubasses
rubato
rubatos
rubbaboo
rubbed
rubber
rubbered
rubbers
rubbery
rubbing
rubbings
rubbish
rubbishy
rubble
rubbled
rubbles
rubblier
rubbling
rubbly
rubdown
rubdowns
rube
rubella
rubellas
rubeola
rubeolar
rubeolas
rubes
rubicund
rubidic
rubidium
rubied
rubier
rubies
rubiest
rubigo
rubigos
rubious
ruble
rubles
ruboff
ruboffs
rubout
rubouts
rubric
rubrical
rubrics
rubs
rubus
ruby
rubying
rubylike
ruche
ruched
ruches
ruching
ruchings
ruck
rucked
rucking
ruckle
ruckled
ruckles
ruckling
rucks
rucksack
ruckus
ruckuses
ruction
ructions
ructious
rudd
rudder
rudders
ruddier
ruddiest
ruddily
ruddle
ruddled
ruddles
ruddling
ruddock
ruddocks
rudds
ruddy
rude
rudely
rudeness
ruder
ruderal
ruderals
rudesby
rudest
rudiment
rue
rued
rueful
ruefully
ruer
ruers
rues
ruff
ruffe
ruffed
ruffes
ruffian
ruffians
ruffing
ruffle
ruffled
ruffler
rufflers
ruffles
rufflier
rufflike
ruffling
ruffly
ruffs
rufiyaa
rufous
rug
ruga
rugae
rugal
rugate
rugbies
rugby
rugged
ruggeder
ruggedly
rugger
ruggers
rugging
ruglike
rugola
rugolas
rugosa
rugosas
rugose
rugosely
rugosity
rugous
rugs
rugulose
ruin
ruinable
ruinate
ruinated
ruinates
ruined
ruiner
ruiners
ruing
ruining
ruinous
ruins
rulable
rule
ruled
ruleless
ruler
rulers
rules
rulier
ruliest
ruling
rulings
ruly
rum
rumaki
rumakis
rumba
rumbaed
rumbaing
rumbas
rumble
rumbled
rumbler
rumblers
rumbles
rumbling
rumbly
rumen
rumens
rumina
ruminal
ruminant
ruminate
rummage
rummaged
rummager
rummages
rummer
rummers
rummest
rummier
rummies
rummiest
rummy
rumor
rumored
rumoring
rumors
rumour
rumoured
rumours
rump
rumple
rumpled
rumples
rumpless
rumplier
rumpling
rumply
rumps
rumpus
rumpuses
rums
run
runabout
runagate
runaway
runaways
runback
runbacks
rundle
rundles
rundlet
rundlets
rundown
rundowns
rune
runelike
runes
rung
rungless
rungs
runic
runkle
runkled
runkles
runkling
runless
runlet
runlets
runnel
runnels
runner
runners
runnier
runniest
running
runnings
runny
runoff
runoffs
runout
runouts
runover
runovers
runround
runs
runt
runtier
runtiest
runtish
runts
runty
runway
runways
rupee
rupees
rupiah
rupiahs
rupture
ruptured
ruptures
rural
ruralise
ruralism
ruralist
ruralite
rurality
ruralize
rurally
rurban
ruse
ruses
rush
rushed
rushee
rushees
rusher
rushers
rushes
rushier
rushiest
rushing
rushings
rushlike
rushy
rusine
rusk
rusks
russet
russets
russety
russify
rust
rustable
rusted
rustic
rustical
rusticly
rustics
rustier
rustiest
rustily
rusting
rustle
rustled
rustler
rustlers
rustles
rustless
rustling
rusts
rusty
rut
rutabaga
ruth
ruthenic
ruthful
ruthless
ruths
rutilant
rutile
rutiles
rutin
rutins
ruts
rutted
ruttier
ruttiest
ruttily
rutting
ruttish
rutty
rya
ryas
rye
ryegrass
ryes
ryke
ryked
rykes
ryking
rynd
rynds
ryokan
ryokans
ryot
ryots
sab
sabaton
sabatons
sabayon
sabayons
sabbat
sabbath
sabbaths
sabbatic
sabbats
sabbed
sabbing
sabe
sabed
sabeing
saber
sabered
sabering
sabers
sabes
sabin
sabine
sabines
sabins
sabir
sabirs
sable
sables
sabot
sabotage
saboteur
sabots
sabra
sabras
sabre
sabred
sabres
sabring
sabs
sabulose
sabulous
sac
sacaton
sacatons
sacbut
sacbuts
saccade
saccades
saccadic
saccate
saccular
saccule
saccules
sacculi
sacculus
sachem
sachemic
sachems
sachet
sacheted
sachets
sack
sackbut
sackbuts
sacked
sacker
sackers
sackful
sackfuls
sacking
sackings
sacklike
sacks
sacksful
saclike
sacque
sacques
sacra
sacral
sacrals
sacraria
sacred
sacredly
sacring
sacrings
sacrist
sacrists
sacristy
sacrum
sacrums
sacs
sad
sadden
saddened
saddens
sadder
saddest
saddhu
saddhus
saddle
saddled
saddler
saddlers
saddlery
saddles
saddling
sade
sades
sadhe
sadhes
sadhu
sadhus
sadi
sadiron
sadirons
sadis
sadism
sadisms
sadist
sadistic
sadists
sadly
sadness
sae
safari
safaried
safaris
safe
safely
safeness
safer
safes
safest
safetied
safeties
safety
saffron
saffrons
safranin
safrol
safrole
safroles
safrols
sag
saga
sagacity
sagaman
sagamen
sagamore
saganash
sagas
sagbut
sagbuts
sage
sagely
sageness
sager
sages
sagest
saggar
saggard
saggards
saggared
saggars
sagged
sagger
saggered
saggers
saggier
saggiest
sagging
saggy
sagier
sagiest
sagittal
sago
sagos
sags
saguaro
saguaros
sagum
sagy
sahib
sahibs
sahiwal
sahiwals
sahuaro
sahuaros
saice
saices
said
saids
saiga
saigas
sail
sailable
sailboat
sailed
sailer
sailers
sailfish
sailing
sailings
sailor
sailorly
sailors
sails
saimin
saimins
sain
sained
sainfoin
saining
sains
saint
saintdom
sainted
sainting
saintly
saints
saith
saithe
saiyid
saiyids
sajou
sajous
sake
saker
sakers
sakes
saki
sakis
sal
salaam
salaamed
salaams
salable
salably
salacity
salad
saladang
salads
salal
salals
salami
salamis
salariat
salaried
salaries
salary
salchow
salchows
sale
saleable
saleably
salep
saleps
saleroom
sales
salesman
salesmen
salic
salicin
salicine
salicins
salience
saliency
salient
salients
salified
salifies
salify
salina
salinas
saline
salines
salinity
salinize
saliva
salivary
salivas
salivate
sall
sallet
sallets
sallied
sallier
salliers
sallies
sallow
sallowed
sallower
sallowly
sallows
sallowy
sally
sallying
salmi
salmis
salmon
salmonid
salmons
salol
salols
salon
salons
saloon
saloons
saloop
saloops
salp
salpa
salpae
salpas
salpian
salpians
salpid
salpids
salpinx
salps
sals
salsa
salsas
salsify
salsilla
salt
saltant
saltbox
saltbush
salted
salter
saltern
salterns
salters
saltest
saltie
saltier
saltiers
salties
saltiest
saltily
saltine
saltines
salting
saltings
saltire
saltires
saltish
saltless
saltlike
saltness
saltpan
saltpans
salts
saltwork
saltwort
salty
saluki
salukis
salutary
salute
saluted
saluter
saluters
salutes
saluting
salvable
salvably
salvage
salvaged
salvagee
salvager
salvages
salve
salved
salver
salvers
salves
salvia
salvias
salvific
salving
salvo
salvoed
salvoes
salvoing
salvor
salvors
salvos
samara
samaras
samarium
samba
sambaed
sambaing
sambar
sambars
sambas
sambhar
sambhars
sambhur
sambhurs
sambo
sambos
sambuca
sambucas
sambuke
sambukes
sambur
samburs
same
samech
samechs
samek
samekh
samekhs
sameks
sameness
samiel
samiels
samisen
samisens
samite
samites
samizdat
samlet
samlets
samosa
samosas
samovar
samovars
samp
sampan
sampans
samphire
sample
sampled
sampler
samplers
samples
sampling
samps
samsara
samsaras
samshu
samshus
samurai
samurais
sanative
sancta
sanctify
sanction
sanctity
sanctum
sanctums
sand
sandal
sandaled
sandals
sandarac
sandbag
sandbags
sandbank
sandbar
sandbars
sandbox
sandbur
sandburr
sandburs
sanddab
sanddabs
sanded
sander
sanders
sandfish
sandfly
sandhi
sandhis
sandhog
sandhogs
sandier
sandiest
sanding
sandlike
sandling
sandlot
sandlots
sandman
sandmen
sandpeep
sandpile
sandpit
sandpits
sands
sandshoe
sandsoap
sandspur
sandwich
sandworm
sandwort
sandy
sane
saned
sanely
saneness
saner
sanes
sanest
sang
sanga
sangar
sangaree
sangars
sangas
sanger
sangers
sangh
sanghs
sangria
sangrias
sanguine
sanicle
sanicles
sanies
saning
sanious
sanitary
sanitate
sanities
sanitise
sanitize
sanity
sanjak
sanjaks
sank
sannop
sannops
sannup
sannups
sannyasi
sans
sansar
sansars
sansei
sanseis
sanserif
santalic
santalol
santimi
santims
santir
santirs
santo
santol
santols
santonin
santos
santour
santours
santur
santurs
sap
sapajou
sapajous
saphead
sapheads
saphena
saphenae
sapid
sapidity
sapience
sapiency
sapiens
sapient
sapless
sapling
saplings
saponify
saponin
saponine
saponins
saponite
sapor
saporous
sapors
sapota
sapotas
sapote
sapotes
sapour
sapours
sapped
sapper
sappers
sapphic
sapphics
sapphire
sapphism
sapphist
sappier
sappiest
sappily
sapping
sappy
sapremia
sapremic
saprobe
saprobes
saprobic
sapropel
saps
sapsago
sapsagos
sapwood
sapwoods
saraband
saran
sarans
sarape
sarapes
sarcasm
sarcasms
sarcenet
sarcoid
sarcoids
sarcoma
sarcomas
sarcous
sard
sardana
sardanas
sardar
sardars
sardine
sardines
sardius
sardonic
sardonyx
sards
saree
sarees
sargasso
sarge
sarges
sari
sarin
sarins
saris
sark
sarkier
sarkiest
sarks
sarky
sarment
sarmenta
sarments
sarod
sarode
sarodes
sarodist
sarods
sarong
sarongs
saros
saroses
sarsar
sarsars
sarsen
sarsenet
sarsens
sartor
sartorii
sartors
sash
sashay
sashayed
sashays
sashed
sashes
sashimi
sashimis
sashing
sasin
sasins
sass
sassaby
sassed
sasses
sassier
sassies
sassiest
sassily
sassing
sasswood
sassy
sastruga
sastrugi
sat
satang
satangs
satanic
satanism
satanist
satara
sataras
satay
satays
satchel
satchels
sate
sated
sateen
sateens
satem
sates
sati
satiable
satiably
satiate
satiated
satiates
satiety
satin
satinet
satinets
sating
satinpod
satins
satiny
satire
satires
satiric
satirise
satirist
satirize
satis
satisfy
satori
satoris
satrap
satraps
satrapy
satsuma
satsumas
saturant
saturate
satyr
satyric
satyrid
satyrids
satyrs
sau
sauce
saucebox
sauced
saucepan
saucer
saucers
sauces
sauch
sauchs
saucier
sauciest
saucily
saucing
saucy
sauger
saugers
saugh
saughs
saughy
saul
sauls
sault
saults
sauna
saunas
saunter
saunters
saurel
saurels
saurian
saurians
sauries
sauropod
saury
sausage
sausages
saute
sauted
sauteed
sauteing
sauterne
sautes
sautoir
sautoire
sautoirs
savable
savage
savaged
savagely
savager
savagery
savages
savagest
savaging
savagism
savanna
savannah
savannas
savant
savants
savarin
savarins
savate
savates
save
saveable
saved
saveloy
saveloys
saver
savers
saves
savin
savine
savines
saving
savingly
savings
savins
savior
saviors
saviour
saviours
savor
savored
savorer
savorers
savorier
savories
savorily
savoring
savorous
savors
savory
savour
savoured
savourer
savours
savoury
savoy
savoys
savvied
savvier
savvies
savviest
savvy
savvying
saw
sawbill
sawbills
sawbones
sawbuck
sawbucks
sawdust
sawdusts
sawed
sawer
sawers
sawfish
sawflies
sawfly
sawhorse
sawing
sawlike
sawlog
sawlogs
sawmill
sawmills
sawn
sawney
sawneys
saws
sawteeth
sawtooth
sawyer
sawyers
sax
saxatile
saxes
saxhorn
saxhorns
saxonies
saxony
saxtuba
saxtubas
say
sayable
sayer
sayers
sayest
sayid
sayids
saying
sayings
sayonara
says
sayst
sayyid
sayyids
scab
scabbard
scabbed
scabbier
scabbily
scabbing
scabble
scabbled
scabbles
scabby
scabies
scabiosa
scabious
scabland
scablike
scabrous
scabs
scad
scads
scaffold
scag
scags
scalable
scalably
scalade
scalades
scalado
scalados
scalage
scalages
scalar
scalare
scalares
scalars
scalawag
scald
scalded
scaldic
scalding
scalds
scale
scaled
scalene
scaleni
scalenus
scalepan
scaler
scalers
scales
scaleup
scaleups
scalier
scaliest
scaling
scall
scallion
scallop
scallops
scalls
scalp
scalped
scalpel
scalpels
scalper
scalpers
scalping
scalps
scaly
scam
scammed
scamming
scammony
scamp
scamped
scamper
scampers
scampi
scampies
scamping
scampish
scamps
scams
scan
scandal
scandals
scandent
scandia
scandias
scandic
scandium
scanned
scanner
scanners
scanning
scans
scansion
scant
scanted
scanter
scantest
scantier
scanties
scantily
scanting
scantly
scants
scanty
scape
scaped
scapes
scaphoid
scaping
scapose
scapula
scapulae
scapular
scapulas
scar
scarab
scarabs
scarce
scarcely
scarcer
scarcest
scarcity
scare
scared
scarer
scarers
scares
scarey
scarf
scarfed
scarfing
scarfpin
scarfs
scarier
scariest
scarify
scarily
scaring
scariose
scarious
scarless
scarlet
scarlets
scarp
scarped
scarper
scarpers
scarph
scarphed
scarphs
scarping
scarps
scarred
scarrier
scarring
scarry
scars
scart
scarted
scarting
scarts
scarves
scary
scat
scatback
scathe
scathed
scathes
scathing
scats
scatt
scatted
scatter
scatters
scattier
scatting
scatts
scatty
scaup
scauper
scaupers
scaups
scaur
scaurs
scavenge
scena
scenario
scenas
scend
scended
scending
scends
scene
scenery
scenes
scenic
scenical
scent
scented
scenting
scents
scepter
scepters
sceptic
sceptics
sceptral
sceptre
sceptred
sceptres
schappe
schappes
schav
schavs
schedule
schema
schemas
schemata
scheme
schemed
schemer
schemers
schemes
scheming
scherzi
scherzo
scherzos
schiller
schism
schisms
schist
schists
schizier
schizo
schizoid
schizont
schizos
schizy
schizzy
schlep
schlepp
schlepps
schleps
schliere
schlock
schlocks
schlocky
schlump
schlumps
schmaltz
schmalz
schmalzy
schmear
schmears
schmeer
schmeers
schmelze
schmo
schmoe
schmoes
schmoos
schmoose
schmooze
schmos
schmuck
schmucks
schnapps
schnaps
schnecke
schnook
schnooks
schnoz
schnozz
scholar
scholars
scholia
scholium
school
schooled
schools
schooner
schorl
schorls
schrik
schriks
schrod
schrods
schtick
schticks
schtik
schtiks
schuit
schuits
schul
schuln
schuss
schussed
schusser
schusses
schwa
schwas
sciaenid
sciatic
sciatica
sciatics
science
sciences
scilicet
scilla
scillas
scimetar
scimitar
scimiter
scincoid
sciolism
sciolist
scion
scions
scirocco
scirrhi
scirrhus
scissile
scission
scissor
scissors
scissure
sciurid
sciurids
sciurine
sciuroid
sclaff
sclaffed
sclaffer
sclaffs
sclera
sclerae
scleral
scleras
sclereid
sclerite
scleroid
scleroma
sclerose
sclerous
scoff
scoffed
scoffer
scoffers
scoffing
scofflaw
scoffs
scold
scolded
scolder
scolders
scolding
scolds
scoleces
scolex
scolices
scolioma
scollop
scollops
sconce
sconced
sconces
sconcing
scone
scones
scoop
scooped
scooper
scoopers
scoopful
scooping
scoops
scoot
scooted
scooter
scooters
scooting
scoots
scop
scope
scoped
scopes
scoping
scops
scopula
scopulae
scopulas
scorch
scorched
scorcher
scorches
score
scored
scorepad
scorer
scorers
scores
scoria
scoriae
scorify
scoring
scorn
scorned
scorner
scorners
scornful
scorning
scorns
scorpion
scot
scotch
scotched
scotches
scoter
scoters
scotia
scotias
scotoma
scotomas
scotopia
scotopic
scots
scottie
scotties
scour
scoured
scourer
scourers
scourge
scourged
scourger
scourges
scouring
scours
scouse
scouses
scout
scouted
scouter
scouters
scouth
scouther
scouths
scouting
scouts
scow
scowder
scowders
scowed
scowing
scowl
scowled
scowler
scowlers
scowling
scowls
scows
scrabble
scrabbly
scrag
scragged
scraggly
scraggy
scrags
scraich
scraichs
scraigh
scraighs
scram
scramble
scramjet
scrammed
scrams
scrannel
scrap
scrape
scraped
scraper
scrapers
scrapes
scrapie
scrapies
scraping
scrapped
scrapper
scrapple
scrappy
scraps
scratch
scratchy
scrawl
scrawled
scrawler
scrawls
scrawly
scrawny
screak
screaked
screaks
screaky
scream
screamed
screamer
screams
scree
screech
screechy
screed
screeded
screeds
screen
screened
screener
screens
screes
screw
screwed
screwer
screwers
screwier
screwing
screws
screwup
screwups
screwy
scribal
scribble
scribe
scribed
scriber
scribers
scribes
scribing
scried
scries
scrieve
scrieved
scrieves
scrim
scrimp
scrimped
scrimper
scrimpit
scrimps
scrimpy
scrims
scrip
scrips
script
scripted
scripter
scripts
scrive
scrived
scrives
scriving
scrod
scrods
scrofula
scroggy
scroll
scrolled
scrolls
scrooch
scrooge
scrooges
scroop
scrooped
scroops
scrootch
scrota
scrotal
scrotum
scrotums
scrouge
scrouged
scrouges
scrounge
scroungy
scrub
scrubbed
scrubber
scrubby
scrubs
scruff
scruffs
scruffy
scrum
scrummed
scrums
scrunch
scruple
scrupled
scruples
scrutiny
scry
scrying
scuba
scubas
scud
scudded
scudding
scudi
scudo
scuds
scuff
scuffed
scuffing
scuffle
scuffled
scuffler
scuffles
scuffs
sculk
sculked
sculker
sculkers
sculking
sculks
scull
sculled
sculler
scullers
scullery
sculling
scullion
sculls
sculp
sculped
sculpin
sculping
sculpins
sculps
sculpt
sculpted
sculptor
sculpts
scum
scumbag
scumbags
scumble
scumbled
scumbles
scumlike
scummed
scummer
scummers
scummier
scumming
scummy
scums
scunner
scunners
scup
scuppaug
scupper
scuppers
scups
scurf
scurfier
scurfs
scurfy
scurried
scurries
scurril
scurrile
scurry
scurvier
scurvies
scurvily
scurvy
scut
scuta
scutage
scutages
scutate
scutch
scutched
scutcher
scutches
scute
scutella
scutes
scuts
scutter
scutters
scuttle
scuttled
scuttles
scutum
scuzzier
scuzzy
scyphate
scyphi
scyphus
scythe
scythed
scythes
scything
sea
seabag
seabags
seabeach
seabed
seabeds
seabird
seabirds
seaboard
seaboot
seaboots
seaborne
seacoast
seacock
seacocks
seacraft
seadog
seadogs
seadrome
seafarer
seafloor
seafood
seafoods
seafowl
seafowls
seafront
seagirt
seagoing
seagull
seagulls
seal
sealable
sealant
sealants
sealed
sealer
sealers
sealery
sealing
seallike
seals
sealskin
seam
seaman
seamanly
seamark
seamarks
seamed
seamen
seamer
seamers
seamier
seamiest
seaming
seamless
seamlike
seamount
seams
seamster
seamy
seance
seances
seapiece
seaplane
seaport
seaports
seaquake
sear
search
searched
searcher
searches
seared
searer
searest
searing
searobin
sears
seas
seascape
seascout
seashell
seashore
seasick
seaside
seasides
season
seasonal
seasoned
seasoner
seasons
seat
seated
seater
seaters
seating
seatings
seatless
seatmate
seatrain
seats
seatwork
seawall
seawalls
seawan
seawans
seawant
seawants
seaward
seawards
seaware
seawares
seawater
seaway
seaways
seaweed
seaweeds
sebacic
sebasic
sebum
sebums
sec
secalose
secant
secantly
secants
secateur
secco
seccos
secede
seceded
seceder
seceders
secedes
seceding
secern
secerned
secerns
seclude
secluded
secludes
second
seconde
seconded
seconder
secondes
secondi
secondly
secondo
seconds
secpar
secpars
secrecy
secret
secrete
secreted
secreter
secretes
secretin
secretly
secretor
secrets
secs
sect
sectary
sectile
section
sections
sector
sectoral
sectored
sectors
sects
secular
seculars
secund
secundly
secundum
secure
secured
securely
securer
securers
secures
securest
securing
security
sedan
sedans
sedarim
sedate
sedated
sedately
sedater
sedates
sedatest
sedating
sedation
sedative
seder
seders
sederunt
sedge
sedges
sedgier
sedgiest
sedgy
sedile
sedilia
sedilium
sediment
sedition
seduce
seduced
seducer
seducers
seduces
seducing
seducive
sedulity
sedulous
sedum
sedums
see
seeable
seecatch
seed
seedbed
seedbeds
seedcake
seedcase
seeded
seeder
seeders
seedier
seediest
seedily
seeding
seedless
seedlike
seedling
seedman
seedmen
seedpod
seedpods
seeds
seedsman
seedsmen
seedtime
seedy
seeing
seeings
seek
seeker
seekers
seeking
seeks
seel
seeled
seeling
seels
seely
seem
seemed
seemer
seemers
seeming
seemings
seemlier
seemly
seems
seen
seep
seepage
seepages
seeped
seepier
seepiest
seeping
seeps
seepy
seer
seeress
seers
sees
seesaw
seesawed
seesaws
seethe
seethed
seethes
seething
seg
segetal
seggar
seggars
segment
segments
segni
segno
segnos
sego
segos
segs
segue
segued
segueing
segues
sei
seicento
seiche
seiches
seidel
seidels
seif
seifs
seigneur
seignior
seignory
seine
seined
seiner
seiners
seines
seining
seis
seisable
seise
seised
seiser
seisers
seises
seisin
seising
seisings
seisins
seism
seismal
seismic
seismism
seisms
seisor
seisors
seisure
seisures
seizable
seize
seized
seizer
seizers
seizes
seizin
seizing
seizings
seizins
seizor
seizors
seizure
seizures
sejant
sejeant
sel
seladang
selah
selahs
selamlik
selcouth
seldom
seldomly
select
selected
selectee
selectly
selector
selects
selenate
selenic
selenide
selenite
selenium
selenous
self
selfdom
selfdoms
selfed
selfheal
selfhood
selfing
selfish
selfless
selfness
selfs
selfsame
selfward
sell
sellable
selle
seller
sellers
selles
selling
sellout
sellouts
sells
sels
selsyn
selsyns
seltzer
seltzers
selva
selvage
selvaged
selvages
selvas
selvedge
selves
semantic
sematic
seme
sememe
sememes
sememic
semen
semens
semes
semester
semi
semiarid
semibald
semicoma
semideaf
semidome
semidry
semifit
semigala
semihard
semihigh
semihobo
semilog
semimat
semimatt
semimute
semina
seminal
seminar
seminars
seminary
seminude
semioses
semiosis
semiotic
semipro
semipros
semiraw
semis
semises
semisoft
semitist
semitone
semiwild
semolina
semple
semplice
sempre
sen
senarii
senarius
senary
senate
senates
senator
senators
send
sendable
sendal
sendals
sended
sender
senders
sending
sendoff
sendoffs
sends
sendup
sendups
sene
seneca
senecas
senecio
senecios
senega
senegas
sengi
senhor
senhora
senhoras
senhores
senhors
senile
senilely
seniles
senility
senior
seniors
seniti
senna
sennas
sennet
sennets
sennight
sennit
sennits
senopia
senopias
senor
senora
senoras
senores
senorita
senors
senryu
sensa
sensate
sensated
sensates
sense
sensed
senseful
senses
sensible
sensibly
sensilla
sensing
sensor
sensoria
sensors
sensory
sensual
sensum
sensuous
sent
sente
sentence
senti
sentient
sentimo
sentimos
sentinel
sentries
sentry
sepal
sepaled
sepaline
sepalled
sepaloid
sepalous
sepals
separate
sepia
sepias
sepic
sepoy
sepoys
seppuku
seppukus
sepses
sepsis
sept
septa
septal
septaria
septate
septet
septets
septette
septic
septical
septics
septime
septimes
septs
septum
septums
septuple
sequel
sequela
sequelae
sequels
sequence
sequency
sequent
sequents
sequin
sequined
sequins
sequitur
sequoia
sequoias
ser
sera
serac
seracs
seraglio
serai
serail
serails
serais
seral
serape
serapes
seraph
seraphic
seraphim
seraphin
seraphs
serdab
serdabs
sere
sered
serein
sereins
serenade
serenata
serenate
serene
serenely
serener
serenes
serenest
serenity
serer
seres
serest
serf
serfage
serfages
serfdom
serfdoms
serfhood
serfish
serflike
serfs
serge
sergeant
serges
serging
sergings
serial
serially
serials
seriate
seriated
seriates
seriatim
sericin
sericins
seriema
seriemas
series
serif
serifed
seriffed
serifs
serin
serine
serines
sering
seringa
seringas
serins
serious
serjeant
sermon
sermonic
sermons
serology
serosa
serosae
serosal
serosas
serosity
serotine
serotype
serous
serow
serows
serpent
serpents
serpigo
serranid
serrano
serranos
serrate
serrated
serrates
serried
serries
serry
serrying
sers
serum
serumal
serums
servable
serval
servals
servant
servants
serve
served
server
servers
serves
service
serviced
servicer
services
servile
serving
servings
servitor
servo
servos
sesame
sesames
sesamoid
sessile
session
sessions
sesspool
sesterce
sestet
sestets
sestina
sestinas
sestine
sestines
set
seta
setae
setal
setback
setbacks
setenant
setiform
setline
setlines
setoff
setoffs
seton
setons
setose
setous
setout
setouts
sets
setscrew
sett
settee
settees
setter
setters
setting
settings
settle
settled
settler
settlers
settles
settling
settlor
settlors
setts
setulose
setulous
setup
setups
seven
sevens
seventh
sevenths
seventy
sever
several
severals
severe
severed
severely
severer
severest
severing
severity
severs
seviche
seviches
sevruga
sevrugas
sew
sewable
sewage
sewages
sewan
sewans
sewar
sewars
sewed
sewer
sewerage
sewered
sewering
sewers
sewing
sewings
sewn
sews
sex
sexed
sexes
sexier
sexiest
sexily
sexiness
sexing
sexism
sexisms
sexist
sexists
sexless
sexology
sexpot
sexpots
sext
sextain
sextains
sextan
sextans
sextant
sextants
sextarii
sextet
sextets
sextette
sextile
sextiles
sexto
sexton
sextons
sextos
sexts
sextuple
sextuply
sexual
sexually
sexy
sferics
sforzato
sfumato
sfumatos
sh
sha
shabbier
shabbily
shabby
shack
shackle
shackled
shackler
shackles
shacko
shackoes
shackos
shacks
shad
shadblow
shadbush
shadchan
shaddock
shade
shaded
shader
shaders
shades
shadfly
shadier
shadiest
shadily
shading
shadings
shadoof
shadoofs
shadow
shadowed
shadower
shadows
shadowy
shadrach
shads
shaduf
shadufs
shady
shaft
shafted
shafting
shafts
shag
shagbark
shagged
shaggier
shaggily
shagging
shaggy
shagreen
shags
shah
shahdom
shahdoms
shahs
shaird
shairds
shairn
shairns
shaitan
shaitans
shakable
shake
shaken
shakeout
shaker
shakers
shakes
shakeup
shakeups
shakier
shakiest
shakily
shaking
shako
shakoes
shakos
shaky
shale
shaled
shales
shaley
shalier
shaliest
shall
shalloon
shallop
shallops
shallot
shallots
shallow
shallows
shalom
shaloms
shalt
shaly
sham
shamable
shaman
shamanic
shamans
shamas
shamble
shambled
shambles
shame
shamed
shameful
shames
shaming
shammas
shammash
shammed
shammer
shammers
shammes
shammied
shammies
shamming
shammos
shammy
shamois
shamos
shamosim
shamoy
shamoyed
shamoys
shampoo
shampoos
shamrock
shams
shamus
shamuses
shandies
shandy
shanghai
shank
shanked
shanking
shanks
shannies
shanny
shantey
shanteys
shanti
shanties
shantih
shantihs
shantis
shantung
shanty
shapable
shape
shaped
shapely
shapen
shaper
shapers
shapes
shapeup
shapeups
shaping
sharable
shard
shards
share
shared
sharer
sharers
shares
sharif
sharifs
sharing
shark
sharked
sharker
sharkers
sharking
sharks
sharn
sharns
sharny
sharp
sharped
sharpen
sharpens
sharper
sharpers
sharpest
sharpie
sharpies
sharping
sharply
sharps
sharpy
shashlik
shaslik
shasliks
shat
shatter
shatters
shaugh
shaughs
shaul
shauled
shauling
shauls
shavable
shave
shaved
shaven
shaver
shavers
shaves
shavie
shavies
shaving
shavings
shaw
shawed
shawing
shawl
shawled
shawling
shawls
shawm
shawms
shawn
shaws
shay
shays
she
shea
sheaf
sheafed
sheafing
sheafs
sheal
shealing
sheals
shear
sheared
shearer
shearers
shearing
shears
sheas
sheath
sheathe
sheathed
sheather
sheathes
sheaths
sheave
sheaved
sheaves
sheaving
shebang
shebangs
shebean
shebeans
shebeen
shebeens
shed
shedable
shedded
shedder
shedders
shedding
shedlike
sheds
sheen
sheened
sheeney
sheeneys
sheenful
sheenie
sheenier
sheenies
sheening
sheens
sheeny
sheep
sheepcot
sheepdog
sheepish
sheepman
sheepmen
sheer
sheered
sheerer
sheerest
sheering
sheerly
sheers
sheet
sheeted
sheeter
sheeters
sheetfed
sheeting
sheets
sheeve
sheeves
shegetz
sheik
sheikdom
sheikh
sheikhs
sheiks
sheila
sheilas
sheitan
sheitans
shekel
shekels
shelduck
shelf
shelfful
shell
shellac
shellack
shellacs
shelled
sheller
shellers
shellier
shelling
shells
shelly
shelta
sheltas
shelter
shelters
sheltie
shelties
shelty
shelve
shelved
shelver
shelvers
shelves
shelvier
shelving
shelvy
shend
shending
shends
shent
sheol
sheols
shepherd
sheqalim
sheqel
sherbert
sherbet
sherbets
sherd
sherds
shereef
shereefs
sherif
sheriff
sheriffs
sherifs
sherlock
sheroot
sheroots
sherpa
sherpas
sherries
sherris
sherry
shes
shetland
sheuch
sheuchs
sheugh
sheughs
shew
shewed
shewer
shewers
shewing
shewn
shews
shh
shiatsu
shiatsus
shiatzu
shiatzus
shibah
shibahs
shicker
shickers
shicksa
shicksas
shied
shiel
shield
shielded
shielder
shields
shieling
shiels
shier
shiers
shies
shiest
shift
shifted
shifter
shifters
shiftier
shiftily
shifting
shifts
shifty
shigella
shiitake
shikar
shikaree
shikari
shikaris
shikars
shikker
shikkers
shiksa
shiksas
shikse
shikses
shilingi
shill
shillala
shilled
shilling
shills
shilpit
shily
shim
shimmed
shimmer
shimmers
shimmery
shimmied
shimmies
shimming
shimmy
shims
shin
shinbone
shindies
shindig
shindigs
shindy
shindys
shine
shined
shiner
shiners
shines
shingle
shingled
shingler
shingles
shingly
shinier
shiniest
shinily
shining
shinleaf
shinned
shinnery
shinney
shinneys
shinnied
shinnies
shinning
shinny
shins
shiny
ship
shiplap
shiplaps
shipload
shipman
shipmate
shipmen
shipment
shipped
shippen
shippens
shipper
shippers
shipping
shippon
shippons
ships
shipside
shipway
shipways
shipworm
shipyard
shire
shires
shirk
shirked
shirker
shirkers
shirking
shirks
shirr
shirred
shirring
shirrs
shirt
shirtier
shirting
shirts
shirty
shist
shists
shit
shitake
shitakes
shithead
shits
shittah
shittahs
shitted
shittier
shittim
shittims
shitting
shitty
shiv
shiva
shivah
shivahs
shivaree
shivas
shive
shiver
shivered
shiverer
shivers
shivery
shives
shivs
shkotzim
shlemiel
shlep
shlepp
shlepped
shlepps
shleps
shlock
shlocks
shlump
shlumped
shlumps
shlumpy
shmaltz
shmaltzy
shmear
shmears
shmo
shmoes
shmooze
shmoozed
shmoozes
shmuck
shmucks
shnaps
shnook
shnooks
shoal
shoaled
shoaler
shoalest
shoalier
shoaling
shoals
shoaly
shoat
shoats
shock
shocked
shocker
shockers
shocking
shocks
shod
shodden
shoddier
shoddies
shoddily
shoddy
shoe
shoebill
shoed
shoehorn
shoeing
shoelace
shoeless
shoepac
shoepack
shoepacs
shoer
shoers
shoes
shoetree
shofar
shofars
shofroth
shog
shogged
shogging
shogs
shogun
shogunal
shoguns
shoji
shojis
sholom
sholoms
shone
shoo
shooed
shoofly
shooing
shook
shooks
shool
shooled
shooling
shools
shoon
shoos
shoot
shooter
shooters
shooting
shootout
shoots
shop
shopboy
shopboys
shopgirl
shophar
shophars
shoplift
shopman
shopmen
shoppe
shopped
shopper
shoppers
shoppes
shopping
shops
shoptalk
shopworn
shoran
shorans
shore
shored
shores
shoring
shorings
shorl
shorls
shorn
short
shortage
shortcut
shorted
shorten
shortens
shorter
shortest
shortia
shortias
shortie
shorties
shorting
shortish
shortly
shorts
shorty
shot
shote
shotes
shotgun
shotguns
shots
shott
shotted
shotten
shotting
shotts
should
shoulder
shouldst
shout
shouted
shouter
shouters
shouting
shouts
shove
shoved
shovel
shoveled
shoveler
shovels
shover
shovers
shoves
shoving
show
showable
showbiz
showboat
showcase
showdown
showed
shower
showered
showerer
showers
showery
showgirl
showier
showiest
showily
showing
showings
showman
showmen
shown
showoff
showoffs
showring
showroom
shows
showy
shoyu
shoyus
shrank
shrapnel
shred
shredded
shredder
shreds
shrew
shrewd
shrewder
shrewdie
shrewdly
shrewed
shrewing
shrewish
shrews
shri
shriek
shrieked
shrieker
shrieks
shrieky
shrieval
shrieve
shrieved
shrieves
shrift
shrifts
shrike
shrikes
shrill
shrilled
shriller
shrills
shrilly
shrimp
shrimped
shrimper
shrimps
shrimpy
shrine
shrined
shrines
shrining
shrink
shrinker
shrinks
shris
shrive
shrived
shrivel
shrivels
shriven
shriver
shrivers
shrives
shriving
shroff
shroffed
shroffs
shroud
shrouded
shrouds
shrove
shrub
shrubby
shrubs
shrug
shrugged
shrugs
shrunk
shrunken
shtetel
shtetels
shtetl
shtetls
shtick
shticks
shtik
shtiks
shuck
shucked
shucker
shuckers
shucking
shucks
shudder
shudders
shuddery
shuffle
shuffled
shuffler
shuffles
shul
shuln
shuls
shun
shunned
shunner
shunners
shunning
shunpike
shuns
shunt
shunted
shunter
shunters
shunting
shunts
shush
shushed
shushes
shushing
shut
shutdown
shute
shuted
shutes
shuteye
shuteyes
shuting
shutoff
shutoffs
shutout
shutouts
shuts
shutter
shutters
shutting
shuttle
shuttled
shuttles
shwanpan
shy
shyer
shyers
shyest
shying
shylock
shylocks
shyly
shyness
shyster
shysters
si
sial
sialic
sialid
sialidan
sialids
sialoid
sials
siamang
siamangs
siamese
siameses
sib
sibb
sibbs
sibilant
sibilate
sibling
siblings
sibs
sibyl
sibylic
sibyllic
sibyls
sic
siccan
sicced
siccing
sice
sices
sick
sickbay
sickbays
sickbed
sickbeds
sicked
sickee
sickees
sicken
sickened
sickener
sickens
sicker
sickerly
sickest
sickie
sickies
sicking
sickish
sickle
sickled
sickles
sicklied
sicklier
sicklies
sicklily
sickling
sickly
sickness
sicko
sickos
sickout
sickouts
sickroom
sicks
sics
siddur
siddurim
siddurs
side
sidearm
sideband
sidebar
sidebars
sidecar
sidecars
sided
sidehill
sidekick
sideline
sideling
sidelong
sideman
sidemen
sidereal
siderite
sides
sideshow
sideslip
sidespin
sidestep
sidewalk
sidewall
sideward
sideway
sideways
sidewise
siding
sidings
sidle
sidled
sidler
sidlers
sidles
sidling
siege
sieged
sieges
sieging
siemens
sienite
sienites
sienna
siennas
sierozem
sierra
sierran
sierras
siesta
siestas
sieur
sieurs
sieve
sieved
sieves
sieving
sifaka
sifakas
siffleur
sift
sifted
sifter
sifters
sifting
siftings
sifts
siganid
siganids
sigh
sighed
sigher
sighers
sighing
sighless
sighlike
sighs
sight
sighted
sighter
sighters
sighting
sightly
sights
sightsaw
sightsee
sigil
sigils
sigloi
siglos
sigma
sigmas
sigmate
sigmoid
sigmoids
sign
signage
signages
signal
signaled
signaler
signally
signals
signed
signee
signees
signer
signers
signet
signeted
signets
signify
signing
signior
signiori
signiors
signiory
signor
signora
signoras
signore
signori
signors
signory
signpost
signs
sike
siker
sikes
silage
silages
silane
silanes
sild
silds
silence
silenced
silencer
silences
sileni
silent
silenter
silently
silents
silenus
silesia
silesias
silex
silexes
silica
silicas
silicate
silicic
silicide
silicify
silicium
silicle
silicles
silicon
silicone
silicons
silicula
siliqua
siliquae
silique
siliques
silk
silked
silken
silkier
silkies
silkiest
silkily
silking
silklike
silks
silkweed
silkworm
silky
sill
sillabub
siller
sillers
sillibub
sillier
sillies
silliest
sillily
sills
silly
silo
siloed
siloing
silos
siloxane
silt
silted
siltier
siltiest
silting
silts
silty
silurid
silurids
siluroid
silva
silvae
silvan
silvans
silvas
silver
silvered
silverer
silverly
silvern
silvers
silvery
silvex
silvexes
silvical
silvics
sim
sima
simar
simars
simaruba
simas
simazine
simian
simians
similar
simile
similes
simioid
simious
simitar
simitars
simlin
simlins
simmer
simmered
simmers
simnel
simnels
simoleon
simoniac
simonies
simonist
simonize
simony
simoom
simooms
simoon
simoons
simp
simper
simpered
simperer
simpers
simple
simpler
simples
simplest
simplex
simplify
simplism
simplist
simply
simps
sims
simulant
simular
simulars
simulate
sin
sinapism
since
sincere
sincerer
sinciput
sine
sinecure
sines
sinew
sinewed
sinewing
sinews
sinewy
sinfonia
sinfonie
sinful
sinfully
sing
singable
singe
singed
singeing
singer
singers
singes
singing
single
singled
singles
singlet
singlets
singling
singly
sings
singsong
singular
sinh
sinhs
sinicize
sinister
sink
sinkable
sinkage
sinkages
sinker
sinkers
sinkhole
sinking
sinks
sinless
sinned
sinner
sinners
sinning
sinology
sinopia
sinopias
sinopie
sins
sinsyne
sinter
sintered
sinters
sinuate
sinuated
sinuates
sinuous
sinus
sinuses
sinusoid
sip
sipe
siped
sipes
siphon
siphonal
siphoned
siphonic
siphons
siping
sipped
sipper
sippers
sippet
sippets
sipping
sips
sir
sirdar
sirdars
sire
sired
siree
sirees
siren
sirenian
sirens
sires
siring
sirloin
sirloins
sirocco
siroccos
sirra
sirrah
sirrahs
sirras
sirree
sirrees
sirs
sirup
sirups
sirupy
sirvente
sis
sisal
sisals
sises
siskin
siskins
sissier
sissies
sissiest
sissy
sissyish
sister
sistered
sisterly
sisters
sistra
sistroid
sistrum
sistrums
sit
sitar
sitarist
sitars
sitcom
sitcoms
site
sited
sites
sith
sithence
sithens
siting
sitology
sits
sitten
sitter
sitters
sitting
sittings
situate
situated
situates
situp
situps
situs
situses
sitzmark
siver
sivers
six
sixes
sixfold
sixmo
sixmos
sixpence
sixpenny
sixte
sixteen
sixteens
sixtes
sixth
sixthly
sixths
sixties
sixtieth
sixty
sixtyish
sizable
sizably
sizar
sizars
size
sizeable
sizeably
sized
sizer
sizers
sizes
sizier
siziest
siziness
sizing
sizings
sizy
sizzle
sizzled
sizzler
sizzlers
sizzles
sizzling
sjambok
sjamboks
ska
skag
skags
skald
skaldic
skalds
skas
skat
skate
skated
skater
skaters
skates
skating
skatings
skatol
skatole
skatoles
skatols
skats
skean
skeane
skeanes
skeans
skee
skeed
skeeing
skeen
skeens
skees
skeet
skeeter
skeeters
skeets
skeg
skegs
skeigh
skein
skeined
skeining
skeins
skeletal
skeleton
skellum
skellums
skelm
skelms
skelp
skelped
skelping
skelpit
skelps
skelter
skelters
skene
skenes
skep
skeps
skepsis
skeptic
skeptics
skerries
skerry
sketch
sketched
sketcher
sketches
sketchy
skew
skewback
skewbald
skewed
skewer
skewered
skewers
skewing
skewness
skews
ski
skiable
skiagram
skibob
skibobs
skid
skidded
skidder
skidders
skiddier
skidding
skiddoo
skiddoos
skiddy
skidoo
skidooed
skidoos
skids
skidway
skidways
skied
skier
skiers
skies
skiey
skiff
skiffle
skiffled
skiffles
skiffs
skiing
skiings
skijorer
skilful
skill
skilled
skilless
skillet
skillets
skillful
skilling
skills
skim
skimmed
skimmer
skimmers
skimming
skimo
skimos
skimp
skimped
skimpier
skimpily
skimping
skimps
skimpy
skims
skin
skinful
skinfuls
skinhead
skink
skinked
skinker
skinkers
skinking
skinks
skinless
skinlike
skinned
skinner
skinners
skinnier
skinning
skinny
skins
skint
skioring
skip
skipjack
skiplane
skipped
skipper
skippers
skippet
skippets
skipping
skips
skirl
skirled
skirling
skirls
skirmish
skirr
skirred
skirret
skirrets
skirring
skirrs
skirt
skirted
skirter
skirters
skirting
skirts
skis
skit
skite
skited
skites
skiting
skits
skitter
skitters
skittery
skittish
skittle
skittles
skive
skived
skiver
skivers
skives
skiving
skivvied
skivvies
skivvy
skiwear
sklent
sklented
sklents
skoal
skoaled
skoaling
skoals
skookum
skosh
skoshes
skreegh
skreeghs
skreigh
skreighs
skua
skuas
skulk
skulked
skulker
skulkers
skulking
skulks
skull
skullcap
skulled
skulls
skunk
skunked
skunking
skunks
sky
skyborne
skybox
skyboxes
skycap
skycaps
skydive
skydived
skydiver
skydives
skydove
skyed
skyey
skyhook
skyhooks
skying
skyjack
skyjacks
skylark
skylarks
skylight
skyline
skylines
skylit
skyman
skymen
skyphoi
skyphos
skysail
skysails
skywalk
skywalks
skyward
skywards
skyway
skyways
skywrite
skywrote
slab
slabbed
slabber
slabbers
slabbery
slabbing
slablike
slabs
slack
slacked
slacken
slackens
slacker
slackers
slackest
slacking
slackly
slacks
slag
slagged
slaggier
slagging
slaggy
slags
slain
slainte
slakable
slake
slaked
slaker
slakers
slakes
slaking
slalom
slalomed
slaloms
slam
slammed
slammer
slammers
slamming
slams
slander
slanders
slang
slanged
slangier
slangily
slanging
slangs
slangy
slank
slant
slanted
slanting
slants
slanty
slap
slapdash
slapjack
slapped
slapper
slappers
slapping
slaps
slash
slashed
slasher
slashers
slashes
slashing
slat
slatch
slatches
slate
slated
slater
slaters
slates
slatey
slather
slathers
slatier
slatiest
slating
slatings
slats
slatted
slattern
slatting
slaty
slave
slaved
slaver
slavered
slaverer
slavers
slavery
slaves
slavey
slaveys
slaving
slavish
slaw
slaws
slay
slayed
slayer
slayers
slaying
slays
sleave
sleaved
sleaves
sleaving
sleaze
sleazes
sleazier
sleazily
sleazo
sleazy
sled
sledded
sledder
sledders
sledding
sledge
sledged
sledges
sledging
sleds
sleek
sleeked
sleeken
sleekens
sleeker
sleekest
sleekier
sleeking
sleekit
sleekly
sleeks
sleeky
sleep
sleeper
sleepers
sleepier
sleepily
sleeping
sleeps
sleepy
sleet
sleeted
sleetier
sleeting
sleets
sleety
sleeve
sleeved
sleeves
sleeving
sleigh
sleighed
sleigher
sleighs
sleight
sleights
slender
slept
sleuth
sleuthed
sleuths
slew
slewed
slewing
slews
slice
sliced
slicer
slicers
slices
slicing
slick
slicked
slicker
slickers
slickest
slicking
slickly
slicks
slid
slidable
slidden
slide
slider
sliders
slides
slideway
sliding
slier
sliest
slight
slighted
slighter
slightly
slights
slily
slim
slime
slimed
slimes
slimier
slimiest
slimily
sliming
slimly
slimmed
slimmer
slimmers
slimmest
slimming
slimness
slimpsy
slims
slimsier
slimsy
slimy
sling
slinger
slingers
slinging
slings
slink
slinked
slinkier
slinkily
slinking
slinks
slinky
slip
slipcase
slipe
sliped
slipes
slipform
sliping
slipknot
slipless
slipout
slipouts
slipover
slippage
slipped
slipper
slippers
slippery
slippier
slipping
slippy
slips
slipshod
slipslop
slipsole
slipt
slipup
slipups
slipware
slipway
slipways
slit
slither
slithers
slithery
slitless
slits
slitted
slitter
slitters
slitting
sliver
slivered
sliverer
slivers
slivovic
slob
slobber
slobbers
slobbery
slobbier
slobbish
slobby
slobs
sloe
sloes
slog
slogan
slogans
slogged
slogger
sloggers
slogging
slogs
sloid
sloids
slojd
slojds
sloop
sloops
slop
slope
sloped
sloper
slopers
slopes
sloping
slopped
sloppier
sloppily
slopping
sloppy
slops
slopwork
slosh
sloshed
sloshes
sloshier
sloshing
sloshy
slot
slotback
sloth
slothful
sloths
slots
slotted
slotting
slouch
slouched
sloucher
slouches
slouchy
slough
sloughed
sloughs
sloughy
sloven
slovenly
slovens
slow
slowdown
slowed
slower
slowest
slowing
slowish
slowly
slowness
slowpoke
slows
slowworm
sloyd
sloyds
slub
slubbed
slubber
slubbers
slubbing
slubs
sludge
sludges
sludgier
sludgy
slue
slued
slues
sluff
sluffed
sluffing
sluffs
slug
slugabed
slugfest
sluggard
slugged
slugger
sluggers
slugging
sluggish
slugs
sluice
sluiced
sluices
sluicing
sluicy
sluing
slum
slumber
slumbers
slumbery
slumgum
slumgums
slumism
slumisms
slumlord
slummed
slummer
slummers
slummier
slumming
slummy
slump
slumped
slumping
slumps
slums
slung
slunk
slur
slurb
slurban
slurbs
slurp
slurped
slurping
slurps
slurred
slurried
slurries
slurring
slurry
slurs
slush
slushed
slushes
slushier
slushily
slushing
slushy
slut
sluts
sluttier
sluttish
slutty
sly
slyboots
slyer
slyest
slyly
slyness
slype
slypes
smack
smacked
smacker
smackers
smacking
smacks
small
smallage
smaller
smallest
smallish
smallpox
smalls
smalt
smalti
smaltine
smaltite
smalto
smaltos
smalts
smaragd
smaragde
smaragds
smarm
smarmier
smarmily
smarms
smarmy
smart
smartass
smarted
smarten
smartens
smarter
smartest
smartie
smarties
smarting
smartly
smarts
smarty
smash
smashed
smasher
smashers
smashes
smashing
smashup
smashups
smatter
smatters
smaze
smazes
smear
smeared
smearer
smearers
smearier
smearing
smears
smeary
smectic
smectite
smeddum
smeddums
smeek
smeeked
smeeking
smeeks
smegma
smegmas
smell
smelled
smeller
smellers
smellier
smelling
smells
smelly
smelt
smelted
smelter
smelters
smeltery
smelting
smelts
smerk
smerked
smerking
smerks
smew
smews
smidge
smidgen
smidgens
smidgeon
smidges
smidgin
smidgins
smilax
smilaxes
smile
smiled
smiler
smilers
smiles
smiley
smiling
smirch
smirched
smirches
smirk
smirked
smirker
smirkers
smirkier
smirking
smirks
smirky
smit
smite
smiter
smiters
smites
smith
smithers
smithery
smithies
smiths
smithy
smiting
smitten
smock
smocked
smocking
smocks
smog
smoggier
smoggy
smogless
smogs
smokable
smoke
smoked
smokepot
smoker
smokers
smokes
smokey
smokier
smokiest
smokily
smoking
smoky
smolder
smolders
smolt
smolts
smooch
smooched
smooches
smoochy
smooth
smoothed
smoothen
smoother
smoothes
smoothie
smoothly
smooths
smoothy
smote
smother
smothers
smothery
smoulder
smudge
smudged
smudges
smudgier
smudgily
smudging
smudgy
smug
smugger
smuggest
smuggle
smuggled
smuggler
smuggles
smugly
smugness
smut
smutch
smutched
smutches
smutchy
smuts
smutted
smuttier
smuttily
smutting
smutty
snack
snacked
snacking
snacks
snaffle
snaffled
snaffles
snafu
snafued
snafuing
snafus
snag
snagged
snaggier
snagging
snaggy
snaglike
snags
snail
snailed
snailing
snails
snake
snakebit
snaked
snakes
snakey
snakier
snakiest
snakily
snaking
snaky
snap
snapback
snapless
snapped
snapper
snappers
snappier
snappily
snapping
snappish
snappy
snaps
snapshot
snapweed
snare
snared
snarer
snarers
snares
snaring
snark
snarkier
snarks
snarky
snarl
snarled
snarler
snarlers
snarlier
snarling
snarls
snarly
snash
snashes
snatch
snatched
snatcher
snatches
snatchy
snath
snathe
snathes
snaths
snaw
snawed
snawing
snaws
snazzier
snazzy
sneak
sneaked
sneaker
sneakers
sneakier
sneakily
sneaking
sneaks
sneaky
sneap
sneaped
sneaping
sneaps
sneck
snecks
sned
snedded
snedding
sneds
sneer
sneered
sneerer
sneerers
sneerful
sneering
sneers
sneesh
sneeshes
sneeze
sneezed
sneezer
sneezers
sneezes
sneezier
sneezing
sneezy
snell
snelled
sneller
snellest
snelling
snells
snib
snibbed
snibbing
snibs
snick
snicked
snicker
snickers
snickery
snicking
snicks
snide
snidely
snider
snidest
sniff
sniffed
sniffer
sniffers
sniffier
sniffily
sniffing
sniffish
sniffle
sniffled
sniffler
sniffles
sniffs
sniffy
snifter
snifters
snigger
sniggers
sniggle
sniggled
sniggler
sniggles
snip
snipe
sniped
sniper
snipers
snipes
sniping
snipped
snipper
snippers
snippet
snippets
snippety
snippier
snippily
snipping
snippy
snips
snit
snitch
snitched
snitcher
snitches
snits
snivel
sniveled
sniveler
snivels
snob
snobbery
snobbier
snobbily
snobbish
snobbism
snobby
snobs
snog
snogged
snogging
snogs
snood
snooded
snooding
snoods
snook
snooked
snooker
snookers
snooking
snooks
snool
snooled
snooling
snools
snoop
snooped
snooper
snoopers
snoopier
snoopily
snooping
snoops
snoopy
snoot
snooted
snootier
snootily
snooting
snoots
snooty
snooze
snoozed
snoozer
snoozers
snoozes
snoozier
snoozing
snoozle
snoozled
snoozles
snoozy
snore
snored
snorer
snorers
snores
snoring
snorkel
snorkels
snort
snorted
snorter
snorters
snorting
snorts
snot
snots
snottier
snottily
snotty
snout
snouted
snoutier
snouting
snoutish
snouts
snouty
snow
snowball
snowbank
snowbell
snowbelt
snowbird
snowbush
snowcap
snowcaps
snowdrop
snowed
snowfall
snowier
snowiest
snowily
snowing
snowland
snowless
snowlike
snowman
snowmelt
snowmen
snowmold
snowpack
snowplow
snows
snowshed
snowshoe
snowsuit
snowy
snub
snubbed
snubber
snubbers
snubbier
snubbing
snubby
snubness
snubs
snuck
snuff
snuffbox
snuffed
snuffer
snuffers
snuffier
snuffily
snuffing
snuffle
snuffled
snuffler
snuffles
snuffly
snuffs
snuffy
snug
snugged
snugger
snuggery
snuggest
snuggies
snugging
snuggle
snuggled
snuggles
snugly
snugness
snugs
snye
snyes
so
soak
soakage
soakages
soaked
soaker
soakers
soaking
soaks
soap
soapbark
soapbox
soaped
soaper
soapers
soapier
soapiest
soapily
soaping
soapless
soaplike
soaps
soapsuds
soapwort
soapy
soar
soared
soarer
soarers
soaring
soarings
soars
soave
soaves
sob
sobbed
sobber
sobbers
sobbing
sobeit
sober
sobered
soberer
soberest
sobering
soberize
soberly
sobers
sobful
sobriety
sobs
socage
socager
socagers
socages
soccage
soccages
soccer
soccers
sociable
sociably
social
socially
socials
societal
society
sock
socked
socket
socketed
sockets
sockeye
sockeyes
socking
sockless
sockman
sockmen
socko
socks
socle
socles
socman
socmen
sod
soda
sodaless
sodalist
sodalite
sodality
sodamide
sodas
sodded
sodden
soddened
soddenly
soddens
soddies
sodding
soddy
sodic
sodium
sodiums
sodom
sodomies
sodomist
sodomite
sodomize
sodoms
sodomy
sods
soever
sofa
sofar
sofars
sofas
soffit
soffits
soft
softa
softas
softback
softball
soften
softened
softener
softens
softer
softest
softhead
softie
softies
softish
softly
softness
softs
software
softwood
softy
sogged
soggier
soggiest
soggily
soggy
soigne
soignee
soil
soilage
soilages
soiled
soiling
soilless
soils
soilure
soilures
soiree
soirees
soja
sojas
sojourn
sojourns
soke
sokeman
sokemen
sokes
sokol
sokols
sol
sola
solace
solaced
solacer
solacers
solaces
solacing
solan
soland
solander
solands
solanin
solanine
solanins
solano
solanos
solans
solanum
solanums
solar
solaria
solarise
solarism
solarium
solarize
solate
solated
solates
solatia
solating
solation
solatium
sold
soldan
soldans
solder
soldered
solderer
solders
soldi
soldier
soldiers
soldiery
soldo
sole
solecise
solecism
solecist
solecize
soled
solei
soleless
solely
solemn
solemner
solemnly
soleness
solenoid
soleret
solerets
soles
soleus
solfege
solfeges
solfeggi
solgel
soli
solicit
solicits
solid
solidago
solidary
solider
solidest
solidi
solidify
solidity
solidly
solids
solidus
soling
solion
solions
soliquid
solitary
soliton
solitons
solitude
solleret
solo
soloed
soloing
soloist
soloists
solon
solonets
solonetz
solons
solos
sols
solstice
soluble
solubles
solubly
solum
solums
solus
solute
solutes
solution
solvable
solvate
solvated
solvates
solve
solved
solvency
solvent
solvents
solver
solvers
solves
solving
soma
somas
somata
somatic
somber
somberly
sombre
sombrely
sombrero
sombrous
some
somebody
someday
somedeal
somehow
someone
someones
somerset
sometime
someway
someways
somewhat
somewhen
somewise
somital
somite
somites
somitic
son
sonance
sonances
sonant
sonantal
sonantic
sonants
sonar
sonarman
sonarmen
sonars
sonata
sonatas
sonatina
sonatine
sonde
sonder
sonders
sondes
sone
sones
song
songbird
songbook
songfest
songful
songless
songlike
songs
songster
sonhood
sonhoods
sonic
sonicate
sonics
sonless
sonlike
sonly
sonnet
sonneted
sonnets
sonnies
sonny
sonobuoy
sonogram
sonorant
sonority
sonorous
sonovox
sons
sonship
sonships
sonsie
sonsier
sonsiest
sonsy
soochong
sooey
sook
sooks
soon
sooner
sooners
soonest
soot
sooted
sooth
soothe
soothed
soother
soothers
soothes
soothest
soothing
soothly
sooths
soothsay
sootier
sootiest
sootily
sooting
soots
sooty
sop
soph
sophies
sophism
sophisms
sophist
sophists
sophs
sophy
sopite
sopited
sopites
sopiting
sopor
sopors
sopped
soppier
soppiest
sopping
soppy
soprani
soprano
sopranos
sops
sora
soras
sorb
sorbable
sorbate
sorbates
sorbed
sorbent
sorbents
sorbet
sorbets
sorbic
sorbing
sorbitol
sorbose
sorboses
sorbs
sorcerer
sorcery
sord
sordid
sordidly
sordine
sordines
sordini
sordino
sordor
sordors
sords
sore
sorehead
sorel
sorels
sorely
soreness
sorer
sores
sorest
sorgho
sorghos
sorghum
sorghums
sorgo
sorgos
sori
soricine
soring
sorings
sorites
soritic
sorn
sorned
sorner
sorners
sorning
sorns
soroche
soroches
sororal
sororate
sorority
soroses
sorosis
sorption
sorptive
sorrel
sorrels
sorrier
sorriest
sorrily
sorrow
sorrowed
sorrower
sorrows
sorry
sort
sortable
sortably
sorted
sorter
sorters
sortie
sortied
sorties
sorting
sorts
sorus
sos
sot
soth
soths
sotol
sotols
sots
sotted
sottish
sou
souari
souaris
soubise
soubises
soucar
soucars
souchong
soudan
soudans
souffle
souffled
souffles
sough
soughed
soughing
soughs
sought
souk
souks
soul
souled
soulful
soulless
soullike
souls
sound
soundbox
sounded
sounder
sounders
soundest
sounding
soundly
soundman
soundmen
sounds
soup
soupcon
soupcons
souped
soupier
soupiest
souping
soups
soupy
sour
sourball
source
sourced
sources
sourcing
sourdine
soured
sourer
sourest
souring
sourish
sourly
sourness
sourpuss
sours
soursop
soursops
sourwood
sous
souse
soused
souses
sousing
soutache
soutane
soutanes
souter
souters
south
southed
souther
southern
southers
southing
southpaw
southron
souths
souvenir
souvlaki
soviet
soviets
sovkhoz
sovkhozy
sovran
sovranly
sovrans
sovranty
sow
sowable
sowans
sowar
sowars
sowbelly
sowbread
sowcar
sowcars
sowed
sowens
sower
sowers
sowing
sown
sows
sox
soy
soya
soyas
soybean
soybeans
soymilk
soymilks
soys
soyuz
soyuzes
sozin
sozine
sozines
sozins
sozzled
spa
space
spaced
spaceman
spacemen
spacer
spacers
spaces
spacey
spacial
spacier
spaciest
spacing
spacings
spacious
spackle
spackled
spackles
spacy
spade
spaded
spadeful
spader
spaders
spades
spadices
spadille
spading
spadix
spadixes
spado
spadones
spae
spaed
spaeing
spaeings
spaes
spaetzle
spagyric
spahee
spahees
spahi
spahis
spail
spails
spait
spaits
spake
spale
spales
spall
spalled
spaller
spallers
spalling
spalls
spalpeen
span
spancel
spancels
spandex
spandrel
spandril
spang
spangle
spangled
spangles
spangly
spaniel
spaniels
spank
spanked
spanker
spankers
spanking
spanks
spanless
spanned
spanner
spanners
spanning
spans
spanworm
spar
sparable
spare
spared
sparely
sparer
sparerib
sparers
spares
sparest
sparge
sparged
sparger
spargers
sparges
sparging
sparid
sparids
sparing
spark
sparked
sparker
sparkers
sparkier
sparkily
sparking
sparkish
sparkle
sparkled
sparkler
sparkles
sparkly
sparks
sparky
sparlike
sparling
sparoid
sparoids
sparred
sparrier
sparring
sparrow
sparrows
sparry
spars
sparse
sparsely
sparser
sparsest
sparsity
spartan
spas
spasm
spasms
spastic
spastics
spat
spate
spates
spathal
spathe
spathed
spathes
spathic
spathose
spatial
spats
spatted
spatter
spatters
spatting
spatula
spatular
spatulas
spatzle
spavie
spavies
spaviet
spavin
spavined
spavins
spawn
spawned
spawner
spawners
spawning
spawns
spay
spayed
spaying
spays
spaz
spazzes
speak
speaker
speakers
speaking
speaks
spean
speaned
speaning
speans
spear
speared
spearer
spearers
speargun
spearing
spearman
spearmen
spears
spec
specced
speccing
special
specials
speciate
specie
species
specific
specify
specimen
specious
speck
specked
specking
speckle
speckled
speckles
specks
specs
spectate
specter
specters
spectra
spectral
spectre
spectres
spectrum
specula
specular
speculum
sped
speech
speeches
speed
speeded
speeder
speeders
speedier
speedily
speeding
speedo
speedos
speeds
speedup
speedups
speedway
speedy
speel
speeled
speeling
speels
speer
speered
speering
speers
speil
speiled
speiling
speils
speir
speired
speiring
speirs
speise
speises
speiss
speisses
spelaean
spelean
spell
spelled
speller
spellers
spelling
spells
spelt
spelter
spelters
spelts
speltz
speltzes
spelunk
spelunks
spence
spencer
spencers
spences
spend
spender
spenders
spending
spends
spense
spenses
spent
sperm
spermary
spermic
spermine
spermous
sperms
spew
spewed
spewer
spewers
spewing
spews
sphagnum
sphene
sphenes
sphenic
sphenoid
spheral
sphere
sphered
spheres
spheric
spherics
spherier
sphering
spheroid
spherule
sphery
sphinges
sphingid
sphinx
sphinxes
sphygmic
sphygmus
spic
spica
spicae
spicas
spicate
spicated
spiccato
spice
spiced
spicer
spicers
spicery
spices
spicey
spicier
spiciest
spicily
spicing
spick
spicks
spics
spicula
spiculae
spicular
spicule
spicules
spiculum
spicy
spider
spiders
spidery
spied
spiegel
spiegels
spiel
spieled
spieler
spielers
spieling
spiels
spier
spiered
spiering
spiers
spies
spiff
spiffed
spiffier
spiffily
spiffing
spiffs
spiffy
spigot
spigots
spik
spike
spiked
spikelet
spiker
spikers
spikes
spikey
spikier
spikiest
spikily
spiking
spiks
spiky
spile
spiled
spiles
spilikin
spiling
spilings
spill
spillage
spilled
spiller
spillers
spilling
spills
spillway
spilt
spilth
spilths
spin
spinach
spinachy
spinage
spinages
spinal
spinally
spinals
spinate
spindle
spindled
spindler
spindles
spindly
spine
spined
spinel
spinelle
spinels
spines
spinet
spinets
spinier
spiniest
spinifex
spinless
spinner
spinners
spinnery
spinney
spinneys
spinnies
spinning
spinny
spinoff
spinoffs
spinor
spinors
spinose
spinous
spinout
spinouts
spins
spinster
spinto
spintos
spinula
spinulae
spinule
spinules
spiny
spiracle
spiraea
spiraeas
spiral
spiraled
spirally
spirals
spirant
spirants
spire
spirea
spireas
spired
spirem
spireme
spiremes
spirems
spires
spirier
spiriest
spirilla
spiring
spirit
spirited
spirits
spiroid
spirt
spirted
spirting
spirts
spirula
spirulae
spirulas
spiry
spit
spital
spitals
spitball
spite
spited
spiteful
spites
spitfire
spiting
spits
spitted
spitter
spitters
spitting
spittle
spittles
spittoon
spitz
spitzes
spiv
spivs
splake
splakes
splash
splashed
splasher
splashes
splashy
splat
splats
splatted
splatter
splay
splayed
splaying
splays
spleen
spleens
spleeny
splendid
splendor
splenia
splenial
splenic
splenii
splenium
splenius
splent
splents
splice
spliced
splicer
splicers
splices
splicing
spliff
spliffs
spline
splined
splines
splining
splint
splinted
splinter
splints
split
splits
splitter
splodge
splodged
splodges
splore
splores
splosh
sploshed
sploshes
splotch
splotchy
splurge
splurged
splurger
splurges
splurgy
splutter
spode
spodes
spoil
spoilage
spoiled
spoiler
spoilers
spoiling
spoils
spoilt
spoke
spoked
spoken
spokes
spoking
spoliate
spondaic
spondee
spondees
sponge
sponged
sponger
spongers
sponges
spongier
spongily
spongin
sponging
spongins
spongy
sponsal
sponsion
sponson
sponsons
sponsor
sponsors
spontoon
spoof
spoofed
spoofer
spoofers
spoofery
spoofing
spoofs
spoofy
spook
spooked
spookery
spookier
spookily
spooking
spookish
spooks
spooky
spool
spooled
spooling
spools
spoon
spooned
spooney
spooneys
spoonful
spoonier
spoonies
spoonily
spooning
spoons
spoony
spoor
spoored
spooring
spoors
sporadic
sporal
spore
spored
spores
sporing
sporoid
sporozoa
sporran
sporrans
sport
sported
sporter
sporters
sportful
sportier
sportif
sportily
sporting
sportive
sports
sporty
sporular
sporule
sporules
spot
spotless
spotlit
spots
spotted
spotter
spotters
spottier
spottily
spotting
spotty
spousal
spousals
spouse
spoused
spouses
spousing
spout
spouted
spouter
spouters
spouting
spouts
spraddle
sprag
sprags
sprain
sprained
sprains
sprang
sprangs
sprat
sprats
sprattle
sprawl
sprawled
sprawler
sprawls
sprawly
spray
sprayed
sprayer
sprayers
spraying
sprays
spread
spreader
spreads
spree
sprees
sprent
sprier
spriest
sprig
sprigged
sprigger
spriggy
spright
sprights
sprigs
spring
springal
springe
springed
springer
springes
springs
springy
sprinkle
sprint
sprinted
sprinter
sprints
sprit
sprite
sprites
sprits
spritz
spritzed
spritzer
spritzes
sprocket
sprout
sprouted
sprouts
spruce
spruced
sprucely
sprucer
spruces
sprucest
sprucier
sprucing
sprucy
sprue
sprues
sprug
sprugs
sprung
spry
spryer
spryest
spryly
spryness
spud
spudded
spudder
spudders
spudding
spuds
spue
spued
spues
spuing
spume
spumed
spumes
spumier
spumiest
spuming
spumone
spumones
spumoni
spumonis
spumous
spumy
spun
spunk
spunked
spunkie
spunkier
spunkies
spunkily
spunking
spunks
spunky
spur
spurgall
spurge
spurges
spurious
spurn
spurned
spurner
spurners
spurning
spurns
spurred
spurrer
spurrers
spurrey
spurreys
spurrier
spurries
spurring
spurry
spurs
spurt
spurted
spurting
spurtle
spurtles
spurts
sputa
sputnik
sputniks
sputter
sputters
sputum
spy
spyglass
spying
squab
squabble
squabby
squabs
squad
squadded
squadron
squads
squalene
squalid
squall
squalled
squaller
squalls
squally
squalor
squalors
squama
squamae
squamate
squamose
squamous
squander
square
squared
squarely
squarer
squarers
squares
squarest
squaring
squarish
squash
squashed
squasher
squashes
squashy
squat
squatly
squats
squatted
squatter
squatty
squaw
squawk
squawked
squawker
squawks
squaws
squeak
squeaked
squeaker
squeaks
squeaky
squeal
squealed
squealer
squeals
squeegee
squeeze
squeezed
squeezer
squeezes
squeg
squegged
squegs
squelch
squelchy
squib
squibbed
squibs
squid
squidded
squids
squiffed
squiffy
squiggle
squiggly
squilgee
squill
squilla
squillae
squillas
squills
squinch
squinny
squint
squinted
squinter
squints
squinty
squire
squired
squireen
squires
squiring
squirish
squirm
squirmed
squirmer
squirms
squirmy
squirrel
squirt
squirted
squirter
squirts
squish
squished
squishes
squishy
squoosh
squooshy
squush
squushed
squushes
sraddha
sraddhas
sradha
sradhas
sri
sris
stab
stabbed
stabber
stabbers
stabbing
stabile
stabiles
stable
stabled
stabler
stablers
stables
stablest
stabling
stablish
stably
stabs
staccati
staccato
stack
stacked
stacker
stackers
stacking
stacks
stackup
stackups
stacte
stactes
staddle
staddles
stade
stades
stadia
stadias
stadium
stadiums
staff
staffed
staffer
staffers
staffing
staffs
stag
stage
staged
stageful
stager
stagers
stages
stagey
staggard
staggart
stagged
stagger
staggers
staggery
staggie
staggier
staggies
stagging
staggy
stagier
stagiest
stagily
staging
stagings
stagnant
stagnate
stags
stagy
staid
staider
staidest
staidly
staig
staigs
stain
stained
stainer
stainers
staining
stains
stair
stairs
stairway
staithe
staithes
stake
staked
stakeout
stakes
staking
stalag
stalags
stale
staled
stalely
staler
stales
stalest
staling
stalk
stalked
stalker
stalkers
stalkier
stalkily
stalking
stalks
stalky
stall
stalled
stalling
stallion
stalls
stalwart
stamen
stamens
stamina
staminal
staminas
stammel
stammels
stammer
stammers
stamp
stamped
stampede
stamper
stampers
stamping
stamps
stance
stances
stanch
stanched
stancher
stanches
stanchly
stand
standard
standby
standbys
standee
standees
stander
standers
standing
standish
standoff
standout
standpat
stands
standup
stane
staned
stanes
stang
stanged
stanging
stangs
stanhope
stanine
stanines
staning
stank
stanks
stannary
stannic
stannite
stannous
stannum
stannums
stanza
stanzaed
stanzaic
stanzas
stapedes
stapelia
stapes
staph
staphs
staple
stapled
stapler
staplers
staples
stapling
star
starch
starched
starches
starchy
stardom
stardoms
stardust
stare
stared
starer
starers
stares
starets
starfish
stargaze
staring
stark
starker
starkers
starkest
starkly
starless
starlet
starlets
starlike
starling
starlit
starnose
starred
starrier
starring
starry
stars
starship
start
started
starter
starters
starting
startle
startled
startler
startles
starts
startsy
startup
startups
starve
starved
starver
starvers
starves
starving
starwort
stases
stash
stashed
stashes
stashing
stasima
stasimon
stasis
stat
statable
statal
statant
state
stated
statedly
stately
stater
staters
states
static
statical
statice
statices
staticky
statics
stating
station
stations
statism
statisms
statist
statists
stative
statives
stator
stators
stats
statuary
statue
statued
statues
stature
statures
status
statuses
statusy
statute
statutes
staumrel
staunch
stave
staved
staves
staving
staw
stay
stayed
stayer
stayers
staying
stays
staysail
stead
steaded
steadied
steadier
steadies
steadily
steading
steads
steady
steak
steaks
steal
stealage
stealer
stealers
stealing
steals
stealth
stealths
stealthy
steam
steamed
steamer
steamers
steamier
steamily
steaming
steams
steamy
steapsin
stearate
stearic
stearin
stearine
stearins
steatite
stedfast
steed
steeds
steek
steeked
steeking
steeks
steel
steeled
steelie
steelier
steelies
steeling
steels
steely
steenbok
steep
steeped
steepen
steepens
steeper
steepers
steepest
steeping
steepish
steeple
steepled
steeples
steeply
steeps
steer
steerage
steered
steerer
steerers
steering
steers
steeve
steeved
steeves
steeving
stegodon
stein
steinbok
steins
stela
stelae
stelai
stelar
stele
stelene
steles
stelic
stella
stellar
stellas
stellate
stellify
stem
stemless
stemlike
stemma
stemmas
stemmata
stemmed
stemmer
stemmers
stemmery
stemmier
stemming
stemmy
stems
stemson
stemsons
stemware
stench
stenches
stenchy
stencil
stencils
stengah
stengahs
steno
stenoky
stenos
stenosed
stenoses
stenosis
stenotic
stentor
stentors
step
stepdame
steplike
steppe
stepped
stepper
steppers
steppes
stepping
steps
stepson
stepsons
stepwise
stere
stereo
stereoed
stereos
steres
steric
sterical
sterigma
sterile
sterlet
sterlets
sterling
stern
sterna
sternal
sterner
sternest
sternite
sternly
sterns
sternson
sternum
sternums
sternway
steroid
steroids
sterol
sterols
stertor
stertors
stet
stets
stetted
stetting
stew
steward
stewards
stewbum
stewbums
stewed
stewing
stewpan
stewpans
stews
stey
sthenia
sthenias
sthenic
stibial
stibine
stibines
stibium
stibiums
stibnite
stich
stichic
stichs
stick
sticked
sticker
stickers
stickful
stickier
stickily
sticking
stickit
stickle
stickled
stickler
stickles
stickman
stickmen
stickout
stickpin
sticks
stickum
stickums
stickup
stickups
sticky
stiction
stied
sties
stiff
stiffed
stiffen
stiffens
stiffer
stiffest
stiffing
stiffish
stiffly
stiffs
stifle
stifled
stifler
stiflers
stifles
stifling
stigma
stigmal
stigmas
stigmata
stilbene
stilbite
stile
stiles
stiletto
still
stilled
stiller
stillest
stillier
stilling
stillman
stillmen
stills
stilly
stilt
stilted
stilting
stilts
stime
stimes
stimied
stimies
stimuli
stimulus
stimy
stimying
sting
stinger
stingers
stingier
stingily
stinging
stingo
stingos
stingray
stings
stingy
stink
stinkard
stinkbug
stinker
stinkers
stinkier
stinking
stinko
stinkpot
stinks
stinky
stint
stinted
stinter
stinters
stinting
stints
stipe
stiped
stipel
stipels
stipend
stipends
stipes
stipites
stipple
stippled
stippler
stipples
stipular
stipule
stipuled
stipules
stir
stirk
stirks
stirp
stirpes
stirps
stirred
stirrer
stirrers
stirring
stirrup
stirrups
stirs
stitch
stitched
stitcher
stitches
stithied
stithies
stithy
stiver
stivers
stoa
stoae
stoai
stoas
stoat
stoats
stob
stobbed
stobbing
stobs
stoccado
stoccata
stock
stockade
stockcar
stocked
stocker
stockers
stockier
stockily
stocking
stockish
stockist
stockman
stockmen
stockpot
stocks
stocky
stodge
stodged
stodges
stodgier
stodgily
stodging
stodgy
stogey
stogeys
stogie
stogies
stogy
stoic
stoical
stoicism
stoics
stoke
stoked
stoker
stokers
stokes
stokesia
stoking
stole
stoled
stolen
stoles
stolid
stolider
stolidly
stollen
stollens
stolon
stolonic
stolons
stolport
stoma
stomach
stomachs
stomachy
stomal
stomas
stomata
stomatal
stomate
stomates
stomatic
stomodea
stomp
stomped
stomper
stompers
stomping
stomps
stonable
stone
stoned
stonefly
stoner
stoners
stones
stoney
stonier
stoniest
stonily
stoning
stonish
stony
stood
stooge
stooged
stooges
stooging
stook
stooked
stooker
stookers
stooking
stooks
stool
stooled
stoolie
stoolies
stooling
stools
stoop
stooped
stooper
stoopers
stooping
stoops
stop
stopbank
stopcock
stope
stoped
stoper
stopers
stopes
stopgap
stopgaps
stoping
stopover
stoppage
stopped
stopper
stoppers
stopping
stopple
stoppled
stopples
stops
stopt
storable
storage
storages
storax
storaxes
store
stored
stores
storey
storeyed
storeys
storied
stories
storing
stork
storks
storm
stormed
stormier
stormily
storming
storms
stormy
story
storying
stoss
stotinka
stotinki
stound
stounded
stounds
stoup
stoups
stour
stoure
stoures
stourie
stours
stoury
stout
stouten
stoutens
stouter
stoutest
stoutish
stoutly
stouts
stove
stover
stovers
stoves
stow
stowable
stowage
stowages
stowaway
stowed
stowing
stowp
stowps
stows
straddle
strafe
strafed
strafer
strafers
strafes
strafing
straggle
straggly
straight
strain
strained
strainer
strains
strait
straiten
straiter
straitly
straits
strake
straked
strakes
stramash
stramony
strand
stranded
strander
strands
strang
strange
stranger
strangle
strap
strapped
strapper
straps
strass
strasses
strata
stratal
stratas
strategy
strath
straths
strati
stratify
stratous
stratum
stratums
stratus
stravage
stravaig
straw
strawed
strawhat
strawier
strawing
straws
strawy
stray
strayed
strayer
strayers
straying
strays
streak
streaked
streaker
streaks
streaky
stream
streamed
streamer
streams
streamy
streek
streeked
streeker
streeks
streel
streeled
streels
street
streets
strength
strep
streps
stress
stressed
stresses
stressor
stretch
stretchy
stretta
strettas
strette
stretti
stretto
strettos
streusel
strew
strewed
strewer
strewers
strewing
strewn
strews
stria
striae
striate
striated
striates
strick
stricken
strickle
stricks
strict
stricter
strictly
stridden
stride
strident
strider
striders
strides
striding
stridor
stridors
strife
strifes
strigil
strigils
strigose
strike
striker
strikers
strikes
striking
string
stringed
stringer
strings
stringy
strip
stripe
striped
striper
stripers
stripes
stripier
striping
stripped
stripper
strips
stript
stripy
strive
strived
striven
striver
strivers
strives
striving
strobe
strobes
strobic
strobil
strobila
strobile
strobili
strobils
strode
stroke
stroked
stroker
strokers
strokes
stroking
stroll
strolled
stroller
strolls
stroma
stromal
stromata
strong
stronger
strongly
strongyl
strontia
strontic
strook
strop
strophe
strophes
strophic
stropped
stropper
stroppy
strops
stroud
strouds
strove
strow
strowed
strowing
strown
strows
stroy
stroyed
stroyer
stroyers
stroying
stroys
struck
strucken
strudel
strudels
struggle
strum
struma
strumae
strumas
strummed
strummer
strumose
strumous
strumpet
strums
strung
strunt
strunted
strunts
strut
struts
strutted
strutter
stub
stubbed
stubbier
stubbily
stubbing
stubble
stubbled
stubbles
stubbly
stubborn
stubby
stubs
stucco
stuccoed
stuccoer
stuccoes
stuccos
stuck
stud
studbook
studded
studdie
studdies
studding
student
students
studfish
studied
studier
studiers
studies
studio
studios
studious
studlier
studly
studs
studwork
study
studying
stuff
stuffed
stuffer
stuffers
stuffier
stuffily
stuffing
stuffs
stuffy
stuiver
stuivers
stull
stulls
stultify
stum
stumble
stumbled
stumbler
stumbles
stummed
stumming
stump
stumpage
stumped
stumper
stumpers
stumpier
stumping
stumps
stumpy
stums
stun
stung
stunk
stunned
stunner
stunners
stunning
stuns
stunsail
stunt
stunted
stunting
stuntman
stuntmen
stunts
stupa
stupas
stupe
stupefy
stupes
stupid
stupider
stupidly
stupids
stupor
stupors
sturdied
sturdier
sturdies
sturdily
sturdy
sturgeon
sturt
sturts
stutter
stutters
sty
stye
styed
styes
stygian
stying
stylar
stylate
style
styled
styler
stylers
styles
stylet
stylets
styli
styling
stylings
stylise
stylised
styliser
stylises
stylish
stylist
stylists
stylite
stylites
stylitic
stylize
stylized
stylizer
stylizes
styloid
stylus
styluses
stymie
stymied
stymies
stymy
stymying
stypsis
styptic
styptics
styrax
styraxes
styrene
styrenes
suable
suably
suasion
suasions
suasive
suasory
suave
suavely
suaver
suavest
suavity
sub
suba
subabbot
subacid
subacrid
subacute
subadar
subadars
subadult
subagent
subah
subahdar
subahs
subalar
subarea
subareas
subarid
subas
subatom
subatoms
subaxial
subbase
subbases
subbasin
subbass
subbed
subbing
subbings
subblock
subbreed
subcaste
subcause
subcell
subcells
subchief
subclan
subclans
subclass
subclerk
subcode
subcodes
subcool
subcools
subcult
subcults
subcutes
subcutis
subdean
subdeans
subdeb
subdebs
subdepot
subdual
subduals
subduce
subduced
subduces
subduct
subducts
subdue
subdued
subduer
subduers
subdues
subduing
subdural
subecho
subedit
subedits
subentry
subepoch
suber
suberect
suberic
suberin
suberins
suberise
suberize
suberose
suberous
subers
subfield
subfile
subfiles
subfix
subfixes
subfloor
subfluid
subframe
subfusc
subgenre
subgenus
subgoal
subgoals
subgrade
subgraph
subgroup
subgum
subgums
subhead
subheads
subhuman
subhumid
subidea
subideas
subindex
subitem
subitems
subito
subject
subjects
subjoin
subjoins
sublate
sublated
sublates
sublease
sublet
sublets
sublevel
sublime
sublimed
sublimer
sublimes
subline
sublines
sublot
sublots
sublunar
submenu
submenus
submerge
submerse
submiss
submit
submits
subnasal
subnet
subnets
subniche
subnodal
suboptic
suboral
suborder
suborn
suborned
suborner
suborns
suboval
subovate
suboxide
subpanel
subpar
subpart
subparts
subpena
subpenas
subphase
subphyla
subplot
subplots
subpoena
subpolar
subpubic
subrace
subraces
subrent
subrents
subring
subrings
subrule
subrules
subs
subsale
subsales
subscale
subsea
subsect
subsects
subsense
subsere
subseres
subserve
subset
subsets
subshaft
subshell
subshrub
subside
subsided
subsider
subsides
subsidy
subsist
subsists
subsite
subsites
subskill
subsoil
subsoils
subsolar
subsonic
subspace
substage
substate
subsume
subsumed
subsumes
subtask
subtasks
subtaxa
subtaxon
subteen
subteens
subtend
subtends
subtest
subtests
subtext
subtexts
subtheme
subtile
subtiler
subtilin
subtilty
subtitle
subtle
subtler
subtlest
subtlety
subtly
subtone
subtones
subtonic
subtopia
subtopic
subtotal
subtract
subtrend
subtribe
subtunic
subtype
subtypes
subulate
subunit
subunits
suburb
suburban
suburbed
suburbia
suburbs
subvene
subvened
subvenes
subvert
subverts
subvicar
subviral
subvocal
subway
subwayed
subways
subworld
subzero
subzone
subzones
succah
succahs
succeed
succeeds
success
succinct
succinic
succinyl
succor
succored
succorer
succors
succory
succoth
succour
succours
succuba
succubae
succubi
succubus
succumb
succumbs
succuss
such
suchlike
suchness
suck
sucked
sucker
suckered
suckers
suckfish
sucking
suckle
suckled
suckler
sucklers
suckles
suckless
suckling
sucks
sucrase
sucrases
sucre
sucres
sucrose
sucroses
suction
suctions
sudaria
sudaries
sudarium
sudary
sudation
sudatory
sudd
sudden
suddenly
suddens
sudds
sudor
sudoral
sudors
suds
sudsed
sudser
sudsers
sudses
sudsier
sudsiest
sudsing
sudsless
sudsy
sue
sued
suede
sueded
suedes
sueding
suer
suers
sues
suet
suets
suety
suffari
suffaris
suffer
suffered
sufferer
suffers
suffice
sufficed
sufficer
suffices
suffix
suffixal
suffixed
suffixes
sufflate
suffrage
suffuse
suffused
suffuses
sugar
sugared
sugarier
sugaring
sugars
sugary
suggest
suggests
sugh
sughed
sughing
sughs
suicidal
suicide
suicided
suicides
suing
suint
suints
suit
suitable
suitably
suitcase
suite
suited
suiter
suiters
suites
suiting
suitings
suitlike
suitor
suitors
suits
sukiyaki
sukkah
sukkahs
sukkot
sukkoth
sulcal
sulcate
sulcated
sulci
sulcus
suldan
suldans
sulfa
sulfas
sulfate
sulfated
sulfates
sulfid
sulfide
sulfides
sulfids
sulfinyl
sulfite
sulfites
sulfitic
sulfo
sulfone
sulfones
sulfonic
sulfonyl
sulfur
sulfured
sulfuret
sulfuric
sulfurs
sulfury
sulfuryl
sulk
sulked
sulker
sulkers
sulkier
sulkies
sulkiest
sulkily
sulking
sulks
sulky
sullage
sullages
sullen
sullener
sullenly
sullied
sullies
sully
sullying
sulpha
sulphas
sulphate
sulphid
sulphide
sulphids
sulphite
sulphone
sulphur
sulphurs
sulphury
sultan
sultana
sultanas
sultanic
sultans
sultrier
sultrily
sultry
sulu
sulus
sum
sumac
sumach
sumachs
sumacs
sumless
summa
summable
summae
summand
summands
summary
summas
summate
summated
summates
summed
summer
summered
summerly
summers
summery
summing
summit
summital
summited
summitry
summits
summon
summoned
summoner
summons
sumo
sumos
sump
sumps
sumpter
sumpters
sumpweed
sums
sun
sunback
sunbaked
sunbath
sunbathe
sunbaths
sunbeam
sunbeams
sunbeamy
sunbelt
sunbelts
sunbird
sunbirds
sunblock
sunbow
sunbows
sunburn
sunburns
sunburnt
sunburst
sunchoke
sundae
sundaes
sundeck
sundecks
sunder
sundered
sunderer
sunders
sundew
sundews
sundial
sundials
sundog
sundogs
sundown
sundowns
sundress
sundries
sundrops
sundry
sunfast
sunfish
sung
sunglass
sunglow
sunglows
sunk
sunken
sunket
sunkets
sunlamp
sunlamps
sunland
sunlands
sunless
sunlight
sunlike
sunlit
sunn
sunna
sunnah
sunnahs
sunnas
sunned
sunnier
sunniest
sunnily
sunning
sunns
sunny
sunporch
sunproof
sunrise
sunrises
sunroof
sunroofs
sunroom
sunrooms
suns
sunscald
sunset
sunsets
sunshade
sunshine
sunshiny
sunspot
sunspots
sunstone
sunsuit
sunsuits
suntan
suntans
sunup
sunups
sunward
sunwards
sunwise
sup
supe
super
superadd
superb
superbad
superber
superbly
supercar
supercop
supered
superego
superfan
superfix
superhit
superhot
supering
superior
superjet
superlay
superlie
superman
supermen
supermom
supernal
superpro
supers
supersex
superspy
supertax
supes
supinate
supine
supinely
supines
supped
supper
suppers
supping
supplant
supple
suppled
supplely
suppler
supples
supplest
supplied
supplier
supplies
suppling
supply
support
supports
supposal
suppose
supposed
supposer
supposes
suppress
supra
supreme
supremer
supremo
supremos
sups
suq
suqs
sura
surah
surahs
sural
suras
surbase
surbased
surbases
surcease
surcoat
surcoats
surd
surds
sure
surefire
surely
sureness
surer
surest
sureties
surety
surf
surfable
surface
surfaced
surfacer
surfaces
surfbird
surfboat
surfed
surfeit
surfeits
surfer
surfers
surffish
surfier
surfiest
surfing
surfings
surflike
surfs
surfy
surge
surged
surgeon
surgeons
surger
surgers
surgery
surges
surgical
surging
surgy
suricate
surimi
surlier
surliest
surlily
surly
surmise
surmised
surmiser
surmises
surmount
surname
surnamed
surnamer
surnames
surpass
surplice
surplus
surprint
surprise
surprize
surra
surras
surreal
surrey
surreys
surround
surroyal
surtax
surtaxed
surtaxes
surtout
surtouts
surveil
surveils
survey
surveyed
surveyor
surveys
survival
survive
survived
surviver
survives
survivor
sushi
sushis
suslik
susliks
suspect
suspects
suspend
suspends
suspense
suspire
suspired
suspires
suss
sussed
susses
sussing
sustain
sustains
susurrus
sutler
sutlers
sutra
sutras
sutta
suttas
suttee
suttees
sutural
suture
sutured
sutures
suturing
suzerain
svaraj
svarajes
svedberg
svelte
sveltely
svelter
sveltest
swab
swabbed
swabber
swabbers
swabbie
swabbies
swabbing
swabby
swabs
swacked
swaddle
swaddled
swaddles
swag
swage
swaged
swager
swagers
swages
swagged
swagger
swaggers
swaggie
swaggies
swagging
swaging
swagman
swagmen
swags
swail
swails
swain
swainish
swains
swale
swales
swallow
swallows
swam
swami
swamies
swamis
swamp
swamped
swamper
swampers
swampier
swamping
swampish
swamps
swampy
swamy
swan
swang
swanherd
swank
swanked
swanker
swankest
swankier
swankily
swanking
swanks
swanky
swanlike
swanned
swannery
swanning
swanpan
swanpans
swans
swanskin
swap
swapped
swapper
swappers
swapping
swaps
swaraj
swarajes
sward
swarded
swarding
swards
sware
swarf
swarfs
swarm
swarmed
swarmer
swarmers
swarming
swarms
swart
swarth
swarths
swarthy
swarty
swash
swashed
swasher
swashers
swashes
swashing
swastica
swastika
swat
swatch
swatches
swath
swathe
swathed
swather
swathers
swathes
swathing
swaths
swats
swatted
swatter
swatters
swatting
sway
swayable
swayback
swayed
swayer
swayers
swayful
swaying
sways
swear
swearer
swearers
swearing
swears
sweat
sweatbox
sweated
sweater
sweaters
sweatier
sweatily
sweating
sweats
sweaty
swede
swedes
sweenies
sweeny
sweep
sweeper
sweepers
sweepier
sweeping
sweeps
sweepy
sweer
sweet
sweeten
sweetens
sweeter
sweetest
sweetie
sweeties
sweeting
sweetish
sweetly
sweets
sweetsop
swell
swelled
sweller
swellest
swelling
swells
swelter
swelters
sweltry
swept
swerve
swerved
swerver
swervers
swerves
swerving
sweven
swevens
swidden
swiddens
swift
swifter
swifters
swiftest
swiftlet
swiftly
swifts
swig
swigged
swigger
swiggers
swigging
swigs
swill
swilled
swiller
swillers
swilling
swills
swim
swimmer
swimmers
swimmier
swimmily
swimming
swimmy
swims
swimsuit
swimwear
swindle
swindled
swindler
swindles
swine
swinepox
swing
swingby
swingbys
swinge
swinged
swinger
swingers
swinges
swingier
swinging
swingle
swingled
swingles
swingman
swingmen
swings
swingy
swinish
swink
swinked
swinking
swinks
swinney
swinneys
swipe
swiped
swipes
swiping
swiple
swiples
swipple
swipples
swirl
swirled
swirlier
swirling
swirls
swirly
swish
swished
swisher
swishers
swishes
swishier
swishing
swishy
swiss
swisses
switch
switched
switcher
switches
swith
swithe
swither
swithers
swithly
swive
swived
swivel
swiveled
swivels
swives
swivet
swivets
swiving
swizzle
swizzled
swizzler
swizzles
swob
swobbed
swobber
swobbers
swobbing
swobs
swollen
swoon
swooned
swooner
swooners
swooning
swoons
swoop
swooped
swooper
swoopers
swooping
swoops
swoosh
swooshed
swooshes
swop
swopped
swopping
swops
sword
swordman
swordmen
swords
swore
sworn
swot
swots
swotted
swotter
swotters
swotting
swoun
swound
swounded
swounds
swouned
swouning
swouns
swum
swung
sybarite
sybo
syboes
sycamine
sycamore
syce
sycee
sycees
syces
sycomore
syconia
syconium
sycoses
sycosis
syenite
syenites
syenitic
syke
sykes
syli
sylis
syllabi
syllabic
syllable
syllabub
syllabus
sylph
sylphic
sylphid
sylphids
sylphish
sylphs
sylphy
sylva
sylvae
sylvan
sylvans
sylvas
sylvatic
sylvin
sylvine
sylvines
sylvins
sylvite
sylvites
symbion
symbions
symbiont
symbiot
symbiote
symbiots
symbol
symboled
symbolic
symbols
symmetry
sympathy
sympatry
symphony
sympodia
symposia
symptom
symptoms
syn
synagog
synagogs
synanon
synanons
synapse
synapsed
synapses
synapsid
synapsis
synaptic
sync
syncarp
syncarps
syncarpy
synced
synch
synched
synching
synchro
synchros
synchs
syncing
syncline
syncom
syncoms
syncopal
syncope
syncopes
syncopic
syncs
syncytia
syndeses
syndesis
syndet
syndetic
syndets
syndic
syndical
syndics
syndrome
syne
synectic
synergia
synergic
synergid
synergy
synesis
synfuel
synfuels
syngamic
syngamy
syngas
syngases
synod
synodal
synodic
synods
synonym
synonyme
synonyms
synonymy
synopses
synopsis
synoptic
synovia
synovial
synovias
syntagma
syntax
syntaxes
synth
synths
syntonic
syntony
synura
synurae
syph
sypher
syphered
syphers
syphilis
syphon
syphoned
syphons
syphs
syren
syrens
syringa
syringas
syringe
syringed
syringes
syrinx
syrinxes
syrphian
syrphid
syrphids
syrup
syrups
syrupy
sysop
sysops
system
systemic
systems
systole
systoles
systolic
syzygal
syzygial
syzygies
syzygy
ta
tab
tabanid
tabanids
tabard
tabarded
tabards
tabaret
tabarets
tabbed
tabbied
tabbies
tabbing
tabbis
tabbises
tabby
tabbying
taber
tabered
tabering
tabers
tabes
tabetic
tabetics
tabid
tabla
tablas
table
tableau
tableaus
tableaux
tabled
tableful
tables
tablet
tableted
tabletop
tablets
tabling
tabloid
tabloids
taboo
tabooed
tabooing
tabooley
taboos
tabor
tabored
taborer
taborers
taboret
taborets
taborin
taborine
taboring
taborins
tabors
tabouli
taboulis
tabour
taboured
tabourer
tabouret
tabours
tabs
tabu
tabued
tabuing
tabular
tabulate
tabuli
tabulis
tabun
tabuns
tabus
tace
taces
tacet
tach
tache
taches
tachinid
tachism
tachisme
tachisms
tachist
tachiste
tachists
tachs
tachyon
tachyons
tacit
tacitly
taciturn
tack
tacked
tacker
tackers
tacket
tackets
tackey
tackier
tackiest
tackify
tackily
tacking
tackle
tackled
tackler
tacklers
tackles
tackless
tackling
tacks
tacky
tacnode
tacnodes
taco
taconite
tacos
tact
tactful
tactic
tactical
tactics
tactile
taction
tactions
tactless
tacts
tactual
tad
tadpole
tadpoles
tads
tae
tael
taels
taenia
taeniae
taenias
taffarel
tafferel
taffeta
taffetas
taffia
taffias
taffies
taffrail
taffy
tafia
tafias
tag
tagalong
tagboard
tagged
tagger
taggers
tagging
taglike
tagmeme
tagmemes
tagmemic
tagrag
tagrags
tags
tahini
tahinis
tahr
tahrs
tahsil
tahsils
taiga
taigas
taiglach
tail
tailback
tailbone
tailcoat
tailed
tailer
tailers
tailfan
tailfans
tailgate
tailing
tailings
taillamp
taille
tailles
tailless
tailleur
taillike
tailor
tailored
tailors
tailpipe
tailrace
tails
tailskid
tailspin
tailwind
tain
tains
taint
tainted
tainting
taints
taipan
taipans
taj
tajes
taka
takable
takahe
takahes
take
takeable
takeaway
takedown
taken
takeoff
takeoffs
takeout
takeouts
takeover
taker
takers
takes
takeup
takeups
takin
taking
takingly
takings
takins
tala
talapoin
talar
talaria
talars
talas
talc
talced
talcing
talcked
talcking
talcky
talcose
talcous
talcs
talcum
talcums
tale
talent
talented
talents
taler
talers
tales
talesman
talesmen
taleysim
tali
talion
talions
taliped
talipeds
talipes
talipot
talipots
talisman
talk
talkable
talked
talker
talkers
talkie
talkier
talkies
talkiest
talking
talkings
talks
talky
tall
tallage
tallaged
tallages
tallboy
tallboys
taller
tallest
tallied
tallier
talliers
tallies
tallis
tallish
tallisim
tallit
tallith
tallitim
tallness
tallol
tallols
tallow
tallowed
tallows
tallowy
tally
tallyho
tallyhos
tallying
tallyman
tallymen
talmudic
talon
taloned
talons
talooka
talookas
taluk
taluka
talukas
taluks
talus
taluses
tam
tamable
tamal
tamale
tamales
tamals
tamandu
tamandua
tamandus
tamarack
tamarao
tamaraos
tamarau
tamaraus
tamari
tamarin
tamarind
tamarins
tamaris
tamarisk
tamasha
tamashas
tambac
tambacs
tambak
tambaks
tambala
tambalas
tambour
tamboura
tambours
tambur
tambura
tamburas
tamburs
tame
tameable
tamed
tamein
tameins
tameless
tamely
tameness
tamer
tamers
tames
tamest
taming
tamis
tamises
tammie
tammies
tammy
tamp
tampala
tampalas
tampan
tampans
tamped
tamper
tampered
tamperer
tampers
tamping
tampion
tampions
tampon
tamponed
tampons
tamps
tams
tan
tanager
tanagers
tanbark
tanbarks
tandem
tandems
tandoor
tandoori
tang
tanged
tangelo
tangelos
tangence
tangency
tangent
tangents
tangible
tangibly
tangier
tangiest
tanging
tangle
tangled
tangler
tanglers
tangles
tanglier
tangling
tangly
tango
tangoed
tangoing
tangos
tangram
tangrams
tangs
tangy
tanist
tanistry
tanists
tank
tanka
tankage
tankages
tankard
tankards
tankas
tanked
tanker
tankers
tankful
tankfuls
tanking
tanklike
tanks
tankship
tannable
tannage
tannages
tannate
tannates
tanned
tanner
tanners
tannery
tannest
tannic
tannin
tanning
tannings
tannins
tannish
tanrec
tanrecs
tans
tansies
tansy
tantalic
tantalum
tantalus
tantara
tantaras
tantivy
tanto
tantra
tantras
tantric
tantrum
tantrums
tanuki
tanukis
tanyard
tanyards
tao
taos
tap
tapa
tapadera
tapadero
tapalo
tapalos
tapas
tape
taped
tapeless
tapelike
tapeline
taper
tapered
taperer
taperers
tapering
tapers
tapes
tapestry
tapeta
tapetal
tapetum
tapeworm
taphole
tapholes
taphouse
taping
tapioca
tapiocas
tapir
tapirs
tapis
tapises
tapped
tapper
tappers
tappet
tappets
tapping
tappings
taproom
taprooms
taproot
taproots
taps
tapster
tapsters
tar
tarama
taramas
tarantas
tarboosh
tarbush
tardier
tardies
tardiest
tardily
tardo
tardy
tardyon
tardyons
tare
tared
tares
targe
targes
target
targeted
targets
tariff
tariffed
tariffs
taring
tarlatan
tarletan
tarmac
tarmacs
tarn
tarnal
tarnally
tarnish
tarns
taro
taroc
tarocs
tarok
taroks
taros
tarot
tarots
tarp
tarpan
tarpans
tarpaper
tarpon
tarpons
tarps
tarragon
tarre
tarred
tarres
tarried
tarrier
tarriers
tarries
tarriest
tarring
tarry
tarrying
tars
tarsal
tarsals
tarsi
tarsia
tarsias
tarsier
tarsiers
tarsus
tart
tartan
tartana
tartanas
tartans
tartar
tartaric
tartars
tarted
tarter
tartest
tarting
tartish
tartlet
tartlets
tartly
tartness
tartrate
tarts
tartufe
tartufes
tartuffe
tarty
tarweed
tarweeds
tarzan
tarzans
tas
task
tasked
tasking
tasks
taskwork
tass
tasse
tassel
tasseled
tassels
tasses
tasset
tassets
tassie
tassies
tastable
taste
tasted
tasteful
taster
tasters
tastes
tastier
tastiest
tastily
tasting
tasty
tat
tatami
tatamis
tatar
tatars
tate
tater
taters
tates
tatouay
tatouays
tats
tatted
tatter
tattered
tatters
tattie
tattier
tatties
tattiest
tattily
tatting
tattings
tattle
tattled
tattler
tattlers
tattles
tattling
tattoo
tattooed
tattooer
tattoos
tatty
tau
taught
taunt
taunted
taunter
taunters
taunting
taunts
taupe
taupes
taurine
taurines
taus
taut
tautaug
tautaugs
tauted
tauten
tautened
tautens
tauter
tautest
tauting
tautly
tautness
tautog
tautogs
tautomer
tautonym
tauts
tav
tavern
taverna
tavernas
taverner
taverns
tavs
taw
tawdrier
tawdries
tawdrily
tawdry
tawed
tawer
tawers
tawie
tawing
tawney
tawneys
tawnier
tawnies
tawniest
tawnily
tawny
tawpie
tawpies
taws
tawse
tawsed
tawses
tawsing
tax
taxa
taxable
taxables
taxably
taxation
taxed
taxeme
taxemes
taxemic
taxer
taxers
taxes
taxi
taxicab
taxicabs
taxied
taxies
taxiing
taximan
taximen
taxing
taxingly
taxis
taxite
taxites
taxitic
taxiway
taxiways
taxless
taxman
taxmen
taxon
taxonomy
taxons
taxpaid
taxpayer
taxus
taxwise
taxying
tazza
tazzas
tazze
tea
teaberry
teaboard
teabowl
teabowls
teabox
teaboxes
teacake
teacakes
teacart
teacarts
teach
teacher
teachers
teaches
teaching
teacup
teacups
teahouse
teak
teaks
teakwood
teal
tealike
teals
team
teamaker
teamed
teaming
teammate
teams
teamster
teamwork
teapot
teapots
teapoy
teapoys
tear
tearable
tearaway
teardown
teardrop
teared
tearer
tearers
tearful
teargas
tearier
teariest
tearily
tearing
tearless
tearoom
tearooms
tears
teary
teas
tease
teased
teasel
teaseled
teaseler
teasels
teaser
teasers
teases
teashop
teashops
teasing
teaspoon
teat
teated
teatime
teatimes
teats
teaware
teawares
teazel
teazeled
teazels
teazle
teazled
teazles
teazling
teched
techie
techier
techies
techiest
techily
technic
technics
techy
tecta
tectal
tectite
tectites
tectonic
tectrix
tectum
ted
tedded
tedder
tedders
teddies
tedding
teddy
tedious
tedium
tediums
teds
tee
teed
teeing
teel
teels
teem
teemed
teemer
teemers
teeming
teems
teen
teenage
teenaged
teenager
teener
teeners
teenful
teenier
teeniest
teens
teensier
teensy
teentsy
teeny
teenybop
teepee
teepees
tees
teeter
teetered
teeters
teeth
teethe
teethed
teether
teethers
teethes
teething
teetotal
teetotum
teff
teffs
tefillin
teg
tegmen
tegmenta
tegmina
tegminal
tegs
tegua
teguas
tegular
tegumen
tegument
tegumina
teiglach
teiid
teiids
teind
teinds
tektite
tektites
tektitic
tel
tela
telae
telamon
tele
telecast
teledu
teledus
telefilm
telega
telegas
telegony
telegram
teleman
telemark
telemen
teleost
teleosts
telepath
teleplay
teleport
teleran
telerans
teles
teleses
telesis
telestic
teletext
telethon
teleview
televise
telex
telexed
telexes
telexing
telfer
telfered
telfers
telford
telfords
telia
telial
telic
telium
tell
tellable
teller
tellers
tellies
telling
tells
telltale
telluric
telly
tellys
teloi
telome
telomere
telomes
telomic
telos
telpher
telphers
tels
telson
telsonic
telsons
temblor
temblors
temerity
temp
temped
tempeh
tempehs
temper
tempera
temperas
tempered
temperer
tempers
tempest
tempests
tempi
temping
templar
templars
template
temple
templed
temples
templet
templets
tempo
temporal
tempos
temps
tempt
tempted
tempter
tempters
tempting
tempts
tempura
tempuras
ten
tenable
tenably
tenace
tenaces
tenacity
tenacula
tenail
tenaille
tenails
tenancy
tenant
tenanted
tenantry
tenants
tench
tenches
tend
tendance
tended
tendence
tendency
tender
tendered
tenderer
tenderly
tenders
tending
tendon
tendons
tendril
tendrils
tends
tenebrae
tenement
tenesmic
tenesmus
tenet
tenets
tenfold
tenfolds
tenia
teniae
tenias
teniases
teniasis
tenner
tenners
tennies
tennis
tennises
tennist
tennists
tenon
tenoned
tenoner
tenoners
tenoning
tenons
tenor
tenorist
tenorite
tenors
tenotomy
tenour
tenours
tenpence
tenpenny
tenpin
tenpins
tenrec
tenrecs
tens
tense
tensed
tensely
tenser
tenses
tensest
tensible
tensibly
tensile
tensing
tension
tensions
tensity
tensive
tensor
tensors
tent
tentacle
tentage
tentages
tented
tenter
tentered
tenters
tenth
tenthly
tenths
tentie
tentier
tentiest
tenting
tentless
tentlike
tents
tenty
tenues
tenuis
tenuity
tenuous
tenure
tenured
tenures
tenurial
tenuti
tenuto
tenutos
teocalli
teopan
teopans
teosinte
tepa
tepal
tepals
tepas
tepee
tepees
tepefied
tepefies
tepefy
tephra
tephras
tephrite
tepid
tepidity
tepidly
tepoy
tepoys
tequila
tequilas
terai
terais
teraohm
teraohms
teraph
teraphim
teratism
teratoid
teratoma
terawatt
terbia
terbias
terbic
terbium
terbiums
terce
tercel
tercelet
tercels
terces
tercet
tercets
terebene
terebic
teredo
teredos
terefah
terete
terga
tergal
tergite
tergites
tergum
teriyaki
term
termed
termer
termers
terminal
terming
termini
terminus
termite
termites
termitic
termless
termly
termor
termors
terms
termtime
tern
ternary
ternate
terne
ternes
ternion
ternions
terns
terpene
terpenes
terpenic
terpinol
terra
terrace
terraced
terraces
terrae
terrain
terrains
terrane
terranes
terrapin
terraria
terras
terrases
terrazzo
terreen
terreens
terrella
terrene
terrenes
terret
terrets
terrible
terribly
terrier
terriers
terries
terrific
terrify
terrine
terrines
territ
territs
terror
terrors
terry
terse
tersely
terser
tersest
tertial
tertials
tertian
tertians
tertiary
tesla
teslas
tessera
tesserae
test
testa
testable
testacy
testae
testate
testates
testator
tested
testee
testees
tester
testers
testes
testicle
testier
testiest
testify
testily
testing
testis
teston
testons
testoon
testoons
tests
testudo
testudos
testy
tet
tetanal
tetanic
tetanics
tetanies
tetanise
tetanize
tetanoid
tetanus
tetany
tetched
tetchier
tetchily
tetchy
teth
tether
tethered
tethers
teths
tetotum
tetotums
tetra
tetracid
tetrad
tetradic
tetrads
tetragon
tetramer
tetrapod
tetrarch
tetras
tetrode
tetrodes
tetroxid
tetryl
tetryls
tets
tetter
tetters
teuch
teugh
teughly
tew
tewed
tewing
tews
texas
texases
text
textbook
textile
textiles
textless
texts
textual
textuary
textural
texture
textured
textures
thack
thacked
thacking
thacks
thae
thairm
thairms
thalami
thalamic
thalamus
thaler
thalers
thalli
thallic
thallium
thalloid
thallous
thallus
than
thanage
thanages
thanatos
thane
thanes
thank
thanked
thanker
thankers
thankful
thanking
thanks
tharm
tharms
that
thataway
thatch
thatched
thatcher
thatches
thatchy
thaw
thawed
thawer
thawers
thawing
thawless
thaws
the
thearchy
theater
theaters
theatre
theatres
theatric
thebaine
thebe
theca
thecae
thecal
thecate
thee
theelin
theelins
theelol
theelols
theft
thefts
thegn
thegnly
thegns
thein
theine
theines
theins
their
theirs
theism
theisms
theist
theistic
theists
thelitis
them
thematic
theme
themed
themes
theming
then
thenage
thenages
thenal
thenar
thenars
thence
thens
theocrat
theodicy
theogony
theolog
theologs
theology
theonomy
theorbo
theorbos
theorem
theorems
theories
theorise
theorist
theorize
theory
therapy
there
thereat
thereby
therefor
therein
theremin
thereof
thereon
theres
thereto
theriac
theriaca
theriacs
therm
thermae
thermal
thermals
therme
thermel
thermels
thermes
thermic
thermion
thermite
thermos
therms
theroid
theropod
thesauri
these
theses
thesis
thespian
theta
thetas
thetic
thetical
theurgic
theurgy
thew
thewier
thewiest
thewless
thews
thewy
they
thiamin
thiamine
thiamins
thiazide
thiazin
thiazine
thiazins
thiazol
thiazole
thiazols
thick
thicken
thickens
thicker
thickest
thicket
thickets
thickety
thickish
thickly
thicks
thickset
thief
thieve
thieved
thievery
thieves
thieving
thievish
thigh
thighed
thighs
thill
thills
thimble
thimbles
thin
thinclad
thindown
thine
thing
things
think
thinker
thinkers
thinking
thinks
thinly
thinned
thinner
thinners
thinness
thinnest
thinning
thinnish
thins
thio
thiol
thiolic
thiols
thionate
thionic
thionin
thionine
thionins
thionyl
thionyls
thiophen
thiotepa
thiourea
thir
thiram
thirams
third
thirdly
thirds
thirl
thirlage
thirled
thirling
thirls
thirst
thirsted
thirster
thirsts
thirsty
thirteen
thirties
thirty
this
thistle
thistles
thistly
thither
tho
thole
tholed
tholepin
tholes
tholing
tholoi
tholos
thong
thonged
thongs
thoracal
thoraces
thoracic
thorax
thoraxes
thoria
thorias
thoric
thorite
thorites
thorium
thoriums
thorn
thorned
thornier
thornily
thorning
thorns
thorny
thoro
thoron
thorons
thorough
thorp
thorpe
thorpes
thorps
those
thou
thoued
though
thought
thoughts
thouing
thous
thousand
thowless
thraldom
thrall
thralled
thralls
thrash
thrashed
thrasher
thrashes
thrave
thraves
thraw
thrawart
thrawed
thrawing
thrawn
thrawnly
thraws
thread
threaded
threader
threads
thready
threap
threaped
threaper
threaps
threat
threated
threaten
threats
three
threep
threeped
threeps
threes
threnode
threnody
thresh
threshed
thresher
threshes
threw
thrice
thrift
thrifts
thrifty
thrill
thrilled
thriller
thrills
thrip
thrips
thrive
thrived
thriven
thriver
thrivers
thrives
thriving
thro
throat
throated
throats
throaty
throb
throbbed
throbber
throbs
throe
throes
thrombi
thrombin
thrombus
throne
throned
thrones
throng
thronged
throngs
throning
throstle
throttle
through
throve
throw
thrower
throwers
throwing
thrown
throws
thru
thrum
thrummed
thrummer
thrummy
thrums
thruput
thruputs
thrush
thrushes
thrust
thrusted
thruster
thrustor
thrusts
thruway
thruways
thud
thudded
thudding
thuds
thug
thuggee
thuggees
thuggery
thuggish
thugs
thuja
thujas
thulia
thulias
thulium
thuliums
thumb
thumbed
thumbing
thumbkin
thumbnut
thumbs
thump
thumped
thumper
thumpers
thumping
thumps
thunder
thunders
thundery
thunk
thunked
thunking
thunks
thurible
thurifer
thurl
thurls
thus
thusly
thuya
thuyas
thwack
thwacked
thwacker
thwacks
thwart
thwarted
thwarter
thwartly
thwarts
thy
thyme
thymes
thymey
thymi
thymic
thymier
thymiest
thymine
thymines
thymol
thymols
thymosin
thymus
thymuses
thymy
thyreoid
thyroid
thyroids
thyroxin
thyrse
thyrses
thyrsi
thyrsoid
thyrsus
thyself
ti
tiara
tiaraed
tiaras
tibia
tibiae
tibial
tibias
tic
tical
ticals
tick
ticked
ticker
tickers
ticket
ticketed
tickets
ticking
tickings
tickle
tickled
tickler
ticklers
tickles
tickling
ticklish
ticks
tickseed
ticktack
ticktock
tics
tictac
tictacs
tictoc
tictocs
tidal
tidally
tidbit
tidbits
tiddler
tiddlers
tiddly
tide
tided
tideland
tideless
tidelike
tidemark
tiderip
tiderips
tides
tideway
tideways
tidied
tidier
tidiers
tidies
tidiest
tidily
tidiness
tiding
tidings
tidy
tidying
tidytips
tie
tieback
tiebacks
tieclasp
tied
tieing
tieless
tiepin
tiepins
tier
tierce
tierced
tiercel
tiercels
tierces
tiered
tiering
tiers
ties
tiff
tiffany
tiffed
tiffin
tiffined
tiffing
tiffins
tiffs
tiger
tigereye
tigerish
tigers
tight
tighten
tightens
tighter
tightest
tightly
tights
tightwad
tiglon
tiglons
tigon
tigons
tigress
tigrish
tike
tikes
tiki
tikis
til
tilak
tilaks
tilapia
tilapias
tilbury
tilde
tildes
tile
tiled
tilefish
tilelike
tiler
tilers
tiles
tiling
tilings
till
tillable
tillage
tillages
tilled
tiller
tillered
tillers
tilling
tillite
tillites
tills
tils
tilt
tiltable
tilted
tilter
tilters
tilth
tilths
tilting
tilts
tiltyard
timarau
timaraus
timbal
timbale
timbales
timbals
timber
timbered
timbers
timbral
timbre
timbrel
timbrels
timbres
time
timecard
timed
timeless
timelier
timeline
timely
timeous
timeout
timeouts
timer
timers
times
timework
timeworn
timid
timider
timidest
timidity
timidly
timing
timings
timolol
timolols
timorous
timothy
timpana
timpani
timpano
timpanum
tin
tinamou
tinamous
tincal
tincals
tinct
tincted
tincting
tincts
tincture
tinder
tinders
tindery
tine
tinea
tineal
tineas
tined
tineid
tineids
tines
tinfoil
tinfoils
tinful
tinfuls
ting
tinge
tinged
tingeing
tinges
tinging
tingle
tingled
tingler
tinglers
tingles
tinglier
tingling
tingly
tings
tinhorn
tinhorns
tinier
tiniest
tinily
tininess
tining
tinker
tinkered
tinkerer
tinkers
tinkle
tinkled
tinkler
tinklers
tinkles
tinklier
tinkling
tinkly
tinlike
tinman
tinmen
tinned
tinner
tinners
tinnier
tinniest
tinnily
tinning
tinnitus
tinny
tinplate
tins
tinsel
tinseled
tinselly
tinsels
tinsmith
tinstone
tint
tinted
tinter
tinters
tinting
tintings
tintless
tints
tintype
tintypes
tinware
tinwares
tinwork
tinworks
tiny
tip
tipcart
tipcarts
tipcat
tipcats
tipi
tipis
tipless
tipoff
tipoffs
tippable
tipped
tipper
tippers
tippet
tippets
tippier
tippiest
tipping
tipple
tippled
tippler
tipplers
tipples
tippling
tippy
tippytoe
tips
tipsier
tipsiest
tipsily
tipstaff
tipster
tipsters
tipstock
tipsy
tiptoe
tiptoed
tiptoes
tiptop
tiptops
tirade
tirades
tiramisu
tire
tired
tireder
tiredest
tiredly
tireless
tires
tiresome
tiring
tirl
tirled
tirling
tirls
tiro
tiros
tirrivee
tis
tisane
tisanes
tissual
tissue
tissued
tissues
tissuey
tissuing
tissular
tit
titan
titanate
titaness
titania
titanias
titanic
titanism
titanite
titanium
titanous
titans
titbit
titbits
titer
titers
titfer
titfers
tithable
tithe
tithed
tither
tithers
tithes
tithing
tithings
tithonia
titi
titian
titians
titis
titivate
titlark
titlarks
title
titled
titles
titling
titlist
titlists
titman
titmen
titmice
titmouse
titrable
titrant
titrants
titrate
titrated
titrates
titrator
titre
titres
tits
titter
tittered
titterer
titters
tittie
titties
tittle
tittles
tittup
tittuped
tittuppy
tittups
titty
titular
titulars
titulary
tivy
tizzies
tizzy
tmeses
tmesis
to
toad
toadfish
toadflax
toadied
toadies
toadish
toadless
toadlike
toads
toady
toadying
toadyish
toadyism
toast
toasted
toaster
toasters
toastier
toasting
toasts
toasty
tobacco
tobaccos
tobies
toboggan
toby
toccata
toccatas
toccate
tocher
tochered
tochers
tocology
tocsin
tocsins
tod
today
todays
toddies
toddle
toddled
toddler
toddlers
toddles
toddling
toddy
todies
tods
tody
toe
toea
toecap
toecaps
toed
toehold
toeholds
toeing
toeless
toelike
toenail
toenails
toepiece
toeplate
toes
toeshoe
toeshoes
toff
toffee
toffees
toffies
toffs
toffy
toft
tofts
tofu
tofus
tog
toga
togae
togaed
togas
togate
togated
together
togged
toggery
togging
toggle
toggled
toggler
togglers
toggles
toggling
togs
togue
togues
toil
toile
toiled
toiler
toilers
toiles
toilet
toileted
toiletry
toilets
toilette
toilful
toiling
toils
toilsome
toilworn
toit
toited
toiting
toits
tokamak
tokamaks
tokay
tokays
toke
toked
token
tokened
tokening
tokenism
tokens
toker
tokers
tokes
toking
tokology
tokomak
tokomaks
tokonoma
tola
tolan
tolane
tolanes
tolans
tolas
tolbooth
told
tole
toled
toledo
toledos
tolerant
tolerate
toles
tolidin
tolidine
tolidins
toling
toll
tollage
tollages
tollbar
tollbars
tolled
toller
tollers
tollgate
tolling
tollman
tollmen
tolls
tollway
tollways
tolu
toluate
toluates
toluene
toluenes
toluic
toluid
toluide
toluides
toluidin
toluids
toluol
toluole
toluoles
toluols
tolus
toluyl
toluyls
tolyl
tolyls
tom
tomahawk
tomalley
toman
tomans
tomato
tomatoes
tomatoey
tomb
tombac
tomback
tombacks
tombacs
tombak
tombaks
tombal
tombed
tombing
tombless
tomblike
tombola
tombolas
tombolo
tombolos
tomboy
tomboys
tombs
tomcat
tomcats
tomcod
tomcods
tome
tomenta
tomentum
tomes
tomfool
tomfools
tommed
tommies
tomming
tommy
tommyrot
tomogram
tomorrow
tompion
tompions
toms
tomtit
tomtits
ton
tonal
tonality
tonally
tondi
tondo
tondos
tone
tonearm
tonearms
toned
toneless
toneme
tonemes
tonemic
toner
toners
tones
tonetic
tonetics
tonette
tonettes
toney
tong
tonga
tongas
tonged
tonger
tongers
tonging
tongman
tongmen
tongs
tongue
tongued
tongues
tonguing
tonic
tonicity
tonics
tonier
toniest
tonight
tonights
toning
tonish
tonishly
tonlet
tonlets
tonnage
tonnages
tonne
tonneau
tonneaus
tonneaux
tonner
tonners
tonnes
tonnish
tons
tonsil
tonsilar
tonsils
tonsure
tonsured
tonsures
tontine
tontines
tonus
tonuses
tony
too
took
tool
toolbox
tooled
tooler
toolers
toolhead
tooling
toolings
toolless
toolroom
tools
toolshed
toom
toon
toons
toot
tooted
tooter
tooters
tooth
toothed
toothier
toothily
toothing
tooths
toothy
tooting
tootle
tootled
tootler
tootlers
tootles
tootling
toots
tootses
tootsie
tootsies
tootsy
top
topaz
topazes
topazine
topcoat
topcoats
topcross
tope
toped
topee
topees
toper
topers
topes
topful
topfull
toph
tophe
tophes
tophi
tophs
tophus
topi
topiary
topic
topical
topics
toping
topis
topkick
topkicks
topknot
topknots
topless
topline
toplines
toplofty
topmast
topmasts
topmost
topnotch
topoi
topology
toponym
toponyms
toponymy
topos
topotype
topped
topper
toppers
topping
toppings
topple
toppled
topples
toppling
tops
topsail
topsails
topside
topsider
topsides
topsoil
topsoils
topspin
topspins
topstone
topwork
topworks
toque
toques
toquet
toquets
tor
tora
torah
torahs
toras
torc
torch
torched
torchere
torches
torchier
torching
torchon
torchons
torchy
torcs
tore
toreador
torero
toreros
tores
toreutic
tori
toric
tories
torii
torment
torments
torn
tornadic
tornado
tornados
tornillo
toro
toroid
toroidal
toroids
toros
torose
torosity
torot
toroth
torous
torpedo
torpedos
torpid
torpidly
torpids
torpor
torpors
torquate
torque
torqued
torquer
torquers
torques
torquing
torr
torrefy
torrent
torrents
torrid
torrider
torridly
torrify
tors
torsade
torsades
torse
torses
torsi
torsion
torsions
torsk
torsks
torso
torsos
tort
torte
torten
tortes
tortile
tortilla
tortious
tortoise
tortoni
tortonis
tortrix
torts
tortuous
torture
tortured
torturer
tortures
torula
torulae
torulas
torus
tory
tosh
toshes
toss
tossed
tosser
tossers
tosses
tossing
tosspot
tosspots
tossup
tossups
tost
tostada
tostadas
tostado
tostados
tot
totable
total
totaled
totaling
totalise
totalism
totalist
totality
totalize
totalled
totally
totals
tote
toted
totem
totemic
totemism
totemist
totemite
totems
toter
toters
totes
tother
toting
tots
totted
totter
tottered
totterer
totters
tottery
totting
toucan
toucans
touch
touche
touched
toucher
touchers
touches
touchier
touchily
touching
touchup
touchups
touchy
tough
toughed
toughen
toughens
tougher
toughest
toughie
toughies
toughing
toughish
toughly
toughs
toughy
toupee
toupees
tour
touraco
touracos
toured
tourer
tourers
touring
tourings
tourism
tourisms
tourist
tourists
touristy
tourney
tourneys
tours
touse
toused
touses
tousing
tousle
tousled
tousles
tousling
tout
touted
touter
touters
touting
touts
touzle
touzled
touzles
touzling
tovarich
tovarish
tow
towage
towages
toward
towardly
towards
towaway
towaways
towboat
towboats
towed
towel
toweled
toweling
towelled
towels
tower
towered
towerier
towering
towers
towery
towhead
towheads
towhee
towhees
towie
towies
towing
towline
towlines
towmond
towmonds
towmont
towmonts
town
townee
townees
townfolk
townhome
townie
townies
townish
townless
townlet
townlets
towns
township
townsman
townsmen
townwear
towny
towpath
towpaths
towrope
towropes
tows
towy
toxaemia
toxaemic
toxemia
toxemias
toxemic
toxic
toxical
toxicant
toxicity
toxics
toxin
toxine
toxines
toxins
toxoid
toxoids
toy
toyed
toyer
toyers
toying
toyish
toyless
toylike
toyo
toyon
toyons
toyos
toys
toyshop
toyshops
trabeate
trace
traced
tracer
tracers
tracery
traces
trachea
tracheae
tracheal
tracheas
tracheid
trachle
trachled
trachles
trachoma
trachyte
tracing
tracings
track
trackage
tracked
tracker
trackers
tracking
trackman
trackmen
tracks
trackway
tract
tractate
tractile
traction
tractive
tractor
tractors
tracts
trad
tradable
trade
traded
tradeoff
trader
traders
trades
trading
traditor
traduce
traduced
traducer
traduces
traffic
traffics
tragedy
tragi
tragic
tragical
tragics
tragopan
tragus
traik
traiked
traiking
traiks
trail
trailed
trailer
trailers
trailing
trails
train
trained
trainee
trainees
trainer
trainers
trainful
training
trainman
trainmen
trains
trainway
traipse
traipsed
traipses
trait
traitor
traitors
traits
traject
trajects
tram
tramcar
tramcars
tramel
trameled
tramell
tramells
tramels
tramless
tramline
trammed
trammel
trammels
tramming
tramp
tramped
tramper
trampers
tramping
trampish
trample
trampled
trampler
tramples
tramps
tramroad
trams
tramway
tramways
trance
tranced
trances
tranche
tranches
trancing
trangam
trangams
trank
tranks
tranq
tranqs
tranquil
trans
transact
transect
transept
transfer
transfix
tranship
transit
transits
transmit
transom
transoms
transude
trap
trapan
trapans
trapball
trapdoor
trapes
trapesed
trapeses
trapeze
trapezes
trapezia
trapezii
traplike
trapline
trapnest
trappean
trapped
trapper
trappers
trapping
trappose
trappous
traprock
traps
trapt
trapunto
trash
trashed
trashes
trashier
trashily
trashing
trashman
trashmen
trashy
trass
trasses
trauchle
trauma
traumas
traumata
travail
travails
trave
travel
traveled
traveler
travelog
travels
traverse
traves
travesty
travois
travoise
trawl
trawled
trawler
trawlers
trawley
trawleys
trawling
trawlnet
trawls
tray
trayful
trayfuls
trays
treacle
treacles
treacly
tread
treaded
treader
treaders
treading
treadle
treadled
treadler
treadles
treads
treason
treasons
treasure
treasury
treat
treated
treater
treaters
treaties
treating
treatise
treats
treaty
treble
trebled
trebles
trebling
trebly
trecento
treddle
treddled
treddles
tree
treed
treeing
treelawn
treeless
treelike
treen
treenail
treens
trees
treetop
treetops
tref
trefah
trefoil
trefoils
trehala
trehalas
trek
trekked
trekker
trekkers
trekking
treks
trellis
tremble
trembled
trembler
trembles
trembly
tremolo
tremolos
tremor
tremors
trenail
trenails
trench
trenched
trencher
trenches
trend
trended
trendier
trendies
trendily
trending
trends
trendy
trepan
trepang
trepangs
trepans
trephine
trepid
trespass
tress
tressed
tressel
tressels
tresses
tressier
tressour
tressure
tressy
trestle
trestles
tret
trets
trevet
trevets
trews
trey
treys
triable
triac
triacid
triacids
triacs
triad
triadic
triadics
triadism
triads
triage
triaged
triages
triaging
trial
trials
triangle
triarchy
triaxial
triazin
triazine
triazins
triazole
tribade
tribades
tribadic
tribal
tribally
tribasic
tribe
tribes
tribrach
tribunal
tribune
tribunes
tribute
tributes
trice
triced
triceps
trices
trichina
trichite
trichoid
trichome
tricing
trick
tricked
tricker
trickers
trickery
trickie
trickier
trickily
tricking
trickish
trickle
trickled
trickles
trickly
tricks
tricksy
tricky
triclad
triclads
tricolor
tricorn
tricorne
tricorns
tricot
tricots
trictrac
tricycle
trident
tridents
triduum
triduums
tried
triene
trienes
triennia
triens
trientes
trier
triers
tries
triethyl
trifecta
trifid
trifle
trifled
trifler
triflers
trifles
trifling
trifocal
trifold
triforia
triform
trig
trigged
trigger
triggers
triggest
trigging
trigly
triglyph
trigness
trigo
trigon
trigonal
trigons
trigos
trigram
trigrams
trigraph
trigs
trihedra
trijet
trijets
trike
trikes
trilbies
trilby
trill
trilled
triller
trillers
trilling
trillion
trillium
trills
trilobal
trilobed
trilogy
trim
trimaran
trimer
trimeric
trimers
trimeter
trimly
trimmed
trimmer
trimmers
trimmest
trimming
trimness
trimorph
trimotor
trims
trinal
trinary
trindle
trindled
trindles
trine
trined
trines
trining
trinity
trinket
trinkets
trinkums
trinodal
trio
triode
triodes
triol
triolet
triolets
triols
trios
triose
trioses
trioxid
trioxide
trioxids
trip
tripack
tripacks
tripart
tripe
tripedal
tripes
triphase
triplane
triple
tripled
triples
triplet
triplets
triplex
tripling
triplite
triploid
triply
tripod
tripodal
tripodic
tripods
tripody
tripoli
tripolis
tripos
triposes
tripped
tripper
trippers
trippet
trippets
trippier
tripping
trippy
trips
triptane
triptyca
triptych
tripwire
trireme
triremes
triscele
trisect
trisects
triseme
trisemes
trisemic
trishaw
trishaws
triskele
trismic
trismus
trisome
trisomes
trisomic
trisomy
tristate
triste
tristeza
tristful
tristich
trite
tritely
triter
tritest
trithing
triticum
tritium
tritiums
tritoma
tritomas
triton
tritone
tritones
tritons
triumph
triumphs
triumvir
triune
triunes
triunity
trivalve
trivet
trivets
trivia
trivial
trivium
troak
troaked
troaking
troaks
trocar
trocars
trochaic
trochal
trochar
trochars
troche
trochee
trochees
troches
trochil
trochili
trochils
trochlea
trochoid
trock
trocked
trocking
trocks
trod
trodden
trode
troffer
troffers
trogon
trogons
troika
troikas
troilism
troilite
troilus
trois
troke
troked
trokes
troking
troland
trolands
troll
trolled
troller
trollers
trolley
trolleys
trollied
trollies
trolling
trollop
trollops
trollopy
trolls
trolly
trombone
trommel
trommels
tromp
trompe
tromped
trompes
tromping
tromps
trona
tronas
trone
trones
troop
trooped
trooper
troopers
troopial
trooping
troops
trooz
trop
trope
tropes
trophic
trophied
trophies
trophy
tropic
tropical
tropics
tropin
tropine
tropines
tropins
tropism
tropisms
troponin
trot
troth
trothed
trothing
troths
trotline
trots
trotted
trotter
trotters
trotting
trotyl
trotyls
trouble
troubled
troubler
troubles
trough
troughs
trounce
trounced
trouncer
trounces
troupe
trouped
trouper
troupers
troupes
troupial
trouping
trouser
trousers
trout
troutier
trouts
trouty
trouvere
trouveur
trove
trover
trovers
troves
trow
trowed
trowel
troweled
troweler
trowels
trowing
trows
trowsers
trowth
trowths
troy
troys
truancy
truant
truanted
truantry
truants
truce
truced
truces
trucing
truck
truckage
trucked
trucker
truckers
truckful
trucking
truckle
truckled
truckler
truckles
truckman
truckmen
trucks
trudge
trudged
trudgen
trudgens
trudgeon
trudger
trudgers
trudges
trudging
true
trueblue
trueborn
truebred
trued
trueing
truelove
trueness
truer
trues
truest
truffe
truffes
truffle
truffled
truffles
trug
trugs
truing
truism
truisms
truistic
trull
trulls
truly
trumeau
trumeaux
trump
trumped
trumpery
trumpet
trumpets
trumping
trumps
truncate
trundle
trundled
trundler
trundles
trunk
trunked
trunkful
trunks
trunnel
trunnels
trunnion
truss
trussed
trusser
trussers
trusses
trussing
trust
trusted
trustee
trusteed
trustees
truster
trusters
trustful
trustier
trusties
trustily
trusting
trustor
trustors
trusts
trusty
truth
truthful
truths
try
trying
tryingly
tryma
trymata
tryout
tryouts
trypsin
trypsins
tryptic
trysail
trysails
tryst
tryste
trysted
tryster
trysters
trystes
trysting
trysts
tryworks
tsade
tsades
tsadi
tsadis
tsar
tsardom
tsardoms
tsarevna
tsarina
tsarinas
tsarism
tsarisms
tsarist
tsarists
tsaritza
tsars
tsetse
tsetses
tsimmes
tsk
tsked
tsking
tsks
tsktsk
tsktsked
tsktsks
tsooris
tsores
tsoris
tsorriss
tsuba
tsunami
tsunamic
tsunamis
tsuris
tuatara
tuataras
tuatera
tuateras
tub
tuba
tubae
tubaist
tubaists
tubal
tubas
tubate
tubbable
tubbed
tubber
tubbers
tubbier
tubbiest
tubbing
tubby
tube
tubed
tubeless
tubelike
tubenose
tuber
tubercle
tuberoid
tuberose
tuberous
tubers
tubes
tubework
tubful
tubfuls
tubifex
tubiform
tubing
tubings
tubist
tubists
tublike
tubs
tubular
tubulate
tubule
tubules
tubulin
tubulins
tubulose
tubulous
tubulure
tuchun
tuchuns
tuck
tuckahoe
tucked
tucker
tuckered
tuckers
tucket
tuckets
tucking
tucks
tuckshop
tufa
tufas
tuff
tuffet
tuffets
tuffs
tufoli
tuft
tufted
tufter
tufters
tuftier
tuftiest
tuftily
tufting
tufts
tufty
tug
tugboat
tugboats
tugged
tugger
tuggers
tugging
tughrik
tughriks
tugless
tugrik
tugriks
tugs
tui
tuille
tuilles
tuis
tuition
tuitions
tuladi
tuladis
tule
tules
tulip
tulips
tulle
tulles
tullibee
tumble
tumbled
tumbler
tumblers
tumbles
tumbling
tumbrel
tumbrels
tumbril
tumbrils
tumefied
tumefies
tumefy
tumid
tumidity
tumidly
tummies
tummler
tummlers
tummy
tumor
tumoral
tumorous
tumors
tumour
tumours
tump
tumped
tumping
tumpline
tumps
tumular
tumuli
tumulose
tumulous
tumult
tumults
tumulus
tun
tuna
tunable
tunably
tunas
tundish
tundra
tundras
tune
tuneable
tuneably
tuned
tuneful
tuneless
tuner
tuners
tunes
tuneup
tuneups
tung
tungs
tungsten
tungstic
tunic
tunica
tunicae
tunicate
tunicle
tunicles
tunics
tuning
tunnage
tunnages
tunned
tunnel
tunneled
tunneler
tunnels
tunnies
tunning
tunny
tuns
tup
tupelo
tupelos
tupik
tupiks
tupped
tuppence
tuppenny
tupping
tups
tuque
tuques
turaco
turacos
turacou
turacous
turban
turbaned
turbans
turbary
turbeth
turbeths
turbid
turbidly
turbinal
turbine
turbines
turbit
turbith
turbiths
turbits
turbo
turbocar
turbofan
turbojet
turbos
turbot
turbots
turd
turdine
turds
tureen
tureens
turf
turfed
turfier
turfiest
turfing
turfless
turflike
turfman
turfmen
turfs
turfski
turfskis
turfy
turgency
turgent
turgid
turgidly
turgite
turgites
turgor
turgors
turista
turistas
turk
turkey
turkeys
turkois
turks
turmeric
turmoil
turmoils
turn
turnable
turncoat
turndown
turned
turner
turners
turnery
turnhall
turning
turnings
turnip
turnips
turnkey
turnkeys
turnoff
turnoffs
turnout
turnouts
turnover
turnpike
turns
turnsole
turnspit
turnup
turnups
turpeth
turpeths
turps
turquois
turret
turreted
turrets
turrical
turtle
turtled
turtler
turtlers
turtles
turtling
turves
tusche
tusches
tush
tushed
tushes
tushie
tushies
tushing
tushy
tusk
tusked
tusker
tuskers
tusking
tuskless
tusklike
tusks
tussah
tussahs
tussal
tussar
tussars
tusseh
tussehs
tusser
tussers
tussis
tussises
tussive
tussle
tussled
tussles
tussling
tussock
tussocks
tussocky
tussor
tussore
tussores
tussors
tussuck
tussucks
tussur
tussurs
tut
tutee
tutees
tutelage
tutelar
tutelars
tutelary
tutor
tutorage
tutored
tutoress
tutorial
tutoring
tutors
tutoyed
tutoyer
tutoyers
tuts
tutted
tutti
tutties
tutting
tuttis
tutty
tutu
tutus
tux
tuxedo
tuxedoed
tuxedoes
tuxedos
tuxes
tuyer
tuyere
tuyeres
tuyers
twa
twaddle
twaddled
twaddler
twaddles
twae
twaes
twain
twains
twang
twanged
twanger
twangers
twangier
twanging
twangle
twangled
twangler
twangles
twangs
twangy
twankies
twanky
twas
twasome
twasomes
twat
twats
twattle
twattled
twattles
tweak
tweaked
tweakier
tweaking
tweaks
tweaky
twee
tweed
tweedier
tweedle
tweedled
tweedles
tweeds
tweedy
tween
tweenies
tweeny
tweet
tweeted
tweeter
tweeters
tweeting
tweets
tweeze
tweezed
tweezer
tweezers
tweezes
tweezing
twelfth
twelfths
twelve
twelvemo
twelves
twenties
twenty
twerp
twerps
twibil
twibill
twibills
twibils
twice
twiddle
twiddled
twiddler
twiddles
twiddly
twier
twiers
twig
twigged
twiggen
twiggier
twigging
twiggy
twigless
twiglike
twigs
twilight
twilit
twill
twilled
twilling
twills
twin
twinborn
twine
twined
twiner
twiners
twines
twinge
twinged
twinges
twinging
twinier
twiniest
twinight
twining
twinjet
twinjets
twinkle
twinkled
twinkler
twinkles
twinkly
twinned
twinning
twins
twinset
twinsets
twinship
twiny
twirl
twirled
twirler
twirlers
twirlier
twirling
twirls
twirly
twirp
twirps
twist
twisted
twister
twisters
twistier
twisting
twists
twisty
twit
twitch
twitched
twitcher
twitches
twitchy
twits
twitted
twitter
twitters
twittery
twitting
twixt
two
twofer
twofers
twofold
twofolds
twopence
twopenny
twos
twosome
twosomes
twyer
twyers
tycoon
tycoons
tye
tyee
tyees
tyer
tyers
tyes
tying
tyke
tykes
tylosin
tylosins
tymbal
tymbals
tympan
tympana
tympanal
tympani
tympanic
tympano
tympans
tympanum
tympany
tyne
tyned
tynes
tyning
typable
typal
type
typeable
typebar
typebars
typecase
typecast
typed
typeface
types
typeset
typesets
typey
typhoid
typhoids
typhon
typhonic
typhons
typhoon
typhoons
typhose
typhous
typhus
typhuses
typic
typical
typier
typiest
typified
typifier
typifies
typify
typing
typist
typists
typo
typology
typos
typp
typps
typy
tyramine
tyrannic
tyranny
tyrant
tyrants
tyre
tyred
tyres
tyring
tyro
tyronic
tyros
tyrosine
tythe
tythed
tythes
tything
tzaddik
tzar
tzardom
tzardoms
tzarevna
tzarina
tzarinas
tzarism
tzarisms
tzarist
tzarists
tzaritza
tzars
tzetze
tzetzes
tzigane
tziganes
tzimmes
tzitzis
tzitzit
tzitzith
tzuris
ubieties
ubiety
ubique
ubiquity
udder
udders
udo
udometer
udometry
udos
ufology
ugh
ughs
uglier
uglies
ugliest
uglified
uglifier
uglifies
uglify
uglily
ugliness
ugly
ugsome
uh
uhlan
uhlans
uintaite
ukase
ukases
uke
ukelele
ukeleles
ukes
ukulele
ukuleles
ulama
ulamas
ulan
ulans
ulcer
ulcerate
ulcered
ulcering
ulcerous
ulcers
ulema
ulemas
ulexite
ulexites
ullage
ullaged
ullages
ulna
ulnad
ulnae
ulnar
ulnas
ulpan
ulpanim
ulster
ulsters
ulterior
ultima
ultimacy
ultimas
ultimata
ultimate
ultimo
ultra
ultradry
ultrahip
ultrahot
ultraism
ultraist
ultralow
ultrared
ultras
ulu
ululant
ululate
ululated
ululates
ulus
ulva
ulvas
um
umangite
umbel
umbeled
umbellar
umbelled
umbellet
umbels
umber
umbered
umbering
umbers
umbilici
umbles
umbo
umbonal
umbonate
umbones
umbonic
umbos
umbra
umbrae
umbrage
umbrages
umbral
umbras
umbrella
umbrette
umiac
umiack
umiacks
umiacs
umiak
umiaks
umiaq
umiaqs
umlaut
umlauted
umlauts
umm
ump
umped
umping
umpirage
umpire
umpired
umpires
umpiring
umps
umpteen
umteenth
un
unabated
unable
unabused
unacted
unadult
unafraid
unaged
unageing
unagile
unaging
unai
unaided
unaimed
unaired
unais
unakin
unakite
unakites
unalike
unallied
unamused
unanchor
unaneled
unapt
unaptly
unargued
unarm
unarmed
unarming
unarms
unartful
unary
unasked
unatoned
unau
unaus
unavowed
unawaked
unaware
unawares
unawed
unbacked
unbaked
unban
unbanned
unbans
unbar
unbarbed
unbarred
unbars
unbased
unbated
unbathed
unbe
unbear
unbeared
unbears
unbeaten
unbelief
unbelt
unbelted
unbelts
unbend
unbended
unbends
unbenign
unbent
unbiased
unbid
unbidden
unbilled
unbind
unbinds
unbitted
unbitten
unbitter
unblamed
unblest
unblock
unblocks
unbloody
unbodied
unbolt
unbolted
unbolts
unboned
unbonnet
unborn
unbosom
unbosoms
unbought
unbouncy
unbound
unbowed
unbox
unboxed
unboxes
unboxing
unbrace
unbraced
unbraces
unbraid
unbraids
unbrake
unbraked
unbrakes
unbred
unbreech
unbridle
unbright
unbroke
unbroken
unbuckle
unbuild
unbuilds
unbuilt
unbulky
unbundle
unburden
unburied
unburned
unburnt
unbusted
unbusy
unbutton
uncage
uncaged
uncages
uncaging
uncake
uncaked
uncakes
uncaking
uncalled
uncandid
uncanny
uncap
uncapped
uncaps
uncaring
uncase
uncased
uncases
uncashed
uncasing
uncasked
uncatchy
uncaught
uncaused
unchain
unchains
unchancy
uncharge
unchary
unchaste
unchewed
unchic
unchicly
unchoke
unchoked
unchokes
unchosen
unchurch
unci
uncia
unciae
uncial
uncially
uncials
unciform
uncinal
uncinate
uncini
uncinus
uncivil
unclad
unclamp
unclamps
unclasp
unclasps
uncle
unclean
unclear
unclench
uncles
unclinch
unclip
unclips
uncloak
uncloaks
unclog
unclogs
unclose
unclosed
uncloses
unclothe
uncloud
unclouds
uncloyed
unco
uncoated
uncock
uncocked
uncocks
uncoded
uncoffin
uncoil
uncoiled
uncoils
uncoined
uncombed
uncomely
uncomic
uncommon
uncooked
uncool
uncooled
uncork
uncorked
uncorks
uncos
uncouple
uncouth
uncover
uncovers
uncoy
uncrate
uncrated
uncrates
uncrazy
uncreate
uncross
uncrown
uncrowns
unction
unctions
unctuous
uncuff
uncuffed
uncuffs
uncurb
uncurbed
uncurbs
uncured
uncurl
uncurled
uncurls
uncursed
uncus
uncut
uncute
undamped
undaring
undated
unde
undead
undecked
undee
undenied
under
underact
underage
underarm
underate
underbid
underbud
underbuy
undercut
underdid
underdo
underdog
undereat
underfed
underfur
undergo
undergod
underjaw
underlap
underlay
underlet
underlie
underlip
underlit
underpay
underpin
underran
underrun
undersea
underset
undertax
undertow
underway
undevout
undid
undies
undimmed
undine
undines
undo
undoable
undocile
undock
undocked
undocks
undoer
undoers
undoes
undoing
undoings
undone
undotted
undouble
undrape
undraped
undrapes
undraw
undrawn
undraws
undreamt
undress
undrest
undrew
undried
undrunk
undubbed
undue
undulant
undular
undulate
undulled
unduly
undy
undyed
undying
uneager
unearned
unearth
unearths
unease
uneases
uneasier
uneasily
uneasy
uneaten
unedible
unedited
unended
unending
unenvied
unequal
unequals
unerased
unerotic
unerring
unevaded
uneven
unevener
unevenly
unexotic
unexpert
unfaded
unfading
unfair
unfairer
unfairly
unfaith
unfaiths
unfaked
unfallen
unfamous
unfancy
unfasten
unfazed
unfeared
unfed
unfelt
unfence
unfenced
unfences
unfetter
unfilial
unfilled
unfilmed
unfired
unfished
unfit
unfitly
unfits
unfitted
unfix
unfixed
unfixes
unfixing
unfixt
unflashy
unflexed
unfoiled
unfold
unfolded
unfolder
unfolds
unfond
unforced
unforged
unforgot
unforked
unformed
unfought
unfound
unframed
unfree
unfreed
unfrees
unfreeze
unfrock
unfrocks
unfroze
unfrozen
unfunded
unfunny
unfurl
unfurled
unfurls
unfused
unfussy
ungainly
ungalled
ungenial
ungentle
ungently
ungifted
ungird
ungirded
ungirds
ungirt
unglazed
unglove
ungloved
ungloves
unglue
unglued
unglues
ungluing
ungodly
ungot
ungotten
ungowned
ungraced
ungraded
ungreedy
unground
ungual
unguard
unguards
unguent
unguenta
unguents
ungues
unguided
unguis
ungula
ungulae
ungular
ungulate
unhailed
unhair
unhaired
unhairs
unhallow
unhalved
unhand
unhanded
unhands
unhandy
unhang
unhanged
unhangs
unhappy
unharmed
unhasty
unhat
unhats
unhatted
unhealed
unheard
unheated
unhedged
unheeded
unhelm
unhelmed
unhelms
unhelped
unheroic
unhewn
unhinge
unhinged
unhinges
unhip
unhired
unhitch
unholier
unholily
unholy
unhood
unhooded
unhoods
unhook
unhooked
unhooks
unhoped
unhorse
unhorsed
unhorses
unhouse
unhoused
unhouses
unhuman
unhung
unhurt
unhusk
unhusked
unhusks
unialgal
uniaxial
unicolor
unicorn
unicorns
unicycle
unideaed
unideal
uniface
unifaces
unific
unified
unifier
unifiers
unifies
unifilar
uniform
uniforms
unify
unifying
unilobed
unimbued
union
unionise
unionism
unionist
unionize
unions
unipod
unipods
unipolar
unique
uniquely
uniquer
uniques
uniquest
unironed
unisex
unisexes
unison
unisonal
unisons
unissued
unit
unitage
unitages
unitard
unitards
unitary
unite
united
unitedly
uniter
uniters
unites
unities
uniting
unitive
unitize
unitized
unitizer
unitizes
unitrust
units
unity
univalve
universe
univocal
unjaded
unjoined
unjoint
unjoints
unjoyful
unjudged
unjust
unjustly
unkempt
unkend
unkenned
unkennel
unkent
unkept
unkind
unkinder
unkindly
unkingly
unkink
unkinked
unkinks
unkissed
unknit
unknits
unknot
unknots
unknown
unknowns
unkosher
unlace
unlaced
unlaces
unlacing
unlade
unladed
unladen
unlades
unlading
unlaid
unlash
unlashed
unlashes
unlatch
unlawful
unlay
unlaying
unlays
unlead
unleaded
unleads
unlearn
unlearns
unlearnt
unleased
unleash
unled
unless
unlet
unlethal
unletted
unlevel
unlevels
unlevied
unlicked
unlike
unlikely
unlimber
unlined
unlink
unlinked
unlinks
unlisted
unlit
unlive
unlived
unlively
unlives
unliving
unload
unloaded
unloader
unloads
unlobed
unlock
unlocked
unlocks
unloose
unloosed
unloosen
unlooses
unloved
unlovely
unloving
unlucky
unmacho
unmade
unmake
unmaker
unmakers
unmakes
unmaking
unman
unmanful
unmanly
unmanned
unmans
unmapped
unmarked
unmarred
unmask
unmasked
unmasker
unmasks
unmated
unmatted
unmeant
unmeet
unmeetly
unmellow
unmelted
unmended
unmerry
unmesh
unmeshed
unmeshes
unmet
unmew
unmewed
unmewing
unmews
unmilled
unmined
unmingle
unmiter
unmiters
unmitre
unmitred
unmitres
unmix
unmixed
unmixes
unmixing
unmixt
unmodish
unmold
unmolded
unmolds
unmolten
unmoor
unmoored
unmoors
unmoral
unmoved
unmoving
unmown
unmuffle
unmuzzle
unnail
unnailed
unnails
unnamed
unneeded
unnerve
unnerved
unnerves
unnoisy
unnoted
unoiled
unopen
unopened
unornate
unowned
unpack
unpacked
unpacker
unpacks
unpaged
unpaid
unpaired
unparted
unpaved
unpaying
unpeeled
unpeg
unpegged
unpegs
unpen
unpenned
unpens
unpent
unpeople
unperson
unpick
unpicked
unpicks
unpile
unpiled
unpiles
unpiling
unpin
unpinned
unpins
unpitied
unplaced
unplait
unplaits
unplayed
unpliant
unplowed
unplug
unplugs
unpoetic
unpoised
unpolite
unpolled
unposed
unposted
unpotted
unpretty
unpriced
unprimed
unprized
unprobed
unproved
unproven
unpruned
unpucker
unpure
unpurged
unpuzzle
unquiet
unquiets
unquote
unquoted
unquotes
unraised
unraked
unranked
unrated
unravel
unravels
unrazed
unread
unready
unreal
unreally
unreason
unreel
unreeled
unreeler
unreels
unreeve
unreeved
unreeves
unrent
unrented
unrepaid
unrepair
unrest
unrested
unrests
unrhymed
unriddle
unrifled
unrig
unrigged
unrigs
unrimed
unrinsed
unrip
unripe
unripely
unriper
unripest
unripped
unrips
unrisen
unrobe
unrobed
unrobes
unrobing
unroll
unrolled
unrolls
unroof
unroofed
unroofs
unroot
unrooted
unroots
unroped
unrough
unround
unrounds
unrove
unroven
unruled
unrulier
unruly
unrushed
unrusted
uns
unsaddle
unsafe
unsafely
unsafety
unsaid
unsalted
unsated
unsaved
unsavory
unsawed
unsawn
unsay
unsaying
unsays
unscaled
unscrew
unscrews
unseal
unsealed
unseals
unseam
unseamed
unseams
unseared
unseat
unseated
unseats
unseeded
unseeing
unseemly
unseen
unseized
unsell
unsells
unsent
unserved
unset
unsets
unsettle
unsew
unsewed
unsewing
unsewn
unsews
unsex
unsexed
unsexes
unsexing
unsexual
unsexy
unshaded
unshaken
unshamed
unshaped
unshapen
unshared
unsharp
unshaved
unshaven
unshed
unshell
unshells
unshift
unshifts
unship
unships
unshod
unshorn
unshowy
unshrunk
unshut
unsicker
unsifted
unsight
unsights
unsigned
unsilent
unsinful
unsized
unslaked
unsliced
unsling
unslings
unslung
unsmart
unsmoked
unsnap
unsnaps
unsnarl
unsnarls
unsoaked
unsober
unsocial
unsoiled
unsold
unsolder
unsolid
unsolved
unsoncy
unsonsie
unsonsy
unsorted
unsought
unsound
unsoured
unsowed
unsown
unspeak
unspeaks
unspent
unsphere
unspilt
unsplit
unspoilt
unspoke
unspoken
unsprung
unspun
unstable
unstably
unstack
unstacks
unstate
unstated
unstates
unstayed
unsteady
unsteel
unsteels
unstep
unsteps
unstick
unsticks
unstitch
unstoned
unstop
unstops
unstrap
unstraps
unstress
unstring
unstrung
unstuck
unstuffy
unstung
unsubtle
unsubtly
unsuited
unsung
unsunk
unsure
unsurely
unswathe
unswayed
unswear
unswears
unswept
unswore
unsworn
untack
untacked
untacks
untagged
untaken
untame
untamed
untangle
untanned
untapped
untasted
untaught
untaxed
unteach
untended
untented
untested
untether
unthawed
unthink
unthinks
unthread
unthrone
untidied
untidier
untidies
untidily
untidy
untie
untied
unties
until
untilled
untilted
untimely
untinged
untipped
untired
untiring
untitled
unto
untold
untorn
untoward
untraced
untread
untreads
untrendy
untried
untrim
untrims
untrod
untrue
untruer
untruest
untruly
untruss
untrusty
untruth
untruths
untuck
untucked
untucks
untufted
untune
untuned
untunes
untuning
unturned
untwine
untwined
untwines
untwist
untwists
untying
ununited
unurged
unusable
unused
unusual
unvalued
unvaried
unveil
unveiled
unveils
unveined
unversed
unvexed
unvext
unviable
unvocal
unvoice
unvoiced
unvoices
unwalled
unwaning
unwanted
unwarier
unwarily
unwarmed
unwarned
unwarped
unwary
unwashed
unwasted
unwaxed
unweaned
unweary
unweave
unweaves
unwed
unwedded
unweeded
unweight
unwelded
unwell
unwept
unwetted
unwhite
unwieldy
unwifely
unwilled
unwind
unwinder
unwinds
unwisdom
unwise
unwisely
unwiser
unwisest
unwish
unwished
unwishes
unwit
unwits
unwitted
unwon
unwonted
unwooded
unwooed
unworked
unworn
unworthy
unwound
unwove
unwoven
unwrap
unwraps
unwrung
unyeaned
unyoke
unyoked
unyokes
unyoking
unyoung
unzip
unzipped
unzips
unzoned
up
upas
upases
upbear
upbearer
upbears
upbeat
upbeats
upbind
upbinds
upboil
upboiled
upboils
upbore
upborne
upbound
upbow
upbows
upbraid
upbraids
upbuild
upbuilds
upbuilt
upby
upbye
upcast
upcasts
upchuck
upchucks
upclimb
upclimbs
upcoast
upcoil
upcoiled
upcoils
upcoming
upcurl
upcurled
upcurls
upcurve
upcurved
upcurves
updart
updarted
updarts
update
updated
updater
updaters
updates
updating
updive
updived
updives
updiving
updo
updos
updove
updraft
updrafts
updried
updries
updry
updrying
upend
upended
upending
upends
upfield
upfling
upflings
upflow
upflowed
upflows
upflung
upfold
upfolded
upfolds
upfront
upgather
upgaze
upgazed
upgazes
upgazing
upgird
upgirded
upgirds
upgirt
upgoing
upgrade
upgraded
upgrades
upgrew
upgrow
upgrown
upgrows
upgrowth
upheap
upheaped
upheaps
upheaval
upheave
upheaved
upheaver
upheaves
upheld
uphill
uphills
uphoard
uphoards
uphold
upholder
upholds
uphove
uphroe
uphroes
upkeep
upkeeps
upland
uplander
uplands
upleap
upleaped
upleaps
upleapt
uplift
uplifted
uplifter
uplifts
uplight
uplights
uplink
uplinks
uplit
upload
uploaded
uploads
upmarket
upmost
upo
upon
upped
upper
uppercut
uppers
uppile
uppiled
uppiles
uppiling
upping
uppings
uppish
uppishly
uppity
upprop
upprops
upraise
upraised
upraiser
upraises
uprate
uprated
uprates
uprating
upreach
uprear
upreared
uprears
upright
uprights
uprise
uprisen
upriser
uprisers
uprises
uprising
upriver
uprivers
uproar
uproars
uproot
uprootal
uprooted
uprooter
uproots
uprose
uprouse
uproused
uprouses
uprush
uprushed
uprushes
ups
upscale
upscaled
upscales
upsend
upsends
upsent
upset
upsets
upsetter
upshift
upshifts
upshoot
upshoots
upshot
upshots
upside
upsides
upsilon
upsilons
upsoar
upsoared
upsoars
upsprang
upspring
upsprung
upstage
upstaged
upstages
upstair
upstairs
upstand
upstands
upstare
upstared
upstares
upstart
upstarts
upstate
upstater
upstates
upstep
upsteps
upstir
upstirs
upstood
upstream
upstroke
upsurge
upsurged
upsurges
upsweep
upsweeps
upswell
upswells
upswept
upswing
upswings
upswung
uptake
uptakes
uptear
uptears
upthrew
upthrow
upthrown
upthrows
upthrust
uptick
upticks
uptight
uptilt
uptilted
uptilts
uptime
uptimes
uptore
uptorn
uptoss
uptossed
uptosses
uptown
uptowner
uptowns
uptrend
uptrends
upturn
upturned
upturns
upwaft
upwafted
upwafts
upward
upwardly
upwards
upwell
upwelled
upwells
upwind
upwinds
uracil
uracils
uraei
uraemia
uraemias
uraemic
uraeus
uraeuses
uralite
uralites
uralitic
urania
uranias
uranic
uranide
uranides
uranism
uranisms
uranite
uranites
uranitic
uranium
uraniums
uranous
uranyl
uranylic
uranyls
urare
urares
urari
uraris
urase
urases
urate
urates
uratic
urb
urban
urbane
urbanely
urbaner
urbanest
urbanise
urbanism
urbanist
urbanite
urbanity
urbanize
urbia
urbias
urbs
urchin
urchins
urd
urds
urea
ureal
ureas
urease
ureases
uredia
uredial
uredinia
uredium
uredo
uredos
ureic
ureide
ureides
uremia
uremias
uremic
ureter
ureteral
ureteric
ureters
urethan
urethane
urethans
urethra
urethrae
urethral
urethras
uretic
urge
urged
urgency
urgent
urgently
urger
urgers
urges
urging
urgingly
urial
urials
uric
uridine
uridines
urinal
urinals
urinary
urinate
urinated
urinates
urine
urinemia
urinemic
urines
urinose
urinous
urn
urnlike
urns
urochord
urodele
urodeles
urolith
uroliths
urologic
urology
uropod
uropodal
uropods
uropygia
uroscopy
urostyle
ursa
ursae
ursiform
ursine
urtext
urtexts
urticant
urticate
urus
uruses
urushiol
us
usable
usably
usage
usages
usance
usances
usaunce
usaunces
use
useable
useably
used
useful
usefully
useless
user
users
uses
usher
ushered
ushering
ushers
using
usnea
usneas
usquabae
usque
usquebae
usques
ustulate
usual
usually
usuals
usufruct
usurer
usurers
usuries
usurious
usurp
usurped
usurper
usurpers
usurping
usurps
usury
ut
uta
utas
utensil
utensils
uteri
uterine
uterus
uteruses
utile
utilidor
utilise
utilised
utiliser
utilises
utility
utilize
utilized
utilizer
utilizes
utmost
utmosts
utopia
utopian
utopians
utopias
utopism
utopisms
utopist
utopists
utricle
utricles
utriculi
uts
utter
uttered
utterer
utterers
uttering
utterly
utters
uvea
uveal
uveas
uveitic
uveitis
uveous
uvula
uvulae
uvular
uvularly
uvulars
uvulas
uvulitis
uxorial
uxorious
vac
vacancy
vacant
vacantly
vacate
vacated
vacates
vacating
vacation
vaccina
vaccinal
vaccinas
vaccine
vaccinee
vaccines
vaccinia
vacs
vacua
vacuity
vacuolar
vacuole
vacuoles
vacuous
vacuum
vacuumed
vacuums
vadose
vagabond
vagal
vagally
vagaries
vagary
vagi
vagile
vagility
vagina
vaginae
vaginal
vaginas
vaginate
vagotomy
vagrancy
vagrant
vagrants
vagrom
vague
vaguely
vaguer
vaguest
vagus
vahine
vahines
vail
vailed
vailing
vails
vain
vainer
vainest
vainly
vainness
vair
vairs
vakeel
vakeels
vakil
vakils
valance
valanced
valances
vale
valence
valences
valencia
valency
valerate
valerian
valeric
vales
valet
valeted
valeting
valets
valgoid
valgus
valguses
valiance
valiancy
valiant
valiants
valid
validate
validity
validly
valine
valines
valise
valises
valkyr
valkyrie
valkyrs
vallate
valley
valleys
valonia
valonias
valor
valorise
valorize
valorous
valors
valour
valours
valse
valses
valuable
valuably
valuate
valuated
valuates
valuator
value
valued
valuer
valuers
values
valuing
valuta
valutas
valval
valvar
valvate
valve
valved
valvelet
valves
valving
valvula
valvulae
valvular
valvule
valvules
vambrace
vamoose
vamoosed
vamooses
vamose
vamosed
vamoses
vamosing
vamp
vamped
vamper
vampers
vamping
vampire
vampires
vampiric
vampish
vamps
van
vanadate
vanadic
vanadium
vanadous
vanda
vandal
vandalic
vandals
vandas
vandyke
vandyked
vandykes
vane
vaned
vanes
vang
vangs
vanguard
vanilla
vanillas
vanillic
vanillin
vanish
vanished
vanisher
vanishes
vanitied
vanities
vanitory
vanity
vanman
vanmen
vanned
vanner
vanners
vanning
vanpool
vanpools
vanquish
vans
vantage
vantages
vanward
vapid
vapidity
vapidly
vapor
vapored
vaporer
vaporers
vaporing
vaporise
vaporish
vaporize
vaporous
vapors
vapory
vapour
vapoured
vapourer
vapours
vapoury
vaquero
vaqueros
var
vara
varactor
varas
varia
variable
variably
variance
variant
variants
variate
variated
variates
varices
varicose
varied
variedly
varier
variers
varies
varietal
variety
variform
variola
variolar
variolas
variole
varioles
variorum
various
varistor
varix
varlet
varletry
varlets
varment
varments
varmint
varmints
varna
varnas
varnish
varnishy
varoom
varoomed
varooms
vars
varsity
varus
varuses
varve
varved
varves
vary
varying
vas
vasa
vasal
vascula
vascular
vasculum
vase
vaselike
vases
vasiform
vasotomy
vassal
vassals
vast
vaster
vastest
vastier
vastiest
vastity
vastly
vastness
vasts
vasty
vat
vatful
vatfuls
vatic
vatical
vaticide
vats
vatted
vatting
vatu
vatus
vau
vault
vaulted
vaulter
vaulters
vaultier
vaulting
vaults
vaulty
vaunt
vaunted
vaunter
vaunters
vauntful
vauntie
vaunting
vaunts
vaunty
vaus
vav
vavasor
vavasors
vavasour
vavassor
vavs
vaw
vaward
vawards
vawntie
vaws
veal
vealed
vealer
vealers
vealier
vealiest
vealing
veals
vealy
vector
vectored
vectors
vedalia
vedalias
vedette
vedettes
vee
veejay
veejays
veena
veenas
veep
veepee
veepees
veeps
veer
veered
veeries
veering
veers
veery
vees
veg
vegan
veganism
vegans
vegetal
vegetant
vegetate
vegete
vegetist
vegetive
veggie
veggies
vegie
vegies
vehement
vehicle
vehicles
veil
veiled
veiledly
veiler
veilers
veiling
veilings
veillike
veils
vein
veinal
veined
veiner
veiners
veinier
veiniest
veining
veinings
veinless
veinlet
veinlets
veinlike
veins
veinule
veinules
veinulet
veiny
vela
velamen
velamina
velar
velaria
velarium
velarize
velars
velate
veld
velds
veldt
veldts
veliger
veligers
velites
velleity
vellum
vellums
veloce
velocity
velour
velours
veloute
veloutes
velum
velure
velured
velures
veluring
velveret
velvet
velveted
velvets
velvety
vena
venae
venal
venality
venally
venatic
venation
vend
vendable
vendace
vendaces
vended
vendee
vendees
vender
venders
vendetta
vendeuse
vendible
vendibly
vending
vendor
vendors
vends
vendue
vendues
veneer
veneered
veneerer
veneers
venenate
venenose
venerate
venereal
veneries
venery
venetian
venge
venged
vengeful
venges
venging
venial
venially
venin
venine
venines
venins
venire
venires
venison
venisons
venogram
venom
venomed
venomer
venomers
venoming
venomous
venoms
venose
venosity
venous
venously
vent
ventage
ventages
ventail
ventails
vented
venter
venters
venting
ventless
ventral
ventrals
vents
venture
ventured
venturer
ventures
venturi
venturis
venue
venues
venular
venule
venules
venulose
venulous
vera
veracity
veranda
verandah
verandas
veratria
veratrin
veratrum
verb
verbal
verbally
verbals
verbatim
verbena
verbenas
verbiage
verbid
verbids
verbify
verbile
verbiles
verbless
verbose
verboten
verbs
verdancy
verdant
verderer
verderor
verdict
verdicts
verdin
verdins
verditer
verdure
verdured
verdures
verecund
verge
verged
vergence
verger
vergers
verges
verging
verglas
veridic
verier
veriest
verified
verifier
verifies
verify
verily
verism
verismo
verismos
verisms
verist
veristic
verists
veritas
verite
verites
verities
verity
verjuice
vermeil
vermeils
vermes
vermian
vermin
vermis
vermoulu
vermouth
vermuth
vermuths
vernacle
vernal
vernally
vernicle
vernier
verniers
vernix
vernixes
veronica
verruca
verrucae
versal
versant
versants
verse
versed
verseman
versemen
verser
versers
verses
verset
versets
versicle
versify
versine
versines
versing
version
versions
verso
versos
verst
verste
verstes
versts
versus
vert
vertebra
vertex
vertexes
vertical
vertices
verticil
vertigo
vertigos
verts
vertu
vertus
vervain
vervains
verve
verves
vervet
vervets
very
vesica
vesicae
vesical
vesicant
vesicate
vesicle
vesicles
vesicula
vesper
vesperal
vespers
vespiary
vespid
vespids
vespine
vessel
vesseled
vessels
vest
vesta
vestal
vestally
vestals
vestas
vested
vestee
vestees
vestiary
vestige
vestiges
vestigia
vesting
vestings
vestless
vestlike
vestment
vestral
vestries
vestry
vests
vestural
vesture
vestured
vestures
vesuvian
vet
vetch
vetches
veteran
veterans
vetiver
vetivers
vetivert
veto
vetoed
vetoer
vetoers
vetoes
vetoing
vets
vetted
vetting
vex
vexation
vexed
vexedly
vexer
vexers
vexes
vexil
vexilla
vexillar
vexillum
vexils
vexing
vexingly
vext
via
viable
viably
viaduct
viaducts
vial
vialed
vialing
vialled
vialling
vials
viand
viands
viatic
viatica
viatical
viaticum
viator
viatores
viators
vibe
vibes
vibist
vibists
vibrance
vibrancy
vibrant
vibrants
vibrate
vibrated
vibrates
vibrato
vibrator
vibratos
vibrio
vibrioid
vibrion
vibrions
vibrios
vibrissa
vibronic
viburnum
vicar
vicarage
vicarate
vicarial
vicarly
vicars
vice
viced
viceless
vicenary
viceroy
viceroys
vices
vichies
vichy
vicinage
vicinal
vicing
vicinity
vicious
vicomte
vicomtes
victim
victims
victor
victoria
victors
victory
victress
victual
victuals
vicugna
vicugnas
vicuna
vicunas
vide
video
videos
videotex
vidette
videttes
vidicon
vidicons
viduity
vie
vied
vier
viers
vies
view
viewable
viewdata
viewed
viewer
viewers
viewier
viewiest
viewing
viewings
viewless
views
viewy
vig
viga
vigas
vigil
vigilant
vigils
vigneron
vignette
vigor
vigorish
vigoroso
vigorous
vigors
vigour
vigours
vigs
viking
vikings
vilayet
vilayets
vile
vilely
vileness
viler
vilest
vilified
vilifier
vilifies
vilify
vilipend
vill
villa
villadom
villae
village
villager
villages
villain
villains
villainy
villas
villatic
villein
villeins
villi
villose
villous
vills
villus
vim
vimen
vimina
viminal
vims
vina
vinal
vinals
vinas
vinasse
vinasses
vinca
vincas
vincible
vincibly
vincula
vinculum
vindaloo
vine
vineal
vined
vinegar
vinegars
vinegary
vineries
vinery
vines
vineyard
vinic
vinier
viniest
vinifera
vinified
vinifies
vinify
vining
vino
vinos
vinosity
vinous
vinously
vintage
vintager
vintages
vintner
vintners
viny
vinyl
vinylic
vinyls
viol
viola
violable
violably
violas
violate
violated
violater
violates
violator
violence
violent
violet
violets
violin
violins
violist
violists
violone
violones
viols
viomycin
viper
viperine
viperish
viperous
vipers
virago
viragoes
viragos
viral
virally
virelai
virelais
virelay
virelays
viremia
viremias
viremic
vireo
vireos
vires
virga
virgas
virgate
virgates
virgin
virginal
virgins
virgule
virgules
viricide
virid
viridian
viridity
virile
virilely
virilism
virility
virion
virions
virl
virls
viroid
viroids
virology
viroses
virosis
virtu
virtual
virtue
virtues
virtuosa
virtuose
virtuosi
virtuoso
virtuous
virtus
virucide
virulent
virus
viruses
vis
visa
visaed
visage
visaged
visages
visaing
visard
visards
visas
viscacha
viscera
visceral
viscid
viscidly
viscoid
viscose
viscoses
viscount
viscous
viscus
vise
vised
viseed
viseing
viselike
vises
visible
visibly
vising
vision
visional
visioned
visions
visit
visitant
visited
visiter
visiters
visiting
visitor
visitors
visits
visive
visor
visored
visoring
visors
vista
vistaed
vistas
visual
visually
visuals
vita
vitae
vital
vitalise
vitalism
vitalist
vitality
vitalize
vitally
vitals
vitamer
vitamers
vitamin
vitamine
vitamins
vitellin
vitellus
vitesse
vitesses
vitiable
vitiate
vitiated
vitiates
vitiator
vitiligo
vitrain
vitrains
vitreous
vitric
vitrics
vitrify
vitrine
vitrines
vitriol
vitriols
vitta
vittae
vittate
vittle
vittled
vittles
vittling
vituline
viva
vivace
vivaces
vivacity
vivaria
vivaries
vivarium
vivary
vivas
vive
viverrid
vivers
vivid
vivider
vividest
vividly
vivific
vivified
vivifier
vivifies
vivify
vivipara
vivisect
vixen
vixenish
vixenly
vixens
vizard
vizarded
vizards
vizcacha
vizier
viziers
vizir
vizirate
vizirial
vizirs
vizor
vizored
vizoring
vizors
vizsla
vizslas
vocable
vocables
vocably
vocal
vocalic
vocalics
vocalise
vocalism
vocalist
vocality
vocalize
vocally
vocals
vocation
vocative
voces
vocoder
vocoders
vodka
vodkas
vodoun
vodouns
vodun
voduns
voe
voes
vogie
vogue
vogued
vogueing
voguer
voguers
vogues
voguing
voguish
voice
voiced
voiceful
voicer
voicers
voices
voicing
void
voidable
voidance
voided
voider
voiders
voiding
voidness
voids
voila
voile
voiles
volant
volante
volar
volatile
volcanic
volcano
volcanos
vole
voled
voleries
volery
voles
voling
volitant
volition
volitive
volley
volleyed
volleyer
volleys
volost
volosts
volplane
volt
volta
voltage
voltages
voltaic
voltaism
volte
voltes
volti
volts
voluble
volubly
volume
volumed
volumes
voluming
volute
voluted
volutes
volutin
volutins
volution
volva
volvas
volvate
volvox
volvoxes
volvuli
volvulus
vomer
vomerine
vomers
vomica
vomicae
vomit
vomited
vomiter
vomiters
vomiting
vomitive
vomito
vomitory
vomitos
vomitous
vomits
vomitus
voodoo
voodooed
voodoos
voracity
vorlage
vorlages
vortex
vortexes
vortical
vortices
votable
votaress
votaries
votarist
votary
vote
voteable
voted
voteless
voter
voters
votes
voting
votive
votively
votress
vouch
vouched
vouchee
vouchees
voucher
vouchers
vouches
vouching
voussoir
vouvray
vouvrays
vow
vowed
vowel
vowelize
vowels
vower
vowers
vowing
vowless
vows
vox
voyage
voyaged
voyager
voyagers
voyages
voyageur
voyaging
voyeur
voyeurs
vroom
vroomed
vrooming
vrooms
vrouw
vrouws
vrow
vrows
vug
vugg
vuggier
vuggiest
vuggs
vuggy
vugh
vughs
vugs
vulcanic
vulgar
vulgarer
vulgarly
vulgars
vulgate
vulgates
vulgo
vulgus
vulguses
vulpine
vulture
vultures
vulva
vulvae
vulval
vulvar
vulvas
vulvate
vulvitis
vying
vyingly
wab
wabble
wabbled
wabbler
wabblers
wabbles
wabblier
wabbling
wabbly
wabs
wack
wacke
wackes
wackier
wackiest
wackily
wacko
wackos
wacks
wacky
wad
wadable
wadded
wadder
wadders
waddie
waddied
waddies
wadding
waddings
waddle
waddled
waddler
waddlers
waddles
waddling
waddly
waddy
waddying
wade
wadeable
waded
wader
waders
wades
wadi
wadies
wading
wadis
wadmaal
wadmaals
wadmal
wadmals
wadmel
wadmels
wadmol
wadmoll
wadmolls
wadmols
wads
wadset
wadsets
wady
wae
waeful
waeness
waes
waesuck
waesucks
wafer
wafered
wafering
wafers
wafery
waff
waffed
waffie
waffies
waffing
waffle
waffled
waffler
wafflers
waffles
waffling
waffs
waft
waftage
waftages
wafted
wafter
wafters
wafting
wafts
wafture
waftures
wag
wage
waged
wageless
wager
wagered
wagerer
wagerers
wagering
wagers
wages
wagged
wagger
waggers
waggery
wagging
waggish
waggle
waggled
waggles
waggling
waggly
waggon
waggoned
waggoner
waggons
waging
wagon
wagonage
wagoned
wagoner
wagoners
wagoning
wagons
wags
wagsome
wagtail
wagtails
wahconda
wahine
wahines
wahoo
wahoos
waif
waifed
waifing
waiflike
waifs
wail
wailed
wailer
wailers
wailful
wailing
wails
wailsome
wain
wains
wainscot
wair
waired
wairing
wairs
waist
waisted
waister
waisters
waisting
waists
wait
waited
waiter
waiters
waiting
waitings
waitress
waits
waive
waived
waiver
waivers
waives
waiving
wakanda
wakandas
wake
waked
wakeful
wakeless
waken
wakened
wakener
wakeners
wakening
wakens
waker
wakerife
wakers
wakes
wakiki
wakikis
waking
wale
waled
waler
walers
wales
walies
waling
walk
walkable
walkaway
walked
walker
walkers
walking
walkings
walkout
walkouts
walkover
walks
walkup
walkups
walkway
walkways
walkyrie
wall
walla
wallaby
wallah
wallahs
wallaroo
wallas
walled
wallet
wallets
walleye
walleyed
walleyes
wallie
wallies
walling
wallop
walloped
walloper
wallops
wallow
wallowed
wallower
wallows
walls
wally
walnut
walnuts
walrus
walruses
waltz
waltzed
waltzer
waltzers
waltzes
waltzing
waly
wamble
wambled
wambles
wamblier
wambling
wambly
wame
wamefou
wamefous
wameful
wamefuls
wames
wammus
wammuses
wampish
wampum
wampums
wampus
wampuses
wamus
wamuses
wan
wand
wander
wandered
wanderer
wanderoo
wanders
wandle
wands
wane
waned
wanes
waney
wangan
wangans
wangle
wangled
wangler
wanglers
wangles
wangling
wangun
wanguns
wanier
waniest
wanigan
wanigans
waning
wanion
wanions
wanly
wanned
wanner
wanness
wannest
wannigan
wanning
wans
want
wantage
wantages
wanted
wanter
wanters
wanting
wanton
wantoned
wantoner
wantonly
wantons
wants
wany
wap
wapiti
wapitis
wapped
wapping
waps
war
warble
warbled
warbler
warblers
warbles
warbling
warcraft
ward
warded
warden
wardenry
wardens
warder
warders
warding
wardress
wardrobe
wardroom
wards
wardship
ware
wared
wareroom
wares
warfare
warfares
warfarin
warhead
warheads
warhorse
warier
wariest
warily
wariness
waring
warison
warisons
wark
warked
warking
warks
warless
warlike
warlock
warlocks
warlord
warlords
warm
warmaker
warmed
warmer
warmers
warmest
warming
warmish
warmly
warmness
warmouth
warms
warmth
warmths
warmup
warmups
warn
warned
warner
warners
warning
warnings
warns
warp
warpage
warpages
warpath
warpaths
warped
warper
warpers
warping
warplane
warpower
warps
warpwise
warragal
warrant
warrants
warranty
warred
warren
warrener
warrens
warrigal
warring
warrior
warriors
wars
warsaw
warsaws
warship
warships
warsle
warsled
warsler
warslers
warsles
warsling
warstle
warstled
warstler
warstles
wart
warted
warthog
warthogs
wartier
wartiest
wartime
wartimes
wartless
wartlike
warts
warty
warwork
warworks
warworn
wary
was
wasabi
wasabis
wash
washable
washbowl
washday
washdays
washed
washer
washers
washes
washier
washiest
washing
washings
washout
washouts
washrag
washrags
washroom
washtub
washtubs
washup
washups
washy
wasp
waspier
waspiest
waspily
waspish
wasplike
wasps
waspy
wassail
wassails
wast
wastable
wastage
wastages
waste
wasted
wasteful
wastelot
waster
wasterie
wasters
wastery
wastes
wasteway
wasting
wastrel
wastrels
wastrie
wastries
wastry
wasts
wat
watap
watape
watapes
wataps
watch
watchcry
watchdog
watched
watcher
watchers
watches
watcheye
watchful
watching
watchman
watchmen
watchout
water
waterage
waterbed
waterdog
watered
waterer
waterers
waterier
waterily
watering
waterish
waterlog
waterloo
waterman
watermen
waters
waterway
watery
wats
watt
wattage
wattages
wattape
wattapes
watter
wattest
watthour
wattle
wattled
wattles
wattless
wattling
watts
waucht
wauchted
wauchts
waugh
waught
waughted
waughts
wauk
wauked
wauking
wauks
waul
wauled
wauling
wauls
waur
wave
waveband
waved
waveform
waveless
wavelet
wavelets
wavelike
waveoff
waveoffs
waver
wavered
waverer
waverers
wavering
wavers
wavery
waves
wavey
waveys
wavier
wavies
waviest
wavily
waviness
waving
wavy
waw
wawl
wawled
wawling
wawls
waws
wax
waxberry
waxbill
waxbills
waxed
waxen
waxer
waxers
waxes
waxier
waxiest
waxily
waxiness
waxing
waxings
waxlike
waxplant
waxweed
waxweeds
waxwing
waxwings
waxwork
waxworks
waxworm
waxworms
waxy
way
waybill
waybills
wayfarer
waygoing
waylaid
waylay
waylayer
waylays
wayless
ways
wayside
waysides
wayward
wayworn
we
weak
weaken
weakened
weakener
weakens
weaker
weakest
weakfish
weakish
weaklier
weakling
weakly
weakness
weakside
weal
weald
wealds
weals
wealth
wealths
wealthy
wean
weaned
weaner
weaners
weaning
weanling
weans
weapon
weaponed
weaponry
weapons
wear
wearable
wearer
wearers
wearied
wearier
wearies
weariest
weariful
wearily
wearing
wearish
wears
weary
wearying
weasand
weasands
weasel
weaseled
weaselly
weasels
weasely
weason
weasons
weather
weathers
weave
weaved
weaver
weavers
weaves
weaving
weazand
weazands
web
webbed
webbier
webbiest
webbing
webbings
webby
weber
webers
webfed
webfeet
webfoot
webless
weblike
webs
webster
websters
webwork
webworks
webworm
webworms
wecht
wechts
wed
wedded
wedder
wedders
wedding
weddings
wedel
wedeled
wedeling
wedeln
wedelns
wedels
wedge
wedged
wedges
wedgie
wedgier
wedgies
wedgiest
wedging
wedgy
wedlock
wedlocks
weds
wee
weed
weeded
weeder
weeders
weedier
weediest
weedily
weeding
weedless
weedlike
weeds
weedy
week
weekday
weekdays
weekend
weekends
weeklies
weeklong
weekly
weeks
weel
ween
weened
weenie
weenier
weenies
weeniest
weening
weens
weensier
weensy
weeny
weep
weeper
weepers
weepie
weepier
weepies
weepiest
weeping
weepings
weeps
weepy
weer
wees
weest
weet
weeted
weeting
weets
weever
weevers
weevil
weeviled
weevilly
weevils
weevily
weewee
weeweed
weewees
weft
wefts
weftwise
weigela
weigelas
weigelia
weigh
weighed
weigher
weighers
weighing
weighman
weighmen
weighs
weight
weighted
weighter
weights
weighty
weiner
weiners
weir
weird
weirder
weirdest
weirdie
weirdies
weirdly
weirdo
weirdoes
weirdos
weirds
weirdy
weirs
weka
wekas
welch
welched
welcher
welchers
welches
welching
welcome
welcomed
welcomer
welcomes
weld
weldable
welded
welder
welders
welding
weldless
weldment
weldor
weldors
welds
welfare
welfares
welkin
welkins
well
welladay
wellaway
wellborn
wellcurb
welldoer
welled
wellhead
wellhole
wellie
wellies
welling
wellness
wells
wellsite
welly
welsh
welshed
welsher
welshers
welshes
welshing
welt
welted
welter
weltered
welters
welting
weltings
welts
wen
wench
wenched
wencher
wenchers
wenches
wenching
wend
wended
wendigo
wendigos
wending
wends
wennier
wenniest
wennish
wenny
wens
went
wept
were
weregild
werewolf
wergeld
wergelds
wergelt
wergelts
wergild
wergilds
wert
werwolf
weskit
weskits
wessand
wessands
west
wester
westered
westerly
western
westerns
westers
westing
westings
westmost
wests
westward
wet
wetback
wetbacks
wether
wethers
wetland
wetlands
wetly
wetness
wetproof
wets
wettable
wetted
wetter
wetters
wettest
wetting
wettings
wettish
wha
whack
whacked
whacker
whackers
whackier
whacking
whacko
whackos
whacks
whacky
whale
whaled
whaleman
whalemen
whaler
whalers
whales
whaling
whalings
wham
whammed
whammies
whamming
whammo
whammy
whamo
whams
whang
whanged
whangee
whangees
whanging
whangs
whap
whapped
whapper
whappers
whapping
whaps
wharf
wharfage
wharfed
wharfing
wharfs
wharve
wharves
what
whatever
whatness
whatnot
whatnots
whats
whatsis
whatsit
whatsits
whaup
whaups
wheal
wheals
wheat
wheatear
wheaten
wheatens
wheats
whee
wheedle
wheedled
wheedler
wheedles
wheel
wheeled
wheeler
wheelers
wheelie
wheelies
wheeling
wheelman
wheelmen
wheels
wheen
wheens
wheep
wheeped
wheeping
wheeple
wheepled
wheeples
wheeps
wheeze
wheezed
wheezer
wheezers
wheezes
wheezier
wheezily
wheezing
wheezy
whelk
whelkier
whelks
whelky
whelm
whelmed
whelming
whelms
whelp
whelped
whelping
whelps
when
whenas
whence
whenever
whens
where
whereas
whereat
whereby
wherein
whereof
whereon
wheres
whereto
wherever
wherried
wherries
wherry
wherve
wherves
whet
whether
whets
whetted
whetter
whetters
whetting
whew
whews
whey
wheyey
wheyface
wheyish
wheylike
wheys
which
whicker
whickers
whid
whidah
whidahs
whidded
whidding
whids
whiff
whiffed
whiffer
whiffers
whiffet
whiffets
whiffing
whiffle
whiffled
whiffler
whiffles
whiffs
whig
whigs
while
whiled
whiles
whiling
whilom
whilst
whim
whimbrel
whimper
whimpers
whims
whimsey
whimseys
whimsied
whimsies
whimsy
whin
whinchat
whine
whined
whiner
whiners
whines
whiney
whinge
whinged
whinges
whinging
whinier
whiniest
whining
whinnied
whinnier
whinnies
whinny
whins
whiny
whip
whipcord
whiplash
whiplike
whipped
whipper
whippers
whippet
whippets
whippier
whipping
whippy
whipray
whiprays
whips
whipsaw
whipsawn
whipsaws
whipt
whiptail
whipworm
whir
whirl
whirled
whirler
whirlers
whirlier
whirlies
whirling
whirls
whirly
whirr
whirred
whirried
whirries
whirring
whirrs
whirry
whirs
whish
whished
whishes
whishing
whisht
whishted
whishts
whisk
whisked
whisker
whiskers
whiskery
whiskey
whiskeys
whiskies
whisking
whisks
whisky
whisper
whispers
whispery
whist
whisted
whisting
whistle
whistled
whistler
whistles
whists
whit
white
whitecap
whited
whitefly
whitely
whiten
whitened
whitener
whitens
whiteout
whiter
whites
whitest
whitey
whiteys
whither
whitier
whities
whitiest
whiting
whitings
whitish
whitlow
whitlows
whitrack
whits
whitter
whitters
whittle
whittled
whittler
whittles
whittret
whity
whiz
whizbang
whizz
whizzed
whizzer
whizzers
whizzes
whizzing
who
whoa
whodunit
whoever
whole
wholes
wholism
wholisms
wholly
whom
whomever
whomp
whomped
whomping
whomps
whomso
whoof
whoofed
whoofing
whoofs
whoop
whooped
whoopee
whoopees
whooper
whoopers
whooping
whoopla
whooplas
whoops
whoosh
whooshed
whooshes
whoosis
whop
whopped
whopper
whoppers
whopping
whops
whore
whored
whoredom
whores
whoreson
whoring
whorish
whorl
whorled
whorls
whort
whortle
whortles
whorts
whose
whosever
whosis
whosises
whoso
whump
whumped
whumping
whumps
why
whydah
whydahs
whys
wich
wiches
wick
wickape
wickapes
wicked
wickeder
wickedly
wicker
wickers
wicket
wickets
wicking
wickings
wickiup
wickiups
wicks
wickyup
wickyups
wicopies
wicopy
widder
widders
widdie
widdies
widdle
widdled
widdles
widdling
widdy
wide
wideband
widely
widen
widened
widener
wideners
wideness
widening
widens
wideout
wideouts
wider
wides
widest
widgeon
widgeons
widget
widgets
widish
widow
widowed
widower
widowers
widowing
widows
width
widths
widthway
wield
wielded
wielder
wielders
wieldier
wielding
wields
wieldy
wiener
wieners
wienie
wienies
wife
wifed
wifedom
wifedoms
wifehood
wifeless
wifelier
wifelike
wifely
wifes
wifing
wiftier
wiftiest
wifty
wig
wigan
wigans
wigeon
wigeons
wigged
wiggery
wiggier
wiggiest
wigging
wiggings
wiggle
wiggled
wiggler
wigglers
wiggles
wigglier
wiggling
wiggly
wiggy
wight
wights
wigless
wiglet
wiglets
wiglike
wigmaker
wigs
wigwag
wigwags
wigwam
wigwams
wikiup
wikiups
wilco
wild
wildcat
wildcats
wilder
wildered
wilders
wildest
wildfire
wildfowl
wilding
wildings
wildish
wildland
wildlife
wildling
wildly
wildness
wilds
wildwood
wile
wiled
wiles
wilful
wilfully
wilier
wiliest
wilily
wiliness
wiling
will
willable
willed
willer
willers
willet
willets
willful
willied
willies
willing
williwau
williwaw
willow
willowed
willower
willows
willowy
wills
willy
willyard
willyart
willying
willywaw
wilt
wilted
wilting
wilts
wily
wimble
wimbled
wimbles
wimbling
wimp
wimpier
wimpiest
wimpish
wimple
wimpled
wimples
wimpling
wimps
wimpy
win
wince
winced
wincer
wincers
winces
wincey
winceys
winch
winched
wincher
winchers
winches
winching
wincing
wind
windable
windage
windages
windbag
windbags
windburn
winded
winder
winders
windfall
windflaw
windgall
windier
windiest
windigo
windigos
windily
winding
windings
windlass
windle
windled
windles
windless
windling
windmill
window
windowed
windows
windpipe
windrow
windrows
winds
windsock
windsurf
windup
windups
windward
windway
windways
windy
wine
wined
wineless
wineries
winery
wines
wineshop
wineskin
winesop
winesops
winey
wing
wingback
wingbow
wingbows
wingding
winged
wingedly
winger
wingers
wingier
wingiest
winging
wingless
winglet
winglets
winglike
wingman
wingmen
wingover
wings
wingspan
wingtip
wingtips
wingy
winier
winiest
wining
winish
wink
winked
winker
winkers
winking
winkle
winkled
winkles
winkling
winks
winless
winnable
winned
winner
winners
winning
winnings
winnock
winnocks
winnow
winnowed
winnower
winnows
wino
winoes
winos
wins
winsome
winsomer
winter
wintered
winterer
winterly
winters
wintery
wintle
wintled
wintles
wintling
wintrier
wintrily
wintry
winy
winze
winzes
wipe
wiped
wipeout
wipeouts
wiper
wipers
wipes
wiping
wirable
wire
wired
wiredraw
wiredrew
wirehair
wireless
wirelike
wireman
wiremen
wirer
wirers
wires
wiretap
wiretaps
wireway
wireways
wirework
wireworm
wirier
wiriest
wirily
wiriness
wiring
wirings
wirra
wiry
wis
wisdom
wisdoms
wise
wiseacre
wiseass
wised
wiselier
wisely
wiseness
wisent
wisents
wiser
wises
wisest
wish
wisha
wishbone
wished
wisher
wishers
wishes
wishful
wishing
wishless
wising
wisp
wisped
wispier
wispiest
wispily
wisping
wispish
wisplike
wisps
wispy
wiss
wissed
wisses
wissing
wist
wistaria
wisted
wisteria
wistful
wisting
wists
wit
witan
witch
witched
witchery
witches
witchier
witching
witchy
wite
wited
wites
with
withal
withdraw
withdrew
withe
withed
wither
withered
witherer
withers
withes
withheld
withhold
withier
withies
withiest
within
withing
withins
without
withouts
withy
witing
witless
witling
witlings
witloof
witloofs
witness
witney
witneys
wits
witted
wittier
wittiest
wittily
witting
wittings
wittol
wittols
witty
wive
wived
wiver
wivern
wiverns
wivers
wives
wiving
wiz
wizard
wizardly
wizardry
wizards
wizen
wizened
wizening
wizens
wizes
wizzen
wizzens
wo
woad
woaded
woads
woadwax
woald
woalds
wobble
wobbled
wobbler
wobblers
wobbles
wobblier
wobblies
wobbling
wobbly
wobegone
wodge
wodges
woe
woeful
woefully
woeness
woes
woesome
woful
wofully
wog
wogs
wok
woke
woken
woks
wold
wolds
wolf
wolfed
wolfer
wolfers
wolffish
wolfing
wolfish
wolflike
wolfram
wolframs
wolfs
wolver
wolvers
wolves
woman
womaned
womaning
womanise
womanish
womanize
womanly
womans
womb
wombat
wombats
wombed
wombier
wombiest
wombs
womby
women
womera
womeras
wommera
wommeras
won
wonder
wondered
wonderer
wonders
wondrous
wonk
wonkier
wonkiest
wonks
wonky
wonned
wonner
wonners
wonning
wons
wont
wonted
wontedly
wonting
wonton
wontons
wonts
woo
wood
woodbin
woodbind
woodbine
woodbins
woodbox
woodchat
woodcock
woodcut
woodcuts
wooded
wooden
woodener
woodenly
woodhen
woodhens
woodie
woodier
woodies
woodiest
wooding
woodland
woodlark
woodless
woodlore
woodlot
woodlots
woodman
woodmen
woodnote
woodpile
woodruff
woods
woodshed
woodsia
woodsias
woodsier
woodsman
woodsmen
woodsy
woodwax
woodwind
woodwork
woodworm
woody
wooed
wooer
wooers
woof
woofed
woofer
woofers
woofing
woofs
wooing
wooingly
wool
wooled
woolen
woolens
wooler
woolers
woolfell
woolhat
woolhats
woolie
woolier
woolies
wooliest
woolled
woollen
woollens
woollier
woollies
woollike
woollily
woolly
woolman
woolmen
woolpack
wools
woolsack
woolshed
woolskin
woolwork
wooly
woomera
woomeras
woops
woopsed
woopses
woopsing
woorali
wooralis
woorari
wooraris
woos
woosh
wooshed
wooshes
wooshing
woozier
wooziest
woozily
woozy
wop
wops
word
wordage
wordages
wordbook
worded
wordier
wordiest
wordily
wording
wordings
wordless
wordplay
words
wordy
wore
work
workable
workaday
workbag
workbags
workboat
workbook
workbox
workday
workdays
worked
worker
workers
workfare
workfolk
working
workings
workless
workload
workman
workmate
workmen
workout
workouts
workroom
works
workshop
workup
workups
workweek
world
worldly
worlds
worm
wormed
wormer
wormers
wormhole
wormier
wormiest
wormil
wormils
worming
wormish
wormlike
wormroot
worms
wormseed
wormwood
wormy
worn
wornness
worried
worrier
worriers
worries
worrit
worrited
worrits
worry
worrying
worse
worsen
worsened
worsens
worser
worses
worset
worsets
worship
worships
worst
worsted
worsteds
worsting
worsts
wort
worth
worthed
worthful
worthier
worthies
worthily
worthing
worths
worthy
worts
wos
wost
wot
wots
wotted
wotting
would
wouldest
wouldst
wound
wounded
wounding
wounds
wove
woven
wovens
wow
wowed
wowing
wows
wowser
wowsers
wrack
wracked
wrackful
wracking
wracks
wraith
wraiths
wrang
wrangle
wrangled
wrangler
wrangles
wrangs
wrap
wrapped
wrapper
wrappers
wrapping
wraps
wrapt
wrasse
wrasses
wrassle
wrassled
wrassles
wrastle
wrastled
wrastles
wrath
wrathed
wrathful
wrathier
wrathily
wrathing
wraths
wrathy
wreak
wreaked
wreaker
wreakers
wreaking
wreaks
wreath
wreathe
wreathed
wreathen
wreathes
wreaths
wreathy
wreck
wreckage
wrecked
wrecker
wreckers
wreckful
wrecking
wrecks
wren
wrench
wrenched
wrenches
wrens
wrest
wrested
wrester
wresters
wresting
wrestle
wrestled
wrestler
wrestles
wrests
wretch
wretched
wretches
wrick
wricked
wricking
wricks
wried
wrier
wries
wriest
wriggle
wriggled
wriggler
wriggles
wriggly
wright
wrights
wring
wringed
wringer
wringers
wringing
wrings
wrinkle
wrinkled
wrinkles
wrinkly
wrist
wristier
wristlet
wrists
wristy
writ
writable
write
writer
writerly
writers
writes
writhe
writhed
writhen
writher
writhers
writhes
writhing
writing
writings
writs
written
wrong
wronged
wronger
wrongers
wrongest
wrongful
wronging
wrongly
wrongs
wrote
wroth
wrothful
wrought
wrung
wry
wryer
wryest
wrying
wryly
wryneck
wrynecks
wryness
wud
wurst
wursts
wurzel
wurzels
wuss
wusses
wussier
wussies
wussiest
wussy
wuther
wuthered
wuthers
wych
wyches
wye
wyes
wyle
wyled
wyles
wyling
wyn
wynd
wynds
wynn
wynns
wyns
wyte
wyted
wytes
wyting
wyvern
wyverns
xanthan
xanthans
xanthate
xanthein
xanthene
xanthic
xanthin
xanthine
xanthins
xanthoma
xanthone
xanthous
xebec
xebecs
xenia
xenial
xenias
xenic
xenogamy
xenogeny
xenolith
xenon
xenons
xerarch
xeric
xerosere
xeroses
xerosis
xerotic
xerox
xeroxed
xeroxes
xeroxing
xerus
xeruses
xi
xiphoid
xiphoids
xis
xu
xylan
xylans
xylem
xylems
xylene
xylenes
xylidin
xylidine
xylidins
xylitol
xylitols
xylocarp
xyloid
xylol
xylols
xylose
xyloses
xylotomy
xylyl
xylyls
xyst
xyster
xysters
xysti
xystoi
xystos
xysts
xystus
ya
yabber
yabbered
yabbers
yacht
yachted
yachter
yachters
yachting
yachtman
yachtmen
yachts
yack
yacked
yacking
yacks
yaff
yaffed
yaffing
yaffs
yager
yagers
yagi
yagis
yah
yahoo
yahooism
yahoos
yahrzeit
yaird
yairds
yak
yakitori
yakked
yakker
yakkers
yakking
yaks
yald
yam
yamalka
yamalkas
yamen
yamens
yammer
yammered
yammerer
yammers
yams
yamulka
yamulkas
yamun
yamuns
yang
yangs
yank
yanked
yanking
yanks
yanqui
yanquis
yantra
yantras
yap
yapock
yapocks
yapok
yapoks
yapon
yapons
yapped
yapper
yappers
yapping
yaps
yar
yard
yardage
yardages
yardarm
yardarms
yardbird
yarded
yarding
yardland
yardman
yardmen
yards
yardwand
yardwork
yare
yarely
yarer
yarest
yarmelke
yarmulke
yarn
yarned
yarner
yarners
yarning
yarns
yarrow
yarrows
yashmac
yashmacs
yashmak
yashmaks
yasmak
yasmaks
yatagan
yatagans
yataghan
yatter
yattered
yatters
yaud
yauds
yauld
yaup
yauped
yauper
yaupers
yauping
yaupon
yaupons
yaups
yautia
yautias
yaw
yawed
yawing
yawl
yawled
yawling
yawls
yawmeter
yawn
yawned
yawner
yawners
yawning
yawns
yawp
yawped
yawper
yawpers
yawping
yawpings
yawps
yaws
yay
yays
ycleped
yclept
ye
yea
yeah
yealing
yealings
yean
yeaned
yeaning
yeanling
yeans
year
yearbook
yearend
yearends
yearlies
yearling
yearlong
yearly
yearn
yearned
yearner
yearners
yearning
yearns
years
yeas
yeasayer
yeast
yeasted
yeastier
yeastily
yeasting
yeasts
yeasty
yecch
yecchs
yech
yechs
yechy
yeelin
yeelins
yegg
yeggman
yeggmen
yeggs
yeh
yeld
yelk
yelks
yell
yelled
yeller
yellers
yelling
yellow
yellowed
yellower
yellowly
yellows
yellowy
yells
yelp
yelped
yelper
yelpers
yelping
yelps
yen
yenned
yenning
yens
yenta
yentas
yente
yentes
yeoman
yeomanly
yeomanry
yeomen
yep
yerba
yerbas
yerk
yerked
yerking
yerks
yes
yeses
yeshiva
yeshivah
yeshivas
yeshivot
yessed
yesses
yessing
yester
yestern
yestreen
yet
yeti
yetis
yett
yetts
yeuk
yeuked
yeuking
yeuks
yeuky
yew
yews
yid
yids
yield
yielded
yielder
yielders
yielding
yields
yikes
yill
yills
yin
yince
yins
yip
yipe
yipes
yipped
yippee
yippie
yippies
yipping
yips
yird
yirds
yirr
yirred
yirring
yirrs
yirth
yirths
ylem
ylems
yo
yob
yobbo
yobboes
yobbos
yobs
yock
yocked
yocking
yocks
yod
yodel
yodeled
yodeler
yodelers
yodeling
yodelled
yodeller
yodels
yodh
yodhs
yodle
yodled
yodler
yodlers
yodles
yodling
yods
yoga
yogas
yogee
yogees
yogh
yoghourt
yoghs
yoghurt
yoghurts
yogi
yogic
yogin
yogini
yoginis
yogins
yogis
yogurt
yogurts
yoicks
yok
yoke
yoked
yokel
yokeless
yokelish
yokels
yokemate
yokes
yoking
yokozuna
yoks
yolk
yolked
yolkier
yolkiest
yolks
yolky
yom
yomim
yon
yond
yonder
yoni
yonic
yonis
yonker
yonkers
yore
yores
you
young
younger
youngers
youngest
youngish
youngs
younker
younkers
youpon
youpons
your
yourn
yours
yourself
youse
youth
youthen
youthens
youthful
youths
yow
yowe
yowed
yowes
yowie
yowies
yowing
yowl
yowled
yowler
yowlers
yowling
yowls
yows
yperite
yperites
ytterbia
ytterbic
yttria
yttrias
yttric
yttrium
yttriums
yuan
yuans
yuca
yucas
yucca
yuccas
yucch
yuch
yuck
yucked
yuckier
yuckiest
yucking
yucks
yucky
yuga
yugas
yuk
yukked
yukking
yuks
yulan
yulans
yule
yules
yuletide
yum
yummier
yummies
yummiest
yummy
yup
yupon
yupons
yuppie
yuppies
yups
yurt
yurta
yurts
ywis
zabaione
zabajone
zacaton
zacatons
zaddick
zaddik
zaddikim
zaffar
zaffars
zaffer
zaffers
zaffir
zaffirs
zaffre
zaffres
zaftig
zag
zagged
zagging
zags
zaibatsu
zaikai
zaikais
zaire
zaires
zamarra
zamarras
zamarro
zamarros
zamia
zamias
zamindar
zanana
zananas
zander
zanders
zanier
zanies
zaniest
zanily
zaniness
zany
zanyish
zanza
zanzas
zap
zapateo
zapateos
zapped
zapper
zappers
zappier
zappiest
zapping
zappy
zaps
zaptiah
zaptiahs
zaptieh
zaptiehs
zaratite
zareba
zarebas
zareeba
zareebas
zarf
zarfs
zariba
zaribas
zarzuela
zastruga
zastrugi
zax
zaxes
zayin
zayins
zazen
zazens
zeal
zealot
zealotry
zealots
zealous
zeals
zeatin
zeatins
zebec
zebeck
zebecks
zebecs
zebra
zebraic
zebras
zebrass
zebrine
zebroid
zebu
zebus
zecchin
zecchini
zecchino
zecchins
zechin
zechins
zed
zedoary
zeds
zee
zees
zein
zeins
zek
zeks
zelkova
zelkovas
zemindar
zemstva
zemstvo
zemstvos
zenaida
zenaidas
zenana
zenanas
zenith
zenithal
zeniths
zeolite
zeolites
zeolitic
zephyr
zephyrs
zeppelin
zerk
zerks
zero
zeroed
zeroes
zeroing
zeros
zeroth
zest
zested
zester
zesters
zestful
zestier
zestiest
zesting
zestless
zests
zesty
zeta
zetas
zeugma
zeugmas
zibeline
zibet
zibeth
zibeths
zibets
zig
zigged
zigging
ziggurat
zigs
zigzag
zigzags
zikkurat
zikurat
zikurats
zilch
zilches
zill
zillah
zillahs
zillion
zillions
zills
zin
zinc
zincate
zincates
zinced
zincic
zincify
zincing
zincite
zincites
zincked
zincking
zincky
zincoid
zincous
zincs
zincy
zineb
zinebs
zing
zingani
zingano
zingara
zingare
zingari
zingaro
zinged
zinger
zingers
zingier
zingiest
zinging
zings
zingy
zinkify
zinky
zinnia
zinnias
zins
zip
zipless
zipped
zipper
zippered
zippers
zippier
zippiest
zipping
zippy
zips
ziram
zirams
zircon
zirconia
zirconic
zircons
zit
zither
zithern
zitherns
zithers
ziti
zitis
zits
zizit
zizith
zizzle
zizzled
zizzles
zizzling
zlote
zloties
zloty
zlotych
zlotys
zoa
zoaria
zoarial
zoarium
zodiac
zodiacal
zodiacs
zoea
zoeae
zoeal
zoeas
zoecia
zoecium
zoftig
zoic
zoisite
zoisites
zombi
zombie
zombies
zombify
zombiism
zombis
zonal
zonally
zonary
zonate
zonated
zonation
zone
zoned
zoneless
zoner
zoners
zones
zonetime
zoning
zonk
zonked
zonking
zonks
zonula
zonulae
zonular
zonulas
zonule
zonules
zoo
zoochore
zooecia
zooecium
zoogenic
zooglea
zoogleae
zoogleal
zoogleas
zoogloea
zooid
zooidal
zooids
zooks
zoolater
zoolatry
zoologic
zoology
zoom
zoomania
zoomed
zoometry
zooming
zoomorph
zooms
zoon
zoonal
zoonoses
zoonosis
zoonotic
zoons
zoophile
zoophily
zoophobe
zoophyte
zoos
zoosperm
zoospore
zootier
zootiest
zootomic
zootomy
zooty
zori
zoril
zorilla
zorillas
zorille
zorilles
zorillo
zorillos
zorils
zoris
zoster
zosters
zouave
zouaves
zounds
zowie
zoysia
zoysias
zucchini
zwieback
zydeco
zydecos
zygoid
zygoma
zygomas
zygomata
zygose
zygoses
zygosis
zygosity
zygote
zygotene
zygotes
zygotic
zymase
zymases
zyme
zymes
zymogen
zymogene
zymogens
zymogram
zymology
zymosan
zymosans
zymoses
zymosis
zymotic
zymurgy
zyzzyva
zyzzyvas


Answers to Questions and Exercises: (The Java™ Tutorials > Collections > Interfaces)

Trail: Collections
Lesson: Interfaces
Home Page > Collections > Interfaces
« Previous • TOC
Answers to Questions and Exercises:

Questions

  1. Question: This lesson mentions three ways to traverse a List. Describe them, and note the limitations of each.

    Answer:

    • Use the enhanced for statement:
      List<Thing> list;
...
for (Thing thing : list) {
    ...
}
      Limitations: cannot be used to add, remove, or modify elements.
    • Use the traditional for statement together with an Iterator:
      List<Thing> list;
...
for (Iterator<Thing> it = list.iterator(); it.hasNext(); ) {
    Thing thing = it.next();
    ...
}
      Limitations: cannot be used to modify elements.
    • Use the traditional for statement together with an ListIterator:
      List<Thing> list;
...
for (ListIterator<Thing> it = list.iterator(); it.hasNext(); ) {
    Thing thing = it.next();
    ...
}
      Limitations: none.
  2. Question: Consider the four core interfaces, Set, List, Queue, and Map. For each of the following four assignments, specify which of the four core interfaces is best-suited, and explain how to use it to implement the assignment.

    Answer:

    • Whimsical Toys Inc (WTI) needs to record the names of all its employees. Every month, an employee will be chosen at random from these records to receive a free toy.
      Use a List. Choose a random employee by picking a number between 0 and size()-1.
    • WTI has decided that each new product will be named after an employee — but only first names will be used, and each name will be used only once. Prepare a list of unique first names.
      Use a Set. Collections that implement this interface don't allow the same element to be entered more than once.
    • WTI decides that it only wants to use the most popular names for its toys. Count up the number of employees who have each first name.
      Use a Map, where the keys are first names, and each value is a count of the number of employees with that first name.
    • WTI acquires season tickets for the local lacrosse team, to be shared by employees. Create a waiting list for this popular sport.
      Use a Queue. Invoke add() to add employees to the waiting list, and remove() to remove them.

  3. Question: The following program is supposed to print the string "Blue". Instead, it throws an error. Why?
    import java.util.*;

public class SortMe {
    public static void main(String args[]) {
        SortedSet<StringBuffer> s = new TreeSet<StringBuffer>();
        s.add(new StringBuffer("Red"));
        s.add(new StringBuffer("White"));
        s.add(new StringBuffer("Blue"));
        System.out.println(s.first());
    }
}

    Answer: TreeSort elements must be instances of a class that implements Comparable. StringBuffer does not.

Exercises

  1. Exercise: Write a program that prints its arguments in random order. Do not make a copy of the argument array.

    Answer:

    /*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.*;

public class Ran {
    public static void main(String[] args) {
        List<String> argList = Arrays.asList(args);
        Collections.shuffle(argList);
        for (String arg: argList) {
            System.out.format("%s ", arg);
        }
        System.out.println();
    }
}
  2. Exercise: Take the FindDups example and modify it to use a SortedSet instead of a Set. Specify a Comparator so that case is ignored when sorting and identifying set elements.

    Answer:

    /*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.*;

public class FindDups {

    public static void main(String[] args) {
        Comparator<String> comparator = new Comparator<String>() {
            public int compare (String s1, String s2) {
                return s1.compareToIgnoreCase(s2);
            }
        };

        SortedSet<String> s = new TreeSet<String>(comparator);
        for (String a : args)
            if (!s.add(a))
                System.out.println("Duplicate detected: " + a);

        System.out.println(s.size() + " distinct words: " + s);
    }
}
  3. Exercise: Write a method that takes a List<String> and applies String.trim to each element. To do this, you'll need to pick one of the three iteration idioms that you described in Question 1. Two of these will not give the result you want, so be sure to write a program that demonstrates that the method actually works!

    Answer: The enhanced for statement does not allow you to modify the List. Using an Iterator allows you to add and delete elements, but not replace existing element. That leaves ListIterator:

    /*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.*;

public class ListTrim {
    static void listTrim(List<String> strings) {
        for (ListIterator<String> lit = strings.listIterator();
                lit.hasNext(); ) {
            lit.set(lit.next().trim());
        }
    }

    public static void main(String[] args) {
        List<String> l = Arrays.asList(" red ", " white ", " blue ");
        listTrim(l);
        for (String s : l) {
            System.out.format("\"%s\"%n", s);
        }
    }
}
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Interfaces


  • Prioritized List of Improvements
  • Highlights of User Feedback

Name of Reviewer: | Ray Ortigas
Current Trail Author(s): | Josh Bloch
Was the author contacted? | Yes If yes, Date: 13 Aug 1999
Comments:

Prioritized List of Improvements/Corrections:

 Priority Scale:
(1-5)
1 = immediate attention required
3 = fix in next public push (2-3 weeks)
5 = when you get a chance...

  1. At the following statement needs to be clarified:

    "The arrays returned by the Collection-views' toArray operations contains the keys, values, or entries in order."

    The keys and entries are sorted by key, as expected, but so are the values. That is, the values are not ordered by value, but according to the keys to which they're matched. The above statement seems to indicate that the values array returned will be ordered by value.

    This has been brought to Josh's attention.

    priority (1-5): 3

  2. At I'm still having problems understanding this:

    "[SortedMap provides a constructor] that takes a SortedMap and returns a new SortedMap containing the same mappings as the given SortedMap, and sorted according to the same Comparator (or using the elements' natural ordering, if the specified SortedMap did too). Note that it is the compile-time type of the argument that determines whether this constructor is invoked in preference to the ordinary Map constructor, and not its runtime type!"

    This has been brought to Josh's attention. priority (1-5): 4

  3. A user noted that the following sentence at is misleading.

    "The fact that the new implementations are unsynchronized represents a break with the past: Vector and Hashtable were synchronized in versions of the JDK prior to 1.2."

    This sentence seems to indicate that Vector and Hashtable are no longer synchronized.

    This has been brought to Josh's attention.

    priority (1-5): 4

  4. Recommendation4
    description
    priority (1-5):

Highlights of User Feedback:

  • Date:
    User1's email

  • Date:
    User2's email

  • Date:
    User3's email

  • Date:
    User4's email


Deployment: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
Deployment: End of Trail
You've reached the end of the "Deployment" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

The Extension Mechanism: You can bundle your classes and interfaces into a JAR file use them to extend the standard JDK.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Java Applets


Trail: Deployment: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: Deployment: Table of Contents
Packaging Programs in JAR Files
Using JAR Files: The Basics
Creating a JAR File
Viewing the Contents of a JAR File
Extracting the Contents of a JAR File
Updating a JAR File
Running JAR-Packaged Software
Working with Manifest Files: The Basics
Understanding the Default Manifest
Modifying a Manifest File
Setting an Application's Entry Point
Adding Classes to the JAR File's Classpath
Setting Package Version Information
Sealing Packages within a JAR File
Signing and Verifying JAR Files
Understanding Signing and Verification
Signing JAR Files
Verifying Signed JAR Files
Using JAR-related APIs
The JarClassLoader Class
The JarRunner Class
Java Web Start
Running Java Web Start Applications
Deploying Java Web Start Applications
Developing Java Web Start Applications
The JNLP API
Java Web Start and Security
Common Java Web Start Problems
Questions and Exercises: Java Web Start
Applets
Getting Started with Applets
Importing Classes and Packages for Applets
Defining an Applet Subclass
The Life Cycle of an Applet
Methods for Milestones
Methods for Drawing and Event Handling
Methods for Adding UI Components
What Applets Can and Can't Do
Taking Advantage of the Applet API
Finding and Loading Data Files
Displaying Short Status Strings
Displaying Documents in the Browser
Sending Messages to Other Applets
Playing Sounds
Defining and Using Applet Parameters
Deciding Which Parameters to Support
Writing the Code to Support Parameters
Giving Information about Parameters
Using the APPLET Tag
Practical Considerations When Writing Applets
Security Restrictions
Creating a User Interface
Creating a GUI
Displaying Diagnostics to the Standard Output and Error Streams
Getting System Properties
Threads in Applets
Threads in Applets: Examples
Working with a Server-Side Application
A Simple Network Client Applet
Using a Server to Work Around Security Restrictions
Finishing an Applet
Before You Ship that Applet
The Perfectly Finished Applet
Deploying Applets
General Deployment Considerations
Using the applet Tag
Using the object Tag
Using the embed Tag
Deploying Applets in a Mixed-Browser Environment
Solving Common Applet Problems
Questions and Exercises: Java Applets
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Life is wonderful. Without it we'd all be dead.
Daddy, why doesn't this magnet pick up this floppy disk?
Give me ambiguity or give me something else.
I.R.S.: We've got what it takes to take what you've got!
We are born naked, wet and hungry. Then things get worse.
Make it idiot proof and someone will make a better idiot.
He who laughs last thinks slowest!
Always remember you're unique, just like everyone else.
"More hay, Trigger?" "No thanks, Roy, I'm stuffed!"
A flashlight is a case for holding dead batteries.
Lottery: A tax on people who are bad at math.
Error, no keyboard - press F1 to continue.
There's too much blood in my caffeine system.
Artificial Intelligence usually beats real stupidity.
Hard work has a future payoff. Laziness pays off now.
"Very funny, Scotty. Now beam down my clothes."
Puritanism: The haunting fear that someone, somewhere may be happy.
Consciousness: that annoying time between naps.
Don't take life too seriously, you won't get out alive.
I don't suffer from insanity. I enjoy every minute of it.
Better to understand a little than to misunderstand a lot.
The gene pool could use a little chlorine.
When there's a will, I want to be in it.
Okay, who put a "stop payment" on my reality check?
We have enough youth, how about a fountain of SMART?
Programming is an art form that fights back.
"Daddy, what does FORMATTING DRIVE C mean?"
All wiyht. Rho sritched mg kegtops awound?
My mail reader can beat up your mail reader.
Never forget: 2 + 2 = 5 for extremely large values of 2.
Nobody has ever, ever, EVER learned all of WordPerfect.
To define recursion, we must first define recursion.
Good programming is 99% sweat and 1% coffee.
Home is where you hang your @
The E-mail of the species is more deadly than the mail.
A journey of a thousand sites begins with a single click.
You can't teach a new mouse old clicks.
Great groups from little icons grow.
Speak softly and carry a cellular phone.
C:\ is the root of all directories.
Don't put all your hypes in one home page.
Pentium wise; pen and paper foolish.
The modem is the message.
Too many clicks spoil the browse.
The geek shall inherit the earth.
A chat has nine lives.
Don't byte off more than you can view.
Fax is stranger than fiction.
What boots up must come down.
Windows will never cease.   (ed. oh sure...)
In Gates we trust.    (ed.  yeah right....)
Virtual reality is its own reward.
Modulation in all things.
A user and his leisure time are soon parted.
There's no place like http://www.home.com
Know what to expect before you connect.
Oh, what a tangled website we weave when first we practice.
Speed thrills.
Give a man a fish and you feed him for a day; teach him to use the Net and he won't bother you for weeks.


Answers to Questions and Exercises: Java Applets (The Java™ Tutorials > Deployment > Applets)

Trail: Deployment
Lesson: Applets
Home Page > Deployment > Applets
« Previous • TOC
Answers to Questions and Exercises: Java Applets

Questions

  1. Question: Which classes can an applet extend?

    Answer: An applet can extend the java.applet.Applet class or the java.swing.JApplet class.

    The java.applet.Applet class extends the java.awt.Panel class and enables you to use the GUI tools in the AWT package.

    The java.swing.JApplet class is a subclass of java.applet.Applet that also enables you to use the Swing GUI tools.

  2. Question: How do you cause the applet GUI in the browser to be refreshed when data in it may have changed?

    Answer: You invoke the repaint() method. This method causes the paint method, which is required in any applet, to be invoked again, updating the display.

  3. Question: For what do you use the start() method?

    Answer: You use the start() method when the applet must perform a task after it is initialized, before receiving user input. The start() method either performs the applet's work or (more likely) starts up one or more threads to perform the work.

  4. Question: True or false: An applet can make network connections to any host on the Internet.

    Answer: False: An applet can only connect to the host that it came from.

  5. Question: How do you get the value of a parameter specified in the APPLET tag from within the applet's code?

    Answer: You use the getParameter("Parameter name") method, which returns the String value of the parameter.

  6. Question: True of false: An applet can run multiple threads.

    Answer: True. The paint and update methods are always called from the AWT drawing and event handling thread. You can have your applet create additional threads, which is recommended for performing time-consuming tasks.

  7. Question: Match the following tag names with the descriptions in the following lists:
    1. EMBED tag
    2. APPLET tag
    3. OBJECT tag

    1. Use to deploy applets to a multi-browser environment.
    2. Use to deploy applets that are to be used only with the Mozilla family of browsers
    3. Use to deploy applets that are to be used only with Internet Explorer

    Answer:

    1. EMBED tag: b
    2. APPLET tag: a
    3. OBJECT tag: c

Exercises

  1. Exercise: For an applet using the Exercise class, write the Applet tag that sets the ButtonName parameter to Save.

    Answer:

    <APPLET CODE=AppletButton.class>
  <PARAM NAME=ButtonName VALUE=Save>
</APPLET>

  2. Exercise: Write the method to display an applet in the browser, so that the contents are contained in a rectangle around the phrase "Exercise Applet". Have the applet be one pixel less than the size specified ont he web page, and the phrase starting at the coordinates 5, 15.

    Answer:

    public void paint(Graphics g) {
    //Draw a Rectangle around the applet's display area.
        g.drawRect(0, 0,
           getWidth() - 1,
           getHeight() - 1);

    //Draw the current string inside the rectangle.
        g.drawString("Exercise Applet", 5, 15);
    }
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Java Applets


TicTacToe

The source.


Questions

  1. Question: How do you invoke an applet that is packaged as a JAR file?

    Answer: To invoke an applet packaged as a JAR file, open a page containing the applet: <applet code=AppletClassName.class archive="JarFileName.jar" width=320 height=240> </applet>

  2. Question: What is the purpose of the -e option in a jar command?

    Answer: This option is available since Java SE 6. It sets the entrypoint as the application entry point for stand-alone applications bundled into executable jar file. The use of this option creates or overrides the Main-Class attribute value in the manifest file. This option can be used during creation of jar file or while updating the jar file. This option specifies the application entry point without editing or creating the manifest file. For example, this command creates Main.jar where the Main-Class attribute value in the manifest is set to Main: jar cfe Main.jar Main Main.class

  3. Question: What is the significance of the manifest in a JAR file?

    Answer: A JAR file's manifest provides meta-information about the other contents of the JAR file. The manifest itself resides in META-INF/MANIFEST.mf. The meta-information can include

    • Dependencies on other jar files
    • The name of a class to run when "java -jar file.jar" is invoked
    • Versioning information
    • Security information

  4. Question: How do you modify a JAR's manifest file?

    Answer: Typically, modifying the default manifest involves adding special-purpose headers to the manifest that allow the JAR file to perform a particular desired function.

    To modify the manifest, you must first prepare a text file with a complete and valid manifest file. You then use the JAR tool's m option to add the information in your file to the manifest.

    The manifest file your prepare must end with a new line or carriage return. The last line will not be parsed properly if it does not end with a new line or carriage return.


Questions

  1. How do you invoke an applet that is packaged as a JAR file?

  2. What is the purpose of the -e option in a jar command?

  3. What is the significance of the manifest in a JAR file?

  4. How do you modify a JAR's manifest file?


Answers to Questions and Exercises: Java Web Start (The Java™ Tutorials > Deployment > Java Web Start)

Trail: Deployment
Lesson: Java Web Start
Home Page > Deployment > Java Web Start
« Previous • TOC
Answers to Questions and Exercises: Java Web Start

Questions

  1. Question: In a link that is to run a Java Web Start application, which file is specified as the a tag's href attribute?

    Answer: You use the application's JNLP file name as the value of the href attribute. When a user clicks the link to the JNLP file, Java Web Start loads the application specified by that JNLP file.

  2. Question: Which MIME type must a Web server recognize in order for it to host Java Web Start applications?

    Answer: You must configure the Web server so that files with the .jnlp extension are set to the application/x-java-jnlp-file MIME type.

  3. Question: In an application's JNLP file, which two elements must be specified within the resources element?

    Answer: The resources element must contain:

    • The j2se element, which specifies the Java platform on which to run the application.
    • The jar element, which specifies the JAR file for the application.

  4. Question: Which interface provides the ability to an application to control how its own resources are cached?

    1. BasicService
    2. DownloadService
    3. PersistenceService
    4. ExtendedService

    Answer: B. The DownloadService interface provides the ability to an application to control how its own resources are cached.

  5. Question: True or False: Java Web Start applications run in a secure sandbox by default.

    Answer: True.

  6. Question: True or False: If a Java Web Start application is running in a secure sandbox, JAR files for the application can reside on different servers.

    Answer: False. All JAR files for the application must reside on the same server.

  7. Question: For a Java Web Start application to support operations outside of the secure sandbox, what must you do with its JAR files?

    Answer: You must sign JAR files to enable your application can work outside of the sandbox.

Exercises

  1. Exercise: Write the XML code you would add to a JNLP file in order to request that the application have complete access to the client system.

    Answer:

    <security>
   <all-permissions/>
</security>

  2. Exercise: For a Java Web Start application, you have two icons, one.gif and two.gif, in the images directory in a JAR file. Write the application code you would use to access these images.

    Answer:

    // Get current classloader
ClassLoader cl = this.getClass().getClassLoader();
// Create icons
Icon firstIcon  = new ImageIcon(cl.getResource("images/one.gif"));
Icon secondIcon   = new ImageIcon(cl.getResource("images/two.gif"));
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Java Web Start


The Java Tutorial Redirect

The page "A Drag and Drop Example by Sheetal Gupta" is no longer available.

We'll be adding new examples soon. For now refer to the resources listed at the start of this trail.
(Your browser should automatically take you there in 10 seconds.)


Essential Classes: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
Essential Classes: End of Trail
You've reached the end of the "Essential Classes" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

Creating a GUI with JFC/Swing: Once you know how to create applications or applets, follow this trail to learn how to create their user interfaces.

Collections: Using the classes and interfaces in the collections framework you can group objects together into a single object.

Internationalization: Essential if you want to create a program that can be used by people all over the world. Furthermore, you can use the information about formatting dates, numbers, and strings in any program.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Regular Expressions


Trail: Essential Classes: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: Essential Classes: Table of Contents
Exceptions
What Is an Exception?
The Catch or Specify Requirement
Catching and Handling Exceptions
The try Block
The catch Blocks
The finally Block
Putting It All Together
Specifying the Exceptions Thrown by a Method
How to Throw Exceptions
Chained Exceptions
Creating Exception Classes
Unchecked Exceptions — The Controversy
Advantages of Exceptions
Summary
Questions and Exercises
Basic I/O
I/O Streams
Byte Streams
Character Streams
Buffered Streams
Scanning and Formatting
Scanning
Formatting
I/O from the Command Line
Data Streams
Object Streams
File I/O
File Objects
Random Access Files
The New I/O Packages
Summary
Questions and Exercises: Basic I/O
Concurrency
Processes and Threads
Thread Objects
Defining and Starting a Thread
Pausing Execution with Sleep
Interrupts
Joins
The SimpleThreads Example
Synchronization
Thread Interference
Memory Consistency Errors
Synchronized Methods
Intrinsic Locks and Synchronization
Atomic Access
Liveness
Deadlock
Starvation and Livelock
Guarded Blocks
Immutable Objects
A Synchronized Class Example
A Strategy for Defining Immutable Objects
High Level Concurrency Objects
Lock Objects
Executors
Executor Interfaces
Thread Pools
Concurrent Collections
Atomic Variables
For Further Reading
Questions and Exercises: Concurrency
The Platform Environment
Configuration Utilities
Properties
Command-Line Arguments
Environment Variables
Other Configuration Utilities
System Utilities
Command-Line I/O Objects
System Properties
The Security Manager
Miscellaneous Methods in System
PATH and CLASSPATH
Questions and Exercises: The Platform Environment
Regular Expressions
Introduction
Test Harness
String Literals
Character Classes
Predefined Character Classes
Quantifiers
Capturing Groups
Boundary Matchers
Methods of the Pattern Class
Methods of the Matcher Class
Methods of the PatternSyntaxException Class
Additional Resources
Questions and Exercises: Regular Expressions
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Answers to Questions and Exercises: Concurrency (The Java™ Tutorials > Essential Classes > Concurrency)

Trail: Essential Classes
Lesson: Concurrency
Home Page > Essential Classes > Concurrency
« Previous • TOC
Answers to Questions and Exercises: Concurrency

Questions

  1. Question: Can you pass a Thread object to Executor.execute? Would such an invocation make sense? Why or why not?

    Answer: Thread implements the Runnable interface, so you can pass an instance of Thread to Executor.execute. However it doesn't make sense to use Thread objects this way. If the object is directly instantiated from Thread, its run method doesn't do anything. You can define a subclass of Thread with a useful run method — but such a class would implement features that the executor would not use.

Exercises

  1. Exercise: Compile and run BadThreads.java:
    /*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class BadThreads {

    static String message;

    private static class CorrectorThread extends Thread {

        public void run() {
            try {
                sleep(1000);
            } catch (InterruptedException e) {}
            //Key statement 1:
            message = "Mares do eat oats.";
        }
    }

    public static void main(String args[]) throws InterruptedException {
        (new CorrectorThread()).start();
        message = "Mares do not eat oats.";
        Thread.sleep(2000);
        //Key statement 2:
        System.out.println(message);
    }
}

    The application should print out "Mares do eat oats." Is it guaranteed to always do this? If not, why not? Would it help to change the parameters of the two invocations of Sleep? Describe two ways to change the program to enforce such a guarantee.

    Solution: The program will almost always print out "Mares do eat oats." However, this result is not guaranteed, because there is no happens-before relationship between "Key statement 1" and "Key statment 2". This is true even if "Key statement 1" actually executes before "Key statement 2" — remember, a happens-before relationship is about visibility, not sequence.

    There are two ways you can guarantee that all changes to message will be visible to the main thread:

    • In the main thread, retain a reference to the CorrectorThread instance. Then invoke join on that instance before referring to message
    • Encapsulate message in an object with synchronized methods. Never reference message except through those methods.

    Both of these techniques establish the necessary happens-before relationship, making changes to message visible.

    A third technique is to simply declare message as volatile. This guarantees that any write to message (as in "Key statement 1") will have a happens-before relationship with any subsequent reads of message (as in "Key statement 2"). But it does not guarantee that "Key statement 1" will literally happen before "Key statement 2". They will probably happen in sequence, but because of scheduling uncertainities and the unknown granularity of sleep, this is not guaranteed.

    Changing the arguments of the two sleep invocations does not help either, since this does nothing to guarantee a happens-before relationship.

  2. Exercise: Modify the producer-consumer example in Guarded Blocks to use a standard library class instead of the Drop class.

    Solution: The java.util.concurrent.BlockingQueue interface defines a get method that blocks if the queue is empty, and a put methods that blocks if the queue is full. These are effectively the same operations defined by Drop — except that Drop is not a queue! However, there's another way of looking at Drop: it's a queue with a capacity of zero. Since there's no room in the queue for any elements, every get blocks until the corresponding take and every take blocks until the corresponding get. There is an implementation of BlockingQueue with precisely this behavior: java.util.concurrent.SynchronousQueue.

    BlockingQueue is almost a drop-in replacement for Drop. The main problem in Producer is that with BlockingQueue, the put and get methods throw InterruptedException. This means that the existing try must be moved up a level:

    /*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.Random;
import java.util.concurrent.BlockingQueue;

public class Producer implements Runnable {
    private BlockingQueue<String> drop;

    public Producer(BlockingQueue<String> drop) {
        this.drop = drop;
    }

    public void run() {
        String importantInfo[] = {
            "Mares eat oats",
            "Does eat oats",
            "Little lambs eat ivy",
            "A kid will eat ivy too"
        };
        Random random = new Random();

        try {
            for (int i = 0; i < importantInfo.length; i++) {
                drop.put(importantInfo[i]);
                Thread.sleep(random.nextInt(5000));
            }
            drop.put("DONE");
        } catch (InterruptedException e) {}
    }
}
    Similar changes are required for Consumer:
    /*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.Random;
import java.util.concurrent.BlockingQueue;

public class Consumer implements Runnable {
    private BlockingQueue<String> drop;

    public Consumer(BlockingQueue<String> drop) {
        this.drop = drop;
    }

    public void run() {
        Random random = new Random();
        try {
            for (String message = drop.take(); ! message.equals("DONE");
                    message = drop.take()) {
                System.out.format("MESSAGE RECEIVED: %s%n", message);
                Thread.sleep(random.nextInt(5000));
            }
        } catch (InterruptedException e) {}
    }
}
    For ProducerConsumerExample, we simply change the declaration for the drop object:
    /*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.SynchronousQueue;

public class ProducerConsumerExample {
    public static void main(String[] args) {
        BlockingQueue<String> drop = new SynchronousQueue<String> ();
        (new Thread(new Producer(drop))).start();
        (new Thread(new Consumer(drop))).start();
    }
}
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Concurrency


subliminal.message=Buy StayPuft Marshmallows!


Answers to Questions and Exercises: The Platform Environment (The Java™ Tutorials > Essential Classes > The Platform Environment)

Trail: Essential Classes
Lesson: The Platform Environment
Home Page > Essential Classes > The Platform Environment
« Previous • TOC
Answers to Questions and Exercises: The Platform Environment

Questions

Question 1.A programmer installs a new library contained in a .jar file. In order to access the library from his code, he sets the CLASSPATH environment variable to point to the new .jar file. Now he finds that he gets an error message when he tries to launch simple applications:

java Hello
Exception in thread "main" java.lang.NoClassDefFoundError: Hello
In this case, the Hello class is compiled into a .class file in the current directory — yet the java command can't seem to find it. What's going wrong?

Answer 1. A class is only found if it appears in the class path. By default, the class path consists of the current directory. If the CLASSPATH environment variable is set, and doesn't include the current directory, the launcher can no longer find classes in the current directory. The solution is to change the CLASSPATH variable to include the current directory. For example, if the CLASSPATH value is c:\java\newLibrary.jar (Windows) or /home/me/newLibrary.jar (UNIX or Linux) it needs to be changed to .;c:\java\newLibrary.jar or .:/home/me/newLibrary.jar.

Exercises

Exercise 1. Write an application, PersistentEcho, with the following features:

  • If PersistentEcho is run with command line arguments, it prints out those arguments. It also saves the string printed out to a property, and saves the property to a file called PersistentEcho.txt
  • If PersistentEcho is run with no command line arguments, it looks for an environment variable called PERSISTENTECHO. If that variable exists, PersistentEcho prints out its value, and also saves the value in the same way it does for command line arguments.
  • If PersistentEcho is run with no command line arguments, and the PERSISTENTECHO environment variable is not defined, it retrieves the property value from PersistentEcho.txt and prints that out.

Answer 1.
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

import java.util.Properties;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

public class PersistentEcho {
    public static void main (String[] args) {
        String argString = "";
        boolean notProperty = true;

        //Are there arguments? If so retrieve them.
        if (args.length > 0) {
            for (String arg: args) {
                argString += arg + " ";
            }
            argString = argString.trim();
        }
        //No arguments, is there an environment variable? If so,
        //retrieve it.
        else if ((argString = System.getenv("PERSISTENTECHO")) != null) {}
        //No environment variable either. Retrieve property value.
        else {
            notProperty = false;
            //Set argString to null. If it's still null after we exit
            //the try block, we've failed to retrieve the property
            //value.
            argString = null;
            FileInputStream fileInputStream = null;
            try {
                fileInputStream = new FileInputStream("PersistentEcho.txt");
                Properties inProperties = new Properties();
                inProperties.load(fileInputStream);
                argString = inProperties.getProperty("argString");
            } catch (IOException e) {
                System.err.println("Can't read property file.");
                System.exit(1);
            } finally {
                if (fileInputStream != null) {
                    try {
                        fileInputStream.close();
                    } catch(IOException e) {};
                }
            }
        }
        if (argString == null) {
            System.err.println("Couldn't find argString property");
            System.exit(1);
        }

        //Somehow, we got the value. Echo it already!
        System.out.println(argString);

        //If we didn't retrieve the value from the property, save it
        //in the property.
        if (notProperty) {
            Properties outProperties = new Properties();
            outProperties.setProperty("argString", argString);
            FileOutputStream fileOutputStream = null;
            try {
                fileOutputStream = new FileOutputStream("PersistentEcho.txt");
                outProperties.store(fileOutputStream,
                        "PersistentEcho properties");
            } catch (IOException e) {}
            finally {
                if (fileOutputStream != null) {
                    try {
                        fileOutputStream.close();
                    } catch(IOException e) {};
                }
            }
        }
    }
}

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: The Platform Environment


Answers to Questions and Exercises (The Java™ Tutorials > Essential Classes > Exceptions)

Trail: Essential Classes
Lesson: Exceptions
Home Page > Essential Classes > Exceptions
« Previous • TOC
Answers to Questions and Exercises

Questions

  1. Question: Is the following code legal?
    try {

} finally {

}
    Answer: Yes, it's legal — and very useful A try statement does not have to have a catch block if it has a finally block. If the code in the try statement has multiple exit points and no associated catch clauses, the code in the finally block is executed no matter how the try block is exited. Thus it makes sense to provide a finally block whenever there is code that must always be executed. This include resource recovery code, such as the code to close I/O streams.

  2. Question: What exception types can be caught by the following handler?
    catch (Exception e) {

}
    What is wrong with using this type of exception handler?

    Answer: This handler catches exceptions of type Exception; therefore, it catches any exception. This can be a poor implementation because you are losing valuable information about the type of exception being thrown and making your code less efficient. As a result, your program may be forced to determine the type of exception before it can decide on the best recovery strategy.

  3. Question: Is there anything wrong with this exception handler as written? Will this code compile?
    try {

} catch (Exception e) {

} catch (ArithmeticException a) {

}
    Answer: This first handler catches exceptions of type Exception; therefore, it catches any exception, including ArithmeticException. The second handler could never be reached. This code will not compile.

  4. Question: Match each situation in the first list with an item in the second list.
    1. int[] A;
      A[0] = 0;
    2. The JVM starts running your program, but the JVM can't find the Java platform classes. (The Java platform classes reside in classes.zip or rt.jar.)
    3. A program is reading a stream and reaches the end of stream marker.
    4. Before closing the stream and after reaching the end of stream marker, a program tries to read the stream again.

    1. __error
    2. __checked exception
    3. __compile error
    4. __no exception

    Answer:

    1. 3 (compile error). The array is not initialized and will not compile.
    2. 1 (error).
    3. 4 (no exception). When you read a stream, you expect there to be an end of stream marker. You should use exceptions to catch unexpected behavior in your program.
    4. 2 (checked exception).

Exercises

  1. Exercise: Add a readList method to ListOfNumbers.java. This method should read in int values from a file, print each value, and append them to the end of the vector. You should catch all appropriate errors. You will also need a text file containing numbers to read in.

    Answer: See ListOfNumbers2.java.

  2. Exercise: Modify the following cat method so that it will compile:
    public static void cat(File file) {
    RandomAccessFile input = null;
    String line = null;

    try {
        input = new RandomAccessFile(file, "r");
        while ((line = input.readLine()) != null) {
            System.out.println(line);
        }
        return;
    } finally {
        if (input != null) {
            input.close();
        }
    }
}

    Answer: The code to catch exceptions is shown in red:

    public static void cat(File file) {
    RandomAccessFile input = null;
    String line = null;

    try {
        input = new RandomAccessFile(file, "r");
        while ((line = input.readLine()) != null) {
            System.out.println(line);
        }
        return;
    } catch(FileNotFoundException fnf) {
        System.err.format("File: %s not found%n", file);
    } catch(IOException e) {
        System.err.println(e.toString());
    } finally {
        if (input != null) {
            try {
                input.close();
            } catch(IOException io) {
            }
        }
    }
}

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises


In Xanadu did Kubla Khan
A stately pleasure-dome decree:
Where Alph, the sacred river, ran
Through caverns measureless to man
Down to a sunless sea.


Answers to Questions and Exercises: Basic I/O (The Java™ Tutorials > Essential Classes > Basic I/O)

Trail: Essential Classes
Lesson: Basic I/O
Home Page > Essential Classes > Basic I/O
« Previous • TOC
Answers to Questions and Exercises: Basic I/O

Questions

Question 1. What class would you use to read a few pieces of data that are at known positions near the end of a large file?
Answer 1. RandomAccessFile.

Question 2.In a format call, what's the best way to indicate a new line?
Answer 2. Use the %n conversion — the \n escape is not platform independent!

Question 3. How would you append data to the end of a file? Show the constructor for the class you would use and explain your answer.
Answer 3. Here's a quick answer: Use the FileWriter and BufferedWriter classes to append data to the end of the text file. Here is the FileWriter constructor, you pass in true to write to the file in append mode:

FileWriter writer = new FileWriter (String filename, boolean append);
An alternate answer is to use RandomAccessFile and skip to the end of the file and start writing:

...
RandomAccessFile file = new RandomAccessFile(datafile, "rw");
file.skipBytes((int)file.length()); //skip to the end of the file
file.writeBytes("Add this text to the end of datafile"); //write at the end of the file
file.close();
...

Exercises

Exercise 1. Implement a pair of classes, one Reader and one Writer, that count the number of times a particular character, such as e, is read or written. The character can be specified when the stream is created. Write a program to test your classes. You can use xanadu.txt as the input file.
Answer 1. See the following three files: CounterDemo.java, CountReader.java, and CountWriter.java.

Exercise 2. The file datafile begins with a single long that tells you the offset of a single int piece of data within the same file. Using the RandomAccessFile class, write a program that gets the int piece of data. What is the int data?
Answer 2. 123. See FileReader.java for the solution. If you're interested in seeing how the file was written, see FileWriter.java.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks  A Sun Developer Network Site
Previous page: Questions and Exercises: Basic I/O


In this chapter, you learned that regular expressions are a way to describe a set of strings based on common characteristics shared by each string in the set. The Java programming language supports regular expressions via the java.util.regex package, primarily through the Pattern, Matcher, and PatternSyntaxException classes.

  • A Pattern object is a compiled representation of a regular expression. The Pattern class provides no public constructors. To create a pattern, you must invoke one of its public static compile methods, both of which will return a Pattern object.

  • A Matcher object is the engine that interprets the pattern and performs match operations against an input string. Like the Pattern class, Matcher defines no public constructors. You obtain a Matcher object by invoking the public matcher method on a Pattern object.

  • A PatternSyntaxException object is an unchecked exception that indicates a syntax error in a regular expression pattern.

The most basic form of pattern matching supported by this API is the match of a string literal. You can also specify metacharacters — characters that carry special meaning — that will be interpreted by the matcher.

A character class is a set of characters enclosed within square brackets. It specifies the characters that will successfully match a single character from a given input string. You can define your own character classes, or use the predefined character classes included in the API.

Quantifiers allow you to specify the number of occurrences to match against. There are three different kinds of quantifiers: greedy, reluctant, and possessive.

  • Greedy quantifiers are considered "greedy" because they force the matcher to read in, or eat, the entire input string prior to attempting the first match. If the first match attempt (the entire input string) fails, the matcher backs off the input string by one character and tries again, repeating the process until a match is found or there are no more characters left to back off from. Depending on the quantifier used in the expression, the last thing it will try matching against is 1 or 0 characters.

  • Reluctant quantifiers take the opposite approach: they start at the beginning of the input string, then reluctantly eat one character at a time looking for a match. The last thing they try is the entire input string.

  • Possessive quantifiers always eat the entire input string, trying once (and only once) for a match. Unlike the greedy quantifiers, possessive quantifiers never back off, even if doing so would allow the overall match to succeed.

Capturing groups provide a way to treat multiple characters as a single unit. They are created by placing the characters to be grouped inside a set of parentheses, and are numbered by counting their opening parentheses from left to right. The section of the input string matching the capturing group(s) is saved in memory for later recall via a backreference. A backreference is specified in the regular expression as a backslash "\" followed by a digit indicating the number of the group to be recalled.

Boundary matchers make your matches more precise by specifying a match location within the input string. The regex API provides boundary matchers for the following locations: the beginning of a line, the end of a line, word boundaries, non-word boundaries, the beginning of the input, the end of the input, and the end of the previous match.

Finally, you explored the Pattern, Matcher, PatternSyntaxException classes in detail to learn about their additional functionality, including their method equivalents in java.lang.String.


Answers to Questions and Exercises: (The Java™ Tutorials > Essential Classes > Regular Expressions)

Trail: Essential Classes
Lesson: Regular Expressions
Home Page > Essential Classes > Regular Expressions
« Previous • TOC
Answers to Questions and Exercises:

Questions

  1. Question: What are the three public classes in the java.util.regex package? Describe the purpose of each.

    Answer:

    • Pattern instances are compiled representations of regular expressions.
    • Matcher instances are engines that interpret patterns and perform match operations against input strings.
    • PatternSyntaxException defines an unchecked exception indicating a syntax error in a regular expression.

  2. Question: Consider the string literal "foo". What is the start index? What is the end index? Explain what these numbers mean.

    Answer: Each character in the string resides in its own cell. Index positions point between cells. The string "foo" starts at index 0 and ends at index 3, even though the characters only occupy cells 0, 1, and 2.

  3. Question: What is the difference between an ordinary character and a metacharacter? Give an example of each.

    Answer: An ordinary character in a regular expression matches itself. A metacharacter is a special character that affects the way a pattern is matched. The letter A is an ordinary character. The punctuation mark . is a metacharacter that matches any single character.

  4. Question: How do you force a metacharacter to act like an ordinary character?

    Answer: There are two ways:

    • Precede the metacharacter with a backslash (\);
    • Enclose the metacharacter within the quote expressions, \Q (at the beginning) and \E (at the end).

  5. Question: What do you call a set of characters enclosed in square brackets? What is it for?

    Answer: This is a character class. It matches any single character that is in the class of characters specified by the expression between the brackets.

  6. Question: Here are three predefined character classes: \d, \s, and \w. Describe each one, and rewrite it using square brackets.

    Answer:
    \d | Matches any digit. | [0-9]
    \s | Matches any white space character. | [ \t\n-x0B\f\r]
    \w | Matches any word character. | [a-zA-Z_0-9]

  7. Question: For each of \d, \s, and \w, write two simple expressions that match the opposite set of characters.

    Answer:
    \d | \D | [^\d]
    \s | \S | [^\s]
    \w | \W | [^\w]

  8. Question: Consider the regular expression (dog){3}. Identify the two subexpressions. What string does the expression match?

    Answer: The expression consists of a capturing group, (dog), followed by a greedy quantifier {3}. It matches the string "dogdogdog".

Exercises

  1. Exercise: Use a backreference to write an expression that will match a person's name only if that person's first name and last name are the same.

    Solution: ([A-Z][a-zA-Z]*)\s\1

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Regular Expressions


The Extension Mechanism: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
The Extension Mechanism: End of Trail
You've reached the end of the "The Extension Mechanism" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

Writing Applets: This is the starting point for learning everything about writing applets.

JAR Files: Extensions must be bundled in JAR files.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Sealing Packages in Extensions


Trail: The Extension Mechanism: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: The Extension Mechanism: Table of Contents
Creating and Using Extensions
Installed Extensions
Download Extensions
Understanding Extension Class Loading
Making Extensions Secure
Setting Privileges for Extensions
Sealing Packages in Extensions
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Bonus: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
Bonus: End of Trail
You've reached the end of the "Bonus" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

Creating a GUI with JFC/Swing: Follow this trail to learn how to create user interfaces using the JFC/Swing API.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Preparation for Java Programmer Language Certification


Trail: Bonus: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: Bonus: Table of Contents
Generics
Introduction
Defining Simple Generics
Generics and Subtyping
Wildcards
Generic Methods
Interoperating with Legacy Code
The Fine Print
Class Literals as Runtime-Type Tokens
More Fun with Wildcards
Converting Legacy Code to Use Generics
Acknowledgements
Full-Screen Exclusive Mode API
Full-Screen Exclusive Mode
Display Mode
Passive vs. Active Rendering
Double Buffering and Page Flipping
BufferStrategy and BufferCapabilities
Examples
Preparation for Java Programmer Language Certification
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Getting Started: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
Getting Started: End of Trail
You've reached the end of the "Getting Started" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

Learning the Java Language: This trail is a gentle introduction to object-oriented concepts and how the Java language implements them.

Essential Java Classes: By taking this trail, you can find out about strings, exceptions, threads, and other Java features that are used in all kinds of Java programs.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Common Problems (and Their Solutions)


Trail: Getting Started: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: Getting Started: Table of Contents
The Java Technology Phenomenon
About the Java Technology
What Can Java Technology Do?
How Will Java Technology Change My Life?
The "Hello World!" Application
"Hello World!" for the NetBeans IDE
"Hello World!" for Microsoft Windows
"Hello World!" for Solaris OS and Linux
A Closer Look at the "Hello World!" Application
Questions and Exercises: Getting Started
Common Problems (and Their Solutions)
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Answers to Questions and Exercises: Getting Started (The Java™ Tutorials > Getting Started > )

Trail: Getting Started
Home Page > Getting Started
« Previous • TOC
Answers to Questions and Exercises: Getting Started

Questions

Question 1: When you compile a program written in the Java programming language, the compiler converts the human-readable source file into platform-independent code that a Java Virtual Machine can understand. What is this platform-independent code called?

Answer 1: Bytecode.

Question 2: Which of the following is not a valid comment:

a. /** comment */
b. /* comment */
c. /* comment
d. // comment
Answer 2: c is an invalid comment.

Question 3: What is the first thing you should check if you see the following error at runtime:

Exception in thread "main" java.lang.NoClassDefFoundError:
HelloWorldApp.java.
Answer 3: Check your classpath. Your class cannot be found.

Question 4: What is the correct signature of the main method?

Answer 4: The correct signature is public static void main(String[] args)

Question 5: When declaring the main method, which modifier must come first, public or static?

Answer 5: They can be in either order, but the convention is public static.

Question 6: What parameters does the main method define?

Answer 6: The main method defines a single parameter, usually named args, whose type is an array of String objects.

Exercises

Exercise 1: Change the HelloWorldApp.java program so that it displays Hola Mundo! instead of Hello World!.

Answer 1: This is the only line of code that must change:

System.out.println("Hola Mundo!"); //Display the string.

Exercise 2: You can find a slightly modified version of HelloWorldApp here: HelloWorldApp2.java
The program has an error. Fix the error so that the program successfully compiles and runs. What was the error?

Answer 2: Here's the error you get when you try to compile the program:

HelloWorldApp2.java:7: unclosed string literal
        System.out.println("Hello World!); //Display the string.
                           ^
HelloWorldApp2.java:7: ')' expected
        System.out.println("Hello World!); //Display the string.
                                                                ^
2 errors
To fix this mistake, you need to close the quotation marks around the string. Here is the correct line of code:
 System.out.println("Hello World!"); //Display the string.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Getting Started


Internationalization: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
Internationalization: End of Trail
You've reached the end of the "Internationalization" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

Essential Java Classes: Contains information about strings and properties, both of which are used when internationalizing programs.

Creating a GUI with JFC/Swing: For many programs, you will be internationalizing the text and graphics on GUI components, such as buttons. Also, Swing supports assistive technologies, thereby, allowing even more people to use your program.

Sound: Don't forget that sounds need to be internationalized as well.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Internationalized Resource Identifier


Trail: Internationalization: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: Internationalization: Table of Contents
Introduction
A Quick Example
Before Internationalization
After Internationalization
Running the Sample Program
Internationalizing the Sample Program
Checklist
Setting the Locale
Creating a Locale
Identifying Available Locales
The Scope of a Locale
Locale-Sensitive Services SPI
Isolating Locale-Specific Data
About the ResourceBundle Class
Preparing to Use a ResourceBundle
Backing a ResourceBundle with Properties Files
Using a ListResourceBundle
Customizing Resource Bundle Loading
Formatting
Numbers and Currencies
Using Predefined Formats
Customizing Formats
Dates and Times
Using Predefined Formats
Customizing Formats
Changing Date Format Symbols
Messages
Dealing with Compound Messages
Handling Plurals
Working with Text
Checking Character Properties
Comparing Strings
Performing Locale-Independent Comparisons
Customizing Collation Rules
Improving Collation Performance
Detecting Text Boundaries
About the BreakIterator Class
Character Boundaries
Word Boundaries
Sentence Boundaries
Line Boundaries
Converting Non-Unicode Text
Byte Encodings and Strings
Character and Byte Streams
Normalizer's API
Internationalization of Network Resources
Internationalized Domain Name
Internationalized Resource Identifier
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


You can design your own format patterns for dates and times from the list of symbols in the following table:
Symbol | Meaning | Presentation | Example
G | era designator | Text | AD
y | year | Number | 1996
M | month in year | Text & Number | July & 07
d | day in month | Number | 10
h | hour in am/pm (1-12) | Number | 12
H | hour in day (0-23) | Number | 0
m | minute in hour | Number | 30
s | second in minute | Number | 55
S | millisecond | Number | 978
E | day in week | Text | Tuesday
D | day in year | Number | 189
F | day of week in month | Number | 2 (2nd Wed in July)
w | week in year | Number | 27
W | week in month | Number | 2
a | am/pm marker | Text | PM
k | hour in day (1-24) | Number | 24
K | hour in am/pm (0-11) | Number | 0
z | time zone | Text | Pacific Standard Time
' escape for text Delimiter (none)
' single quote Literal '
Characters that are not letters are treated as quoted text. That is, they will appear in the formatted text even if they are not enclosed within single quotes.

The number of symbol letters you specify also determines the format. For example, if the "zz" pattern results in "PDT," then the "zzzz" pattern generates "Pacific Daylight Time." The following table summarizes these rules:

Presentation | Number of Symbols | Result
Text | 1 - 3 | abbreviated form, if one exists
Text | >= 4 | full form
Number | minimum number of digits is required | shorter numbers are padded with zeros (for a year, if the count of 'y' is 2, then the year is truncated to 2 digits)
Text & Number | 1 - 2 | text form
Text & Number | 3 | number form


You can design your own format patterns for numbers by following the rules specified by the following BNF diagram: pattern := subpattern{;subpattern} subpattern := {prefix}integer{.fraction}{suffix} prefix := '\\u0000'..'\\uFFFD' - specialCharacters suffix := '\\u0000'..'\\uFFFD' - specialCharacters integer := '#'* '0'* '0' fraction := '0'* '#'* The notation used in the preceding diagram is explained in the following table:
Notation Description
X*
 0 or more instances of X
(X | Y)
 either X or Y
X..Y
 any character from X up to Y, inclusive
S - T
 characters in S, except those in T
{X}
 X is optional
In the preceding BNF diagram, the first subpattern specifies the format for positive numbers. The second subpattern, which is optional, specifies the format for negative numbers.

Although not noted in the BNF diagram, a comma may appear within the integer portion.

Within the subpatterns, you specify formatting with special symbols. These symbols are described in the following table:

Symbol | Description
0 | a digit
# a digit, zero shows as absent
. placeholder for decimal separator
, placeholder for grouping separator
E | separates mantissa and exponent for exponential formats
; separates formats
- default negative prefix
% multiply by 100 and show as percentage
? multiply by 1000 and show as per mille
¤ currency sign; replaced by currency symbol; if doubled, replaced by international currency symbol; if present in a pattern, the monetary decimal separator is used instead of the decimal separator
X | any other characters can be used in the prefix or suffix
' used to quote special characters in a prefix or suffix


  • Prioritized List of Improvements
  • Highlights of User Feedback

Name of Reviewer: | Ray Ortigas
Current Trail Author(s): | Dale Green
Was the author contacted? | No If yes, Date:
Comments:

Prioritized List of Improvements/Corrections:

 Priority Scale:
(1-5)
1 = immediate attention required
3 = fix in next public push (2-3 weeks)
5 = when you get a chance...

  1. Update to Java 2 SDK 1.2. This includes covering Input Method Framework, Complex Output and Physical Fonts.

    priority (1-5): 4

  2. Recommendation2
    description
    priority (1-5):

  3. Recommendation3
    description
    priority (1-5):

  4. Recommendation4
    description
    priority (1-5):

Highlights of User Feedback:

  • Date: 18 May 1999

    1. Your example in /resbundle/propfile.html would be misleading for a german= ,=20 because "Platte" denotes only a hard disk, not a floppy disk (which is=20 "Diskette"). One of the rare moments, when the english language is not=20 precise enough.

    2. The sample time formats in /format/dateFormate.html given for the german=20 locale are wrong. According to german rules (Duden rule no. 233d) hours and=20 minutes are separated by a period instead of a colon.

    3. The german sentence used as an example in /format/messageFormat.html is=20 quite clumsy, though absolutely correct. Use "Wir haben am 13. April 1998 um=20 13.15 Uhr 7 Raumschiffe auf dem Planeten Mars entdeckt" instead, which will=20 even make your point clearer, since the order of the arguments changes.

    4. Checking character properties with the Character methods is all very fine= .=20 But please tell your colleagues at the collection trail about this=20 magnificent feature, so they can use it as well.

    5. First things last: There is one hint to be added to /intro/checklist.html= ,=20 namely to do l10n for german first. Not because the language is so beautiful=20 (she isn=B4t) or so easy (she=B4s rather lingual hell on earth), but she is=20 lengthy as a tape worm! If the size of menues, dialogs, reports etc. is=20 sufficient for german, it is sufficient for every language. As you can see,=20 we can=B4t even write short mails in english.

  • Date:
    User2's email

  • Date:
    User3's email

  • Date:
    User4's email


Get Announcements about The Java Tutorial

The Java Tutorial announcements list is a low traffic e-mail list that is maintained and used only by the Java Tutorial team. We send announcements to this list when the online Tutorial is updated, new books are published, and so on. Only Java Tutorial team members can post to the list.

Sun Microsystems respects your desire for privacy. Data collected for this mailing list will not be given, sold, or shared with organizations external to Sun. This information will be used only to add you to a low-traffic mailing list that informs you of Tutorial updates. If you have any questions, refer to Sun's Privacy Policy.

How to Subscribe

To subscribe, send mail to
java-tutorial-announce-request@eng.sun.com
and put the single word
subscribe
in the body of the message.

If the subscription is successful, you will receive two e-mail messages. One is a short message that indicates you have been added to the list. The other is a longer message that contains a welcome message and instructions for unsubscribing, should you ever choose to do so.

How to Unsubscribe

Send mail to
java-tutorial-announce-request@eng.sun.com
and put the single word
unsubscribe
in the body of the message.

If you unsubscribe successfully, you will receive a single e-mail message that indicates you've been removed from the list.


Thanks For Your Feedback! (The Java™ Tutorials)

Home Page
Thanks For Your Feedback!

Thanks for helping us improve the Java Tutorials. You may find the following links helpful.

The Java Tutorial FAQ answers some common questions.

Compiling and Running the Examples: FAQs may be helpful if you have trouble with the example programs.

Online Resources for Java Programmers contains many useful links.

Copyright 1995-2006 Sun Microsystems, Inc. All rights reserved.


Copyright: The Java SE Tutorials

Copyright © 1995-2008 Sun Microsystems, Inc. 4150 Network Circle, Santa Clara, California 95054, U.S.A. All rights reserved.

Sun, Sun Microsystems, the Sun logo, Java, Solaris, the Duke logo, JavaScript, JDK, JRE, JVM, JavaBeans, NetBeans, JDBC, Java 2D, and the Java Coffee Cup are trademarks or registered trademarks of Sun Microsystems, Inc. in the U.S. and other countries.

UNIX is a registered trademark in the U.S. and other countries, exclusively licensed through X/Open Company, Ltd.

This product is covered and controlled by U.S. Export Control laws and may be subject to the export or import laws in other countries. Nuclear, missile, chemical biological weapons or nuclear maritime end uses or end users, whether direct or indirect, are strictly prohibited. Export or reexport to countries subject to U.S. embargo or to entities identified on U.S. export exclusion lists, including, but not limited to, the denied persons and specially designated nationals lists is strictly prohibited.


Download The Java Tutorial

Download The Java Tutorials

NOTE As of March 2008, the Java SE Tutorials can be downloaded from the Sun Download Center. These historical download files will be available for some time but will be eventually EOLd.

To guarantee you're looking at the latest version, we invite you to read the tutorial at its permanent home: http://java.sun.com/docs/books/tutorial/.

If you download any part of the tutorial, feel free to make it available locally at your site. Please do not publicly mirror it to the Web! Check our FAQ if you want to know why.

Archives of Former Trails

Archive Compressed /
Uncompressed 		HTTP Download
Java SE Tutorial (updated to JDK 6)
(last updated August 1, 2007) 		34.0 MB / 55.4 MB tutorial.zip
Java SE Tutorial (Basics, Specialized and Swing (50%) updated to JDK 6)
(last updated November 10, 2006) 		26.2 MB / 49.6 MB tutorial_apr_30_07.zip
Java SE Tutorial (Basics and Specialized updated to JDK 6)
(last updated November 10, 2006) 		26.2 MB / 42 MB tutorial_nov_10_06.zip
Java SE Tutorial (The Basics updated to JDK 6)
(last updated Aug 4, 2006) 		18 MB / 32 MB tutorial_aug_4_06.zip
Java SE 5.0 (Tiger) Tutorial
(last updated Dec 23, 2005) 		15 MB / 25 MB tutorial-5.0.zip

If you have trouble downloading the tutorial: Please try again later. If you still can't download, ask your system administrator for help. You might also find some relevant information on the Download Help page.

If you have trouble unarchiving the tutorial: Make sure you have the latest software to unzip the tutorial. For example, PC users can use WinZip.


Errata for The Java Tutorial, 4th Edition

First Printing

  • CD problems on Linux:

    Some Linux systems automount the CD with a filesystem that forces all file names to lower case. This will break browser links to HTML files with mixed-case names, and also prevent the examples from compiling.

    If you have this problem, try manually mounting the CD with the UDF filesystem. To do this:

    • Become superuser.
    • Unmount the cd:
      umount cd_device_path
    • Remount the the cd using the UDF filesystem:
      mount -t udf cd_device_path cd_mount_point
  • Chapter 1: Getting Started, page 3:

    The source code inside figure 1.2 is missing a closing bracket to end the class definition.

    The missing bracket appears in bold below:

    class HelloWorldApp {
    public static void main(String[] args) {
        System.out.println("Hello World!");
    }
}

    Thanks to the anonymous reader who reported this!

  • Chapter 3: Language Basics, page 59:

    Typo fix: In the following sentence, the word "operand" (shown in bold) was mistakenly printed as "operator":

    "The equality and relational operators determine if one operand is greater than, less than, equal to, or not equal to another operand."

    Thanks to Dirk Henrici for reporting this!

  • Chapter 4: Classes and Objects, page 89:

    In the Bicycle class, the getspeed() method should be called getSpeed().

  • Chapter 4: Classes and Objects, page 97:

    In the example in the second paragraph, getX and getY should be changed to getX() and getY() so that the 3rdand 4th lines in the example read:

    circle.setX(circle.getX() + deltaX);
circle.setY(circle.getY() + deltaY);
    Thanks to Laslo Vukovitch for reporting this.
  • Chapter 4: Classes and Objects, page 107:

    In the SeeWhosFastest() method, the method should be called seeWhosFastest().

  • Chapter 4: Classes and Objects, page 114:

    The last word in the Note should be changed from "variables" to "methods" so that the sentence reads: "You can also refer to static methods with an object reference like instanceName.methodName(args) but this is discouraged because it does not make it clear that they are class methods."

  • Chapter 5: Interfaces and Inheritance, page 145:

    The code "if ( (obj1)isLargerThan(obj2)) ..." should be changed to "if ( (obj1)isLargerThan(obj2) ..." in three places by removing the extra parenthesis, ). The three lines should read:

    if ( (obj1)isLargerThan(obj2) > 0);
if ( (obj1)isLargerThan(obj2) < 0);
if ( (obj1)isLargerThan(obj2) == 0);
    Thanks to Clare Murnaghan for catching this.
  • Chapter 8: Numbers and Strings, page 200:

    In the title for Table 8.3, the file name should be TestFormat.java.

  • Chapter 8: Numbers and Strings, page 208:

    In the Random Numbers section:

    1. in the 4th line, change the sentence to read: "For example, to generate an integer between 0 and 9."
    2. change the code in line 6 to read int number = (int)(Math.random() * 10);
    3. in line 8, remove the entire sentence that begins "The compiler boxes...."

    Thanks to Serge Abrashevich for pointing this out.

  • Chapter 8: Numbers and Strings, page 223:

    In the picture, change substring(sep, dot) to substring(sep + 1, dot)

    Thanks to Tomec Czechowski for pointing this out.

  • Chapter 13: Regular Expressions, page 80:

    The second paragraph from the bottom reads:

    To see this effect more clearly, try removing the continue statement and recompiling. When you run the program again, the count will be wrong, saying that it found 44 p's instead of 9.
    In fact, when you run the program again, the count is 35.

    Thanks to Cesar Siqueira for being the first to report this error!

  • Chapter 17: Java Web Start, page 526: This is an older JNLP file and needs to be slightly modified to use release 6.

    The codebase line should read:

    codebase = "http://java.sun.com/docs/books/
            tutorialJWS/deployment/webstart/examples/"
href="Notepad.jnlp">
    and the j2se version should read:
    <j2se version="1.6+"
      href="http://java.sun.com/products/autodl/j2se"/>
    Thanks to Ian Davis for catching this!
  • Appendix A

    There is a clarification to the descriptive text above the keyword list.

    Previous text:

    "Here's a list of keywords in the Java language. These words are reserved — you cannot use any of these words as names in your programs. true, false, and null are not keywords but they are reserved words, so you cannot use them as names in your programs either."

    Clarified text:

    "Here's a list of keywords in the Java programming language. You cannot use any of the following as identifiers in your programs. The keywords const and goto are reserved, even though they are not currently used. true, false, and null might seem like keywords, but they are actually literals; you cannot use them as identifiers in your programs."


Running Tutorial Examples in NetBeans IDE (The Java™ Tutorials)

Home Page
Running Tutorial Examples in NetBeans IDE

The examples in the Swing Tutorial are also provided as NetBeans projects that are ready to be opened and run inside of NetBeans IDE, a free integrated development environment that you can use to simplify application development.

This page provides information on the following tasks:

  • Downloading, Installing, and Launching NetBeans IDE
  • Opening a Project for an Example
  • Compiling and Running a Project

Downloading, Installing, and Launching NetBeans IDE

The easiest way to get NetBeans IDE is to download the NetBeans IDE installer for your operating system from the NetBeans download page.

You can then run the installer and complete a short sequence of steps in the installation wizard to set up the IDE. You can find more details on the installation process from the installation instructions that are linked to from the download page.

You can then launch the IDE in one of the following ways:

  • On Microsoft Windows systems, you can use the NetBeans IDE item in the Start menu.
  • On Solaris OS and Linux systems, execute the IDE launcher script by navigating to the IDE's bin directory and typing ./netbeans.
  • On Mac OS X systems, click the NetBeans IDE application icon.

Opening a Project for an Example

Opening a project in NetBeans IDE consists of the following steps:

  • Download a tutorial example or the whole set of examples. Individual examples are available in the Example as NetBeans IDE Project column on the various example index pages (such as the components index page). You can download all of the examples as part of one of the bundles listed on the tutorial download page.
  • If you have downloaded an individual project, unzip the project on your system. If you have downloaded a zip file of the the whole tutorial or a zip file of all of the examples, unzip that file.
  • In NetBeans IDE, choose File > Open Project. In the file chooser, select the project and click Open Project Folder.

    NetBeans project folders are marked with the modified folder icon in the file chooser indicating a project icon.

Once opened, the project appears in the IDE's Projects window. Expand the nodes of the project to show the project's structure. The project includes the following main subnodes:

  • Source Packages. Contains nodes representing Java packages for your source files. Expand these nodes to access the .java source files for the project.
  • Libraries. Contains nodes representing the libraries on which the application depends. For the examples in the Swing Tutorial, just the JDK is listed here.

To open a file, double-click the file's node in the Projects window. When opened, a file is displayed in the Source Editor, to the right of the Projects window.

The Projects window represents the "logical" structure of the project, which does not correspond to the layout of the files on your system. This logical structure highlights the parts the project that you need to access most often. The Projects window does not display compiled .class files. If you want to see how the entire project is physically represented on disk, open the Files window.

Compiling and Running a Project

To compile your whole project, right-click the project's node in the Projects window and choose Build Project.

The Output window opens and displays output on the compilation progress.

If the build output concludes with the statement BUILD FAILED, you probably have a syntax error in your code. Errors are reported in the Output window as hyperlinked text. You double-click such a hyperlink to navigate to the source of an error. You can then fix the error and once again choose Build Project.

When you build the project, bytecode .class files are generated. You can see where the new files are generated by opening the Files window and expanding the folder for the project.

To run your project, right-click the project's node in the Projects window and choose Run Project.

Note: You can also use the Build Main Project and Run Main Project commands in the main menu. However, these commands work only work on the project that is currently designated as the "main" project. You can make a project the main project by right-clicking its node in the Projects window and choosing Set Main Project.

For more tips on using NetBeans IDE with the Java Tutorial, see Continuing the Tutorial with the NetBeans IDE.


The Java Tutorial FAQ

  • About the Tutorial
    • What is "the Java tutorial"?
    • Where can I get the tutorial?
    • How often is the online tutorial updated?
    • What do I need to know about the books before I buy one?
    • How much does the tutorial cost?
    • Some of the online tutorial isn't finished. What's up with that?

  • About Downloading the Tutorial
    • How do I download the tutorial?
    • May I mirror the tutorial publicly?
    • I'm having trouble unarchiving the tutorial. What should I do?

  • About Getting the Tutorial in Other Formats
    • Can I get a PostScript or PDF version of the tutorial to download?
    • Why isn't the tutorial available in PostScript or PDF?

  • Other Questions
    • Can you help me with my Java programming problem?
    • Where's the change history for the tutorial?

About the Tutorial

What is "the Java Tutorial"?

The Java Tutorial is a programmer's guide for the Java platform. It has two forms:

  1. The online version — This version is a hyperlinked, interactive set of HTML pages available on the World-Wide Web.
  2. The books — The first edition of The Java™ Tutorial was published in the summer of 1996. Since then, two additional books and several new editions of existing books have been published.
Where can I get the tutorial?

You can read the tutorial online. From the front page you can choose a trail or search the java.sun.com version of the tutorial. If you prefer to view the tutorial on your own system, you can download the tutorial free of charge.

If you prefer to read paper, you can buy the book.

How often is the online tutorial updated?

Sometimes we update as often as once a month; sometimes months pass between updates. Frequently we'll make minor fixes to individual pages without updating the whole tutorial.

What do I need to know about the books before I buy one?

The Swing Tutorial, 2nd edition, last updated for release 1.4, is available in bookstores. The Java Tutorial, 4th edition, updated to release 6.0, was published in October 2006.

How much does the tutorial cost?

You can view the online version free and you can download it for free.

For book prices, consult your preferred booksellers.

Some of the online tutorial isn't finished. What's up with that?

The online tutorial is a dynamic growing document. Read more about that in This Is a Work in Progress!.

About Downloading the Tutorial

How do I download the tutorial?

See Download the Tutorial for information. Unfortunately, we cannot send the tutorial to individuals via e-mail.

If for some reason, you cannot download the tutorial from the web, consider buying the book and using the version of the tutorial contained on the CD included with the book.

Note: If you download the tutorial, feel free to make it available locally at your site. Please do not publicly mirror it to the Web!. See the next question and answer to find out why.

May I mirror the tutorial publicly?

Our policy on distribution is that anyone is permitted have a copy of the online tutorial as long as it's visible only within their own institution (university, business, or whatever) and no one is profiting from the tutorial's distribution.

We've taken this strict position because the many tutorial mirrors mean that search engines generally don't find the most up-to-date version of the tutorial. Instead, search engines find mirror sites, which invariably fall behind. We end up getting e-mail about problems that have been corrected in newer versions of the tutorial. Or perhaps worse, we don't get e-mail and the reputation of the tutorial suffers. We allow local copies because we realize that browsing java.sun.com isn't always practical.

When you tell us about a mirror, we send the offender a friendly e-mail asking them to please move their copy of the tutorial to a place that isn't visible from the outside world.

I'm having trouble unarchiving the tutorial. What should I do?

Many readers can solve this problem by installing or updating software to unarchive compressed files (like Zip files). For example, on the Microsoft Windows platform, you can use WinZip to unarchive the Tutorial.

You can also download only examples, only the current Swing trail, or archived versions of tutorial trails that have been removed from or completely updated in the current online and downloaded versions of the tutorial.

About Getting the Tutorial in Other Formats

Can I get a PostScript or PDF version of the tutorial to download?

No. If you want a hard copy of the tutorial, you can buy or borrow the book. To find out why, read the next question and answer.

Why isn't the tutorial available in PostScript or PDF?

We used to offer a PostScript version of the tutorial, but it caused many more problems than it solved. There were problems with fonts, page size in Europe, older versions of PostScript, and so on. PDF format might solve some or all of those problems, but we also got a lot of complaints about the actual document: "it's just a PostScript dump of the HTML," "the links don't make sense on paper," and so on. PDF wouldn't solve those problems. As a result, we no longer provide PostScript, and we won't be providing it or PDF in the future.

Other Questions

Can you help me with my programming problem?

This question is actually a series of similar questions:

  • Here's my code. Can you help me debug it?
  • How do I set up my CLASSPATH? How do I set up the compiler? How do I install Windows 95? Where do I get the Java 2 Platform?
  • When I try to run one of the tutorial examples on a PC/Mac/Sun it doesn't work at all. Help me.
  • I want to write a <<insert description of some program here>>. Where do I begin?
  • I'm taking a class and I need help learning Java.
  • My boss told me to find out about Java. What is Java? Where do I get it?
  • What's a compiler?

Unfortunately we are not staffed to provide answers to these types of questions at this address. Your best bet is to go to the Sun Developer Network (SDN).

By the way, we automatically compile (and always run at least once) all of the examples in the tutorial. The examples work for us. If you are having problems with the examples, then you are probably having configuration problems.

Where's the change history for the tutorial?

Read a complete change history of the tutorial.


Inside the Java Tutorial

 INSIDE THE JAVATM TUTORIAL
by Steve Lipson

Walking Traveller It's hard to find a Java programmer anywhere who hasn't at least visited (and then likely become immersed in) The Java Tutorial -- the free, online introduction to the Java language available on the java.sun.com Web site.

On a typical week, the opening page of the Tutorial can receive more than 80,000 visits. The tutorial pages frequently rank as the most popular area on the java.sun.com Web site. And of course this readership doesn't even count the many thousands who are reading the tutorial from CD-ROM or using cached versions on their local networks.

More than Just a Basic ``Tutorial''

The Java Tutorial provides the first detailed introduction many people get to the Java language and Java technology. In addition to the basics, it delves into topics as diverse as security, internationalization, networking, graphical user interfaces, and JavaBeans.

Despite the name, authors Kathy Walrath and Mary Campione consider the Tutorial to be more of a programmer's guide than a formal tutorial.

"Unlike a tutorial, you don't have to go through it sequentially; it has scores of examples, and you can use it as a reference," says Walrath. "We changed the name from Programmer's Guide to Tutorial at our publisher's request, so that beginning programmers wouldn't be scared off by it."

How do people use it? There is no single approach, but typically users revisit the Tutorial regularly to check out new examples and walkthroughs or to get information on new releases and revisions. Like Java technology, the Tutorial is a work in progress that is constantly improving with age.

As one of the Tutorial's Amazon.com reviewers says, "Even the most experienced Java programmers I know continually learn new tricks and techniques from the Tutorial."

Designed for the Web

Designed first as an online document, the Tutorial's unique hypertext approach lets the reader follow "trails" to learn topics in greater depth; its "hands-on" approach has earned the Tutorial --and its authors-- a steady stream of accolades and praise. It is constantly being revised, updated, and expanded, providing programmers an easy means of keeping skills up to date.

The Language 'Trail'

Learning the Java Language: One of many "trails" users can explore in The Java Tutorial.

Wildly Popular

Perhaps surprisingly, a $39.75 printed version is quite a brisk seller in book stores even though the tutorial is available online for free. In part, the popularity of the printed book is attributable to its convenience and portability: As one satisfied programmer said when the book came out, "Now the Java Tutorial is even good in bed!"

The Java Tutorial book has been reprinted four times, and has just undergone another major revision. The book is more than 800 pages and includes a CD-ROM that contains the online tutorial and the JDK; you'll find it at any technical bookstore or can order the book online from booksellers such as Amazon.com.

Interestingly, the popularity of The Java Tutorial has steadily increased even though there are now many other outlets for Java training, such as university courses and commercial programming classes. In fact, several computer science courses and training sessions recommend The Java Tutorial (either in online or printed form) as a supplement to their course material.

Behind the Tutorial: A Great Team

Kathy Walrath and Mary Campione, the creators of the Tutorial, have successfully documented and thus have made a major contribution to defining and formalizing the Java platform. As the authors of the most popular Java technology instructional guide, they are in no small way responsible for building the Java community. These two extremely bright women have a definite sense of how to document and teach the platform.

The Team

The Team: Manager Lisa Friendly, authors Mary Campione and Kathy Walrath, and Alison Huml.

Kathy Walrath received her BS degree in computer science from UC Berkeley in 1986. A stint with NeXT Computers, Inc. gave her the opportunity to immerse herself in object oriented programming. It was at NeXT where Kathy also met her future co-author, Mary Campione. In 1993, opportunity came knocking and Kathy became employee #36 at Sun Microsystems' FirstPerson project. FirstPerson really represented the groundwork and basic staff for Javasoft, so Kathy has effectively been a member of the team and has been documenting the Java language since its embryonic stage.

As Kathy's responsibilities and (Tutorial) vision grew, it was clear she needed help. It was time to reconnect with Mary Campione.

Campione was glad to join. After receiving her BS in computer science at Cal Poly in 1985, and then having worked a variety of engineering jobs --including her time at NeXT -- she had been looking for something that would allow her to put her own experience to work. She had come to the realization, having co-authored two books (one on PostScipt), that she preferred the writing process over the engineering process. In 1995, she gladly accepted Kathy's offer to work at Sun. A stellar writing team was born.

As Java technology evolved, the Tutorial began to take on a life of its own. "Our managers gave us a lot of autonomy," says Campione. "That meant that we could use our own judgment about what needed to be covered and how to cover it."

Object-oriented programming page

The Java Tutorial covers everything from basic principles of object-oriented programming to the newest components of the Java platform.

Birth in Print

As the momentum began to build, book publishers wanted access to Walrath's and Campione's work. Numerous publishers approached Sun with the hopes of publishing the Tutorial, as well as a Java Series. Gosling and Lisa Friendly interviewed a number of different publishers and picked one: Addison Wesley.

Tutorial book cover The authors say it was Addison Wesley who best understood and shared the vision of the authors, acknowledging that the Tutorial had to remain online and free of charge, even when the books were published. In addition, the authors and the Series Editor felt it was most important that information would not be published in hard copy until the release it was based on had been finalized and shipped.

"Computer book publishers are typically of the mind that first is best", says Friendly. "We didn't want to be first, we just wanted to be right. When Addison Wesley agreed and let us decide what should and shouldn't be included, we knew we had our publisher." Addison Wesley made the right choice; the Java Tutorial has become something of a runaway best seller, as technical books go.

In 1996, Addison Wesley released the first printed version of The Java Tutorial (ISBN 0-201-63454-6).

Labor and Delivery Pains

Was it easy to translate the online Tutorial to book form? Campione and Walrath understood their task, but extenuating circumstances made their deadlines both difficult as well as somewhat comical.

As it happened, both women were pregnant while translating the Tutorial into book form. With their due dates two weeks apart -- sandwiching the due date for the book's manuscript -- things got a little dicey. The era produced not only a great book, but two adorable tutorial babies.

Looking back, both authors speak gratefully of the role of Randy Nelson, [Dean of Pixar University] who ultimately helped them get the manuscript to Addison Wesley on time. "Randy acted as the book's midwife," says Walrath. "He was really great."

It is likely that the book's innovative conversion from a web-centric, hyperlinked set of lesson trails to an equally well navigated, more linear, hard-copy orientation was among the first, and perhaps one of the few books ever published in this manner. The Tutorial works extremely well in both formats and its dual availability has been a success for its users, for the publisher, who broke new ground with such simultaneous publication, and for Sun and the authors, whose goal it was to teach developers around the world how to program in Java.

Ahead for the Tutorial

What's in store for Walrath and Campione? "We are really anxious to document the upcoming release, says Campione. "Alison Huml, who recently joined our group, has some great ideas for improving the online Tutorial. With her help we're going to revamp the whole user interface. We also expect to have a new search engine and to provide an updated page template. We're excited about it."

They have a lot to be excited about. The Tutorial has been instrumental in educating users in the ways of the Java language, and in turn has helped the Java developer community thrive (the Java developer community is expected to soon boast 700,000 programmers). They are excellent writers with an exceptional sense of what is most important in the learning process, and they have helped make Java technology accessible and understandable to everyone who reads the Java Tutorial.

Other Java Language Tutorials

In addition to the main tutorial on java.sun.com, Sun's Java Developer Connection Web site offers additional short courses on specific topics such as JDBC interfaces, JavaBeans, Swing, and the AWT. Membership in the Java Developer Connection is free.

The short courses are listed on the JDC's Online Training page.

This page was updated: 05-Jan-98


Glossary of Terms

For simplicity, "the JavaTM platform" is called Java in the following definitions.

A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
100% Pure Java(TM)
A Sun Microsystems initiative to guide developers in writing, certifying, and marketing applications written entirely in the Java(TM) programming language.
A

Abstract Window Toolkit (AWT)
A collection of graphical user interface (GUI) components that were implemented using native-platform versions of the components. These components provide that subset of functionality which is common to all native platforms. Largely supplanted by the Project Swing component set. See also Swing Set.

abstract
A Java(TM) programming language keyword used in a class definition to specify that a class is not to be instantiated, but rather inherited by other classes. An abstract class can have abstract methods that are not implemented in the abstract class, but in subclasses.

abstract class
A class that contains one or more abstract methods, and therefore can never be instantiated. Abstract classes are defined so that other classes can extend them and make them concrete by implementing the abstract methods.

abstract method
A method that has no implementation.

actual parameter list
The arguments specified in a particular method call. See also formal parameter list.

alpha value
A value that indicates the opacity of a pixel.

API
Application Programming Interface. The specification of how a programmer writing an application accesses the behavior and state of classes and objects.

appliances
Networked devices such as printers, Java(TM) technology-enabled terminals, and clients, that are managed using applications built using the Java Management API (JMAPI).

applet
A program written in the Java(TM) programming language to run within a web browser compatible with the Java platform, such as HotJava(TM) or Netscape Navigator(TM).

argument
A data item specified in a method call. An argument can be a literal value, a variable, or an expression.

array
A collection of data items, all of the same type, in which each item's position is uniquely designated by an integer.

ASCII
American Standard Code for Information Interchange. A standard assignment of 7-bit numeric codes to characters. See also Unicode.

atomic
Refers to an operation that is never interrupted or left in an incomplete state under any circumstance.

B

Bean
A reusable software component. Beans can be combined to create an application.

binary operator
An operator that has two arguments.

bit
The smallest unit of information in a computer, with a value of either 0 or 1.

bitwise operator
An operator that manipulates two values comparing each bit of one value to the corresponding bit of the other value.

block
In the Java(TM) programming language, any code between matching braces. Example: { x = 1; }.

boolean
Refers to an expression or variable that can have only a true or false value. The Java(TM) programming language provides the boolean type and the literal values true and false.

bounding box
For a Raster object, the smallest rectangle that completely encloses all the pixels that are not fully transparent.

break
A Java(TM) programming language keyword used to resume program execution at the statement immediately following the current statement. If followed by a label, the program resumes execution at the labeled statement.

byte
A sequence of eight bits. The Java(TM) programming language provides a corresponding byte type.

bytecode
Machine-independent code generated by the Java(TM) compiler and executed by the Java interpreter.

C

case
A Java(TM) programming language keyword that defines a group of statements to begin executing if a value specified matches the value defined by a preceding "switch" keyword.

casting
Explicit conversion from one data type to another.

catch
A Java(TM) programming language keyword used to declare a block of statements to be executed in the event that a Java exception, or run time error, occurs in a preceding "try" block.

char
A Java(TM) programming language keyword used to declare a variable of type character.

class
In the Java(TM) programming language, a type that defines the implementation of a particular kind of object. A class definition defines instance and class variables and methods, as well as specifying the interfaces the class implements and the immediate superclass of the class. If the superclass is not explicitly specified, the superclass will implicitly be Object.

class method
A method that is invoked without reference to a particular object. Class methods affect the class as a whole, not a particular instance of the class. Also called a static method. See also instance method.

classpath
A classpath is an environmental variable which tells the Java(TM) virtual machine* and Java technology-based applications (for example, the tools located in the JDK(TM) 1.1.X\bin directory) where to find the class libraries, including user-defined class libraries.

class variable
A data item associated with a particular class as a whole--not with particular instances of the class. Class variables are defined in class definitions. Also called a static field. See also instance variable.

client
In the client/server model of communcations, the client is a process that remotely accesses resources of a compute server, such as compute power and large memory capacity.

codebase
Works together with the code attribute in the <APPLET> tag to give a complete specification of where to find the main applet class file: code specifies the name of the file, and codebase specifies the URL of the directory containing the file.

comment
In a program, explanatory text that is ignored by the compiler. In programs written in the Java(TM) programming language, comments are delimited using // or /*...*/.

compilation unit
The smallest unit of source code that can be compiled. In the current implementation of the Java(TM) platform, the compilation unit is a file.

compiler
A program to translate source code into code to be executed by a computer. The Java(TM) compiler translates source code written in the Java programming language into bytecode for the Java virtual machine*. See also interpreter.

compositing
The process of superimposing one image on another to create a single image.

constructor
A pseudo-method that creates an object. In the Java(TM) programming language, constructors are instance methods with the same name as their class. Constructors are invoked using the new keyword.

const
This is a reserved Java(TM) programming language keyword. However, it is not used by current versions of the Java programming language.

continue
A Java(TM) programming language keyword used to resume program execution at the end of the current loop. If followed by a label, "continue" resumes execution where the label occurs.

core class
A public class (or interface) that is a standard member of the Java(TM) Platform. The intent is that the core classes for the Java platform, at minimum, are available on all operating systems where the Java platform runs. A program written entirely in the Java programming language relies only on core classes, meaning it can run anywhere. See also, 100% Pure Java(TM).

Core Packages
The required set of APIs in a Java platform edition which must be supported in any and all compatible implementations.

critical section
A segment of code in which a thread uses resources (such as certain instance variables) that can be used by other threads, but that must not be used by them at the same time.

D

declaration
A statement that establishes an identifier and associates attributes with it, without necessarily reserving its storage (for data) or providing the implementation (for methods). See also definition.

default
A Java(TM) programming language keyword optionally used after all "case" conditions in a "switch" statement. If all "case" conditions are not matched by the value of the "switch" variable, the "default" keyword will be executed.

definition
A declaration that reserves storage (for data) or provides implementation (for methods). See also declaration.

deprecation
Refers to a class, interface, constructor, method or field that is no longer recommended, and may cease to exist in a future version.

derived from
Class X is "derived from" class Y if class X extends class Y. See also subclass, superclass.

distributed
Running in more than one address space.

do
A Java(TM) programming language keyword used to declare a loop that will iterate a block of statements. The loop`s exit condition can be specified with the "while" keyword.

double
A Java(TM) programming language keyword used to define a variable of type double.

double precision
In the Java(TM) programming language specification, describes a floating point number that holds 64 bits of data. See also single precision.

E

else
A Java(TM) programming language keyword used to execute a block of statements in the case that the test condition with the "if" keyword evaluates to false.

EmbeddedJava(TM) Technology
The availability of Sun's Java 2 Platform, Micro Edition technology under a restrictive license agreement that allows a licensee to leverage certain Java technologies to create and deploy a closed-box application that exposes no APIs.

encapsulation
The localization of knowledge within a module. Because objects encapsulate data and implementation, the user of an object can view the object as a black box that provides services. Instance variables and methods can be added, deleted, or changed, but as long as the services provided by the object remain the same, code that uses the object can continue to use it without being rewritten. See also instance variable, instance method.

exception
An event during program execution that prevents the program from continuing normally; generally, an error. The Java(TM) programming language supports exceptions with the try, catch, and throw keywords. See also exception handler.

exception handler
A block of code that reacts to a specific type of exception. If the exception is for an error that the program can recover from, the program can resume executing after the exception handler has executed.

executable content
An application that runs from within an HTML file. See also applet.

extends
Class X extends class Y to add functionality, either by adding fields or methods to class Y, or by overriding methods of class Y. An interface extends another interface by adding methods. Class X is said to be a subclass of class Y. See also derived from.

F

FCS
First Customer Ship. The day in which a product is released/shipped to the customer.

field
A data member of a class. Unless specified otherwise, a field is not static.

final
A Java(TM) programming language keyword. You define an entity once and cannot change it or derive from it later. More specifically: a final class cannot be subclassed, a final method cannot be overridden and a final variable cannot change from its initialized value.

finally
A Java(TM) programming language keyword that executes a block of statements regardless of whether a Java Exception, or run time error, occurred in a block defined previously by the "try" keyword.

float
A Java(TM) programming language keyword used to define a floating point number variable.

for
A Java(TM) programming language keyword used to declare a loop that reiterates statements. The programmer can specify the statements to be executed, exit conditions, and initialization variables for the loop.

FTP
The basic Internet File Transfer Protocol. FTP, which is based on TCP/IP, enables the fetching and storing of files between hosts on the Internet. See also TCP/IP.

formal parameter list
The parameters specified in the definition of a particular method. See also actual parameter list.

G

garbage collection
The automatic detection and freeing of memory that is no longer in use. The Java(TM) runtime system performs garbage collection so that programmers never explicitly free objects.

goto
This is a reserved Java(TM) programming language keyword. However, it is not used by current versions of the Java programming language.

GUI
Graphical User Interface. Refers to the techniques involved in using graphics, along with a keyboard and a mouse, to provide an easy-to-use interface to some program.

H

hexadecimal
The numbering system that uses 16 as its base. The marks 0-9 and a-f (or equivalently A-F) represent the digits 0 through 15. In programs written in the Java(TM) programming language, hexadecimal numbers must be preceded with 0x. See also octal.

hierarchy
A classification of relationships in which each item except the top one (known as the root) is a specialized form of the item above it. Each item can have one or more items below it in the hierarchy. In the Java(TM) class hierarchy, the root is the Object class.

HotJava(TM) Browser
An easily customizable Web browser developed by Sun Microsystems, which is written in the Java(TM) programming language.

HTML
HyperText Markup Language. This is a file format, based on SGML, for hypertext documents on the Internet. It is very simple and allows for the embedding of images, sounds, video streams, form fields and simple text formatting. References to other objects are embedded using URLs.

HTTP
HyperText Transfer Protocol. The Internet protocol, based on TCP/IP, used to fetch hypertext objects from remote hosts. See also TCP/IP.

I

IDL
Interface Definition Language. APIs written in the Java(TM) programming language that provide standards-based interoperability and connectivity with CORBA (Common Object Request Broker Architecture).

identifier
The name of an item in a program written in the Java(TM) programming language.

if
A Java(TM) programming language keyword used to conduct a conditional test and execute a block of statements if the test evaluates to true.

implements
A Java(TM) programming language keyword optionally included in the class declaration to specify any interfaces that are implemented by the current class.

import
A Java(TM) programming language keyword used at the beginning of a source file that can specify classes or entire packages to be referred to later without including their package names in the reference.

inheritance
The concept of classes automatically containing the variables and methods defined in their supertypes. See also superclass, subclass.

instance
An object of a particular class. In programs written in the Java(TM) programming language, an instance of a class is created using the new operator followed by the class name.

instance method
Any method that is invoked with respect to an instance of a class. Also called simply a method. See also class method.

instance variable
Any item of data that is associated with a particular object. Each instance of a class has its own copy of the instance variables defined in the class. Also called a field. See also class variable.

instanceof
A two-argument Java(TM) programming language keyword that tests whether the run-time type of its first argument is assignment compatible with its second argument.

int
A Java(TM) programming language keyword used to define a variable of type integer.

interface
A Java(TM) programming language keyword used to define a collection of method definitions and constant values. It can later be implemented by classes that define this interface with the "implements" keyword.

Internet
An enormous network consisting of literally millions of hosts from many organizations and countries around the world. It is physically put together from many smaller networks and data travels by a common set of protocols.

IP
Internet Protocol. The basic protocol of the Internet. It enables the unreliable delivery of individual packets from one host to another. It makes no guarantees about whether or not the packet will be delivered, how long it will take, or if multiple packets will arrive in the order they were sent. Protocols built on top of this add the notions of connection and reliability. See also TCP/IP.

interpreter
A module that alternately decodes and executes every statement in some body of code. The Java(TM) interpreter decodes and executes bytecode for the Java virtual machine*. See also compiler, runtime system.

J

JAE
Java(TM) Application Environment. The source code release of the Java Development Kit (JDK(TM)) software.

JAR Files (.jar)
Java ARchive. A file format used for aggregating many files into one.

JAR file format
JAR (Java Archive) is a platform-independent file format that aggregates many files into one. Multiple applets written in the Java(TM) programming language, and their requisite components (.class files, images, sounds and other resource files) can be bundled in a JAR file and subsequently downloaded to a browser in a single HTTP transaction. It also supports file compression and digital signatures.

Java(TM)
Sun's trademark for a set of technologies for creating and safely running software programs in both stand-alone and networked environments.

Java Application Environment (JAE)
The source code release of the Java Development Kit (JDK(TM)) software.

JavaBeans(TM)
A portable, platform-independent reusable component model.

Java Blend(TM)
A product that enables developers to simplify database application development by mapping database records to objects in the Java(TM) programming language (Java objects) and Java objects to databases.

Java Card(TM) API
An ISO 7816-4 compliant application environment focused on smart cards.

JavaCheck(TM)
A tool for checking compliance of applications and applets to a specification.

JavaChip(TM)
Sun's processor, which executes bytecode for the Java(TM) virtual machine* natively. With a JavaChip processor, bytecode bypasses the virtual machine or just-in-time compiler stage to go directly to the processor.

Java(TM) Compatibility Kit (JCK)
A test suite, a set of tools, and other requirements used to certify a Java platform implementation conformant both to the applicable Java platform specifications and to Java Software reference implementations.

Java Database Connectivity (JDBC(TM))
An industry standard for database-independent connectivity between the Java(TM) platform and a wide range of databases. The JDBC(TM) provides a call-level API for SQL-based database access.

Java Developer Connection(SM)
A service designed for individual developers, providing online training, product discounts, feature articles, bug information, and early access capabilities.

Java Development Kit (JDK(TM))
A software development environment for writing applets and applications in the Java programming language.

Java(TM) Electronic Commerce Framework
A structured architecture for the development of electronic commerce applications in the Java(TM) programming language.

Java(TM) Enterprise API
This API makes it easy to create large-scale commercial and database applications that can share multimedia data with other applications within an organization or across the Internet. Four APIs have been designed within the Java(TM) Enterprise API family.

Java(TM) Foundation Classes (JFC)
An extension that adds graphical user interface class libraries to the Abstract Windowing Toolkit (AWT).

Java(TM) Interface Definition Language (IDL)
APIs written in the Java programming language that provide standards-based interoperability and connectivity with CORBA (Common Object Request Broker Architecture).

Java(TM) Media APIs
A set of APIs that support the integration of audio and video clips, 2D fonts, graphics, and images as well as 3D models and telephony.

Java(TM) Media Framework
The core framework supports clocks for synchronizing between different media (e.g., audio and video output). The standard extension framework allows users to do full audio and video streaming.

Java Naming and Directory Interface(TM) (JNDI)
A set of APIs that assists with the interfacing to multiple naming and directory services.

JavaOS(TM)
An Java(TM) technology-based operating system that is optimized to run on a variety of computing and consumer platforms. The JavaOS(TM) operating environment provides a runtime specifically tuned to run applications written in the Java programming language directly on hardware platforms without requiring a host operating system.

JavaPlan(TM)
An object-oriented design and diagramming tool written in the Java(TM) programming language.

Java(TM) Platform
Consists of a language for writing programs ("the Java(TM) programming language"); a set of APIs, class libraries, and other programs used in developing, compiling, and error-checking programs; and a virtual machine which loads and executes the class files.

In addition, the Java platform is subject to a set of compatibility requirements to ensure consistent and compatible implementations. Implementations that meet the compatibility requirements may qualify for Sun's targeted compatibility brands.

The Java(TM) 2 platform is the current generation of the Java platform.

Java(TM) Platform Editions
A Java platform "edition" is a definitive and agreed-upon version of the Java platform that provides the functionality needed over a broad market segment.

An edition is comprised of two kinds of API sets: (i) "core packages," which are essential to all implementations of a given platform edition, and (ii) "optional packages," which are available for a given platform edition and which may be supported in a compatible implementation.

There are 3 distinct editions of the Java Platform:

* Java 2 Platform, Enterprise Edition:
The edition of the Java platform that is targeted at enterprises to enable development, deployment, and management of multi-tier server-centric applications.

* Java 2 Platform, Standard Edition:
The edition of the Java platform that enables development, deployment, and management of cross-platform, general-purpose applications.

* Java 2 Platform, Micro Edition:
The edition of the Java platform that is targeted at small, standalone or connectable consumer and embedded devices to enable development, deployment, and management of applications that can scale from smart cards through mobile devices and set-top boxes to conventional computing devices.

Java(TM) Remote Method Invocation (RMI)
A distributed object model for Java(TM) program to Java program, in which the methods of remote objects written in the Java programming language can be invoked from other Java virtual machines*, possibly on different hosts.

Java(TM) Runtime Environment (JRE)
A subset of the Java Development Kit (JDK(TM)) for end-users and developers who want to redistribute the runtime environment alone. The Java runtime environment consists of the Java virtual machine*, the Java core classes, and supporting files.

JavaSafe(TM)
A tool for tracking and managing source file changes, written in the Java(TM) programming language.

JavaScript(TM)
A Web scripting language that is used in both browsers and Web servers. Like all scripting languages, it is used primarily to tie other components together or to accept user input.

Java Studio(TM)
The first program that allows you to easily create Java(TM) technology-based applications and applets without having to know the Java programming language.

Java(TM) Technologies
A set of technologies that enable the creation and safe running of software programs in both stand-alone and networked environments.

Java(TM) virtual machine (JVM)*
Sun's specification for or implementation of a software "execution engine" that safely and compatibly executes the byte codes in Java class files on a microprocessor (whether in a computer or in another electronic device).

* Java HotSpot(TM) performance engine - Sun's ultra-high-performance engine for implementing the Java runtime environment which features an adaptive compiler that dynamically optimizes the performance of running applications.

* KJava(TM) virtual machine - Sun's small-footprint, highly optimized foundation of a runtime environment within the Java 2 Platform, Micro Edition. Derived from the Java virtual machine, it is targeted at small connected devices and can scale from 30KB to approximately 128KB, depending on the target device's functionality.

* Java Card(TM) virtual machine - Sun's ultra-small-footprint, highly-optimized foundation of a runtime environment within the Java 2 Platform, Micro Edition. Derived from the Java virtual machine, it is targeted at smart cards and other severely memory-constrained devices and can run in devices with memory as small as 24K of ROM, 16K of EEPROM, and 512 bytes of RAM.

Java Web Server(TM)
The easy-to-use, extensible, easy-to-administer, secure, platform-independent solution to speed and simplify the deployment and management of your Internet and Intranet Web sites. It provides immediate productivity for robust, full-featured, Java technology-based server applications.

Java Workshop(TM)
A complete set of tools integrated into a single environment for managing programming with Java technology. The Java Workshop software uses a highly modular structure that enables you to easily plug new tools into the overall structure.

Java(TM) wallet
A user interface, built on the Java(TM) Electronic Commerce Framework, which allows for online purchases, value transfers, and administrative functions.

JavaSpaces(TM)
A technology that provides distributed persistence and data exchange mechanisms for code in the Java(TM) programming language.

JavaSoft(TM)
A former business unit of Sun Microsystems, Inc., currently known as Sun Microsystems, Inc., Java Software division.

JDBC(TM)
Java(TM) Database Connectivity. An industry standard for database-independent connectivity between the Java platform and a wide range of databases. The JDBC interface provides a call-level API for SQL-based database access.

JDK(TM)
Java(TM) Development Kit software. A software development environment for writing applets and application in the Java programming language.

JFC
Java(TM) Foundation Class. An extension that adds graphical user interface class libraries to the Abstract Windowing Toolkit (AWT).

Jini(TM) Technology
Sun's Jini technology includes a set of APIs that may be incorporated an optional package for any Java 2 platform edition. This set of APIs enables transparent networking of devices and services and eliminates the need for system or network administration intervention by a user.

The Jini technology is currently an optional package available on all Java 2 platform editions.

JMAPI
Java(TM) Management API. A collection of Java programming language classes and interfaces that allow developers to build system, network, and service management applications.

JNDI
Java Naming and Directory Interface(TM). A set of APIs that assist with the interfacing to multiple naming and directory services.

JPEG
Joint Photographic Experts Group. An image file compression standard established by this group. It achieves tremendous compression at the cost of introducing distortions into the image which are almost always imperceptible.

JRE
Java(TM) runtime environment. A subset of the Java Developer Kit for end-users and developers who want to redistribute the runtime environment. The Java runtime environment consists of the Java virtual machine*, the Java core classes, and supporting files.

Just-in-time (JIT) Compiler
A compiler that converts all of the bytecode into native machine code just as a Java(TM) program is run. This results in run-time speed improvements over code that is interpreted by a Java virtual machine*.

JVM
Java(TM) Virtual Machine*. The part of the Java Runtime Environment responsible for interpreting bytecodes.

K

keyword
The Java(TM) programming language sets aside words as keywords - these words are reserved by the language itself and therefore are not available as names for variables or methods.

L

lexical
Pertaining to how the characters in source code are translated into tokens that the compiler can understand.

linker
A module that builds an executable, complete program from component machine code modules. The Java(TM) linker creates a runnable program from compiled classes. See also compiler, interpreter, runtime system.

literal
The basic representation of any integer, floating point, or character value. For example, 3.0 is a double-precision floating point literal, and "a" is a character literal.

local variable
A data item known within a block, but inaccessible to code outside the block. For example, any variable defined within a method is a local variable and can't be used outside the method.

long
A Java(TM) programming language keyword used to define a variable of type long.

M

member
A field or method of a class. Unless specified otherwise, a member is not static.

method
A function defined in a class. See also instance method, class method. Unless specified otherwise, a method is not static.

Mosaic
A program that provides a simple GUI that enables easy access to the data stored on the Internet. These data may be simple files or hypertext documents. Mosaic was written by a team at NCSA.

multithreaded
Describes a program that is designed to have parts of its code execute concurrently. See also thread.

N

native
A Java(TM) programming language keyword that is used in method declarations to specify that the method is not implemented in the same Java source file, but rather in another language.

NCSA
National Center for Supercomputer Applications. See also Mosaic.

new
A Java(TM) programming language keyword used to create an instance of a class.

null
A Java(TM) programming language keyword used to specify an undefined value for reference variables.

O

object
The principal building blocks of object-oriented programs. Each object is a programming unit consisting of data (instance variables) and functionality (instance methods). See also class.

object-oriented design
A software design method that models the characteristics of abstract or real objects using classes and objects.

octal
The numbering system using 8 as its base, using the numerals 0-7 as its digits. In programs written in the Java(TM) programming language, octal numbers must be preceded with 0. See also hexadecimal.

Optional Packages
The set or sets of APIs in a Java platform edition which are available with and may be supported in a compatible implementation.

Over time, optional packages may become required in an edition as the marketplace requires them.

overloading
Using one identifier to refer to multiple items in the same scope. In the Java(TM) programming language, you can overload methods but not variables or operators.

overriding
Providing a different implementation of a method in a subclass of the class that originally defined the method.

P

package
A group of types. Packages are declared with the package keyword.

peer
In networking, any functional unit in the same layer as another entity.

PersonalJava(TM)
A Java runtime environment for network-connectable applications on personal consumer devices for home, office, and mobile use.

pixel
The smallest addressable picture element on a display screen or printed page.

POSIX
Portable Operating System for UNIX(TM). A standard that defines the language interface between the UNIX operating system and application programs through a minimal set of supported functions.

private
A Java(TM) programming language keyword used in a method or variable declaration. It signifies that the method or variable can only be accessed by other elements of its class.

process
A virtual address space containing one or more threads.

property
Characteristics of an object that users can set, such as the color of a window.

Profiles
A Profile is a collection of Java APIs that complements one or more Java 2 Platform Editions by adding domain-specific capabilities. Profiles may also include other defined Profiles. A profile implementation requires a Java 2 Platform Edition to create a complete development and deployment environment in a targeted vertical market. Each profile is subject to an associated set of compatibility requirements.

Profiles may be usable on one or more editions.

Some examples of profiles within the Java 2 Platform, Micro Edition are:

* PersonalJava(TM) - for non-PC products that need to display web-compatible Java-based content

* Java Card(TM) - for secure smart cards and other severely memory-constrained devices.

protected
A Java(TM) programming language keyword used in a method or variable declaration. It signifies that the method or variable can only be accessed by elements residing in its class, subclasses, or classes in the same package.

public
A Java(TM) programming language keyword used in a method or variable declaration. It signifies that the method or variable can be accessed by elements residing in other classes.

Q

R

raster
A line of pixels.

reference
A data element whose value is an address.

return
A Java(TM) programming language keyword used to finish the execution of a method. It can be followed by a value required by the method definition.

RFE
Request for Enhancement.

RMI
See Java Remote Method Invocation.

root
In a hierarchy of items, the one item from which all other items are descended. The root item has nothing above it in the hierarchy. See also hierarchy, class, package.

RPC
Remote Procedure Call. Executing what looks like a normal procedure call (or method invocation) by sending network packets to some remote host.

runtime system
The software environment in which programs compiled for the Java(TM) virtual machine* can run. The runtime system includes all the code necessary to load programs written in the Java programming language, dynamically link native methods, manage memory, handle exceptions, and an implementation of the Java virtual machine, which may be a Java interpreter.

S

Sandbox
Comprises a number of cooperating system components, ranging from security managers that execute as part of the application, to security measures designed into the Java(TM) virtual machine* and the language itself. The sandbox ensures that an untrusted, and possibly malicious, application cannot gain access to system resources.

scope
A characteristic of an identifier that determines where the identifier can be used. Most identifiers in the Java(TM) programming environment have either class or local scope. Instance and class variables and methods have class scope; they can be used outside the class and its subclasses only by prefixing them with an instance of the class or (for class variables and methods) with the class name. All other variables are declared within methods and have local scope; they can be used only within the enclosing block.

Secure Socket Layer (SSL)
A protocol that allows communication between a Web browser and a server to be encrypted for privacy.

servlet
A server-side program that gives Java(TM) technology-enabled servers additional functionality.

short
A Java(TM) programming language keyword used to define a variable of type short.

single precision
In the Java(TM) language specification, describes a floating point number with 32 bits of data. See also double precision.

SGML
Standardized Generalized Markup Language. An ISO/ANSI/ECMA standard that specifies a way to annotate text documents with information about types of sections of a document.

static
A Java(TM) programming language keyword used to define a variable as a class variable. Classes maintain one copy of class variables regardless of how many instances exist of that class. "static" can also be used to define a method as a class method. Class methods are invoked by the class instead of a specific instance, and can only operate on class variables.

static field
Another name for class variable.

static method
Another name for class method.

subarray
An array that is inside another array.

subclass
A class that is derived from a particular class, perhaps with one or more classes in between. See also superclass, supertype.

subtype
If type X extends or implements type Y, then X is a subtype of Y. See also supertype.

superclass
A class from which a particular class is derived, perhaps with one or more classes in between. See also subclass, subtype.

super
A Java(TM) programming language keyword used to access members of a class inherited by the class in which it appears.

supertype
The supertypes of a type are all the interfaces and classes that are extended or implemented by that type. See also subtype, superclass.

switch
A Java(TM) programming language keyword used to evaluate a variable that can later be matched with a value specified by the "case" keyword in order to execute a group of statements.

Swing Set
The code name for a collection of graphical user interface (GUI) components that runs uniformly on any native platform which supports the Java(TM) virtual machine*. Because they are written entirely in the Java programming language, these components may provide functionality above and beyond that provided by native-platform equivalents. (Contrast with AWT.)

synchronized
A keyword in the Java programming language that, when applied to a method or code block, guarantees that at most one thread at a time executes that code.

T

TCP/IP
Transmission Control Protocol based on IP. This is an Internet protocol that provides for the reliable delivery of streams of data from one host to another. See also IP.

Technology Compatibility Kit (TCK)
A test suite, a set of tools, and other requirements used to certify an implementation of a particular Sun technology conformant both to the applicable specifications and to Sun or Sun-designated reference implementations.

Thin Client
A system that runs a very light operating system with no local system administration and executes applications delivered over the network.

this
A Java(TM) programming language keyword that can be used to represent an instance of the class in which it appears. "this" can be used to access class variables and methods.

thread
The basic unit of program execution. A process can have several threads running concurrently, each performing a different job, such as waiting for events or performing a time-consuming job that the program doesn't need to complete before going on. When a thread has finished its job, the thread is suspended or destroyed. See also process.

throw
A Java(TM) programming language keyword that allows the user to throw an exception or any class that implements the "throwable" interface.

throws
A Java(TM) programming language keyword used in method declarations that specify which exceptions are not handled within the method but rather passed to the next higher level of the program.

transient
A keyword in the Java programming language that indicates that a field is not part of the serialized form of an object. When an object is serialized, the values of its transient fields are not included in the serial representation, while the values of its non-transient fields are included.

try
A Java(TM) programming language keyword that defines a block of statements that may throw a Java language exception. If an exception is thrown, an optional "catch" block can handle specific exceptions thrown within the "try" block. Also, an optional "finally" block will be executed regardless of whether an exception is thrown or not.

type
A class or interface.

U

Unicode
A 16-bit character set defined by ISO 10646. See also ASCII. All source code in the Java(TM) programming environment is written in Unicode.

URL
Uniform Resource Locator. A standard for writing a text reference to an arbitrary piece of data in the WWW. A URL looks like "protocol://host/localinfo" where protocol specifies a protocol to use to fetch the object (like HTTP or FTP), host specifies the Internet name of the host on which to find it, and localinfo is a string (often a file name) passed to the protocol handler on the remote host.

V

variable
An item of data named by an identifier. Each variable has a type, such as int or Object, and a scope. See also class variable, instance variable, local variable.

virtual machine
An abstract specification for a computing device that can be implemented in different ways, in software or hardware. You compile to the instruction set of a virtual machine much like you'd compile to the instruction set of a microprocessor. The Java(TM) virtual machine* consists of a bytecode instruction set, a set of registers, a stack, a garbage-collected heap, and an area for storing methods.

void
A Java(TM) programming language keyword used in method declarations to specify that the method does not return any value. "void" can also be used as a nonfunctional statement.

volatile
A Java(TM) programming language keyword used in variable declarations that specifies that the variable is modified asynchronously by concurrently running threads.

W

wait
A UNIX® command which will wait for all background processes to complete, and report their termination status.

while
A Java(TM) programming language keyword used to declare a loop that iterates a block of statements. The loop`s exit condition is specified as part of the while statement.

world readable files
Files on a file system that can be viewed (read) by any user. For example: files residing on web servers can only be viewed by Internet users if their permissions have been set to world readable.

wrapper
An object that encapsulates and delegates to another object to alter its interface or behavior in some way.

WWW
World Wide Web. The web of systems and the data in them that is the Internet. See also Internet.

X

Y

Z

*As used on this web site, the terms "Java virtual machine" or "JVM" mean a virtual machine for the Java platform.


What's new and What's Old? The History of the Tutorial

14 March 2008 —

This update features:

  • The Drag and Drop lesson has been completely rewritten and updated to JDK 6.
  • An updated Copyright page
  • A new License page that allows our users to modify tutorial content for limited non-commercial purposes.
  • We are moving our downloads to the Sun Download Center. You are required to accept the license in order to download the Java Tutorials.
  • We are retiring the feature where we name the releases and will be using dates from now on.
  • Besides the work listed here, there are many fixed broken links, typos and other miscellaneous errata.

Antediluvian Chili Pepper Day*, 1 August 2007 —

This push completes the tutorial update to JDK 6, with the exception of the Swing drag and drop lesson, which is marked as such. There are many updated pages, but the more notable changes are:

  • Performing Custom Painting, a new lesson.
  • How to Print Text, a new page.
  • Laying Out Components Within a Container, an updated lesson.
  • How to Use Icons, with an updated demo by reader Collin Fagan.

*OK, we made this up, or rather Collin did. :-)

National Honesty Day, 30 April 2007 —

This update focuses on the Swing tutorial — we have updated 80% of the material in the Swing tutorial to the JDK 6 release.

A significant part of this effort makes our examples easier than ever to use! The Swing examples are now packaged ready to use in NetBeans IDE. Check out the examples index for any of the Swing lessons (this link takes you to the Components lesson, there is a separate index for each Swing lesson) and you can download a zip file for any demo. Or you can visit the tutorial's download page and download a zip file containing all of the Swing examples. Check out the Running Tutorial Examples in NetBeans IDE page for more information on how to use the examples with NetBeans. Visit the NetBeans IDE download page to obtain release 5.5 of NetBeans IDE (it's free).

Some of our brand new and significantly updated sections include:

  • Learning Swing with NetBeans IDE, a new lesson!
  • The Synth Look and Feel
  • How to Integrate with the Desktop Class
  • How to Use Modality in Dialogs
  • How to Print Tables
  • How to Create a Splash Screen
  • How to Use the System Tray
  • How to Use Tables

Area Code Day, 10 November 2006 —

Check out the new Java Tutorials' Blog!

The Java™ Tutorial (4th edition) is now available in print. This update of the tutorial includes an Errata page for the first printing. Our publisher, Addison Wesley, informs us that several translations of this book are already in progress.

For this update, all of the specialized trails, except for Reflection, have been updated to release 6. The newly updated sections include:

  • Internationalization
  • JavaBeans
  • JDBC Database Access
  • RMI
  • Security
  • Sound
  • 2D Graphics
Plus, there are two all-new specialized trails:
  • Java Naming and Directory Interface (JNDI)
  • Java Management Extensions (JMX)

Also, the update of the Swing trail to release 6 is in progress and includes these sections:

  • Swing Concurrency is a new lesson that replaces the old "How to Use Threads" section. It covers the new class javax.swing.SwingWorker.
  • How to Use Tabbed Panes
  • Modifying the Look and Feel is a new lesson that includes the previous How to Set the Look and Feel page. Note that this section is still in progress.
The new look and feel of the tutorial has been further refined. Many of you have sent us feedback and we have been listening. The TOC on the left-side of the page can now be toggled. See the "Hide the TOC" button in the banner at the top of the page.

Also, there is a new Compiling and Running the Examples FAQ available at the bottom of most every page in the tutorial.

National Watermelon Day, 3 August 2006 —

The core tutorial is now updated to release JDK 6. This is in preparation for a new printed edition of The Java™ Tutorial (4th edition) that you can pre-order on Amazon or through many other booksellers. This online update includes the following sections:

  • Getting Started (with a new NetBeans section)
  • Object-Oriented Programming Concepts
  • Language Basics
  • Classes and Objects
  • Interfaces and Inheritance
  • Numbers and Strings
  • Generics
  • Packages
  • Exceptions
  • Basic I/O
  • Concurrency
  • Regular Expressions
  • The Platform Environment
  • Swing, a new trail that shows the many capabilities of Swing and features a sophisticated PasswordStore demo by Swing engineer, Scott Violet (source included) Deployment
  • Preparation for Java Programming Language Certification
The following update is also complete, though not part of the published tutorial:
  • Custom Networking
  • The Extension Mechanism
All examples in the basic tutorial and in the Swing tutorial have been updated to compile against the 6.0 release. Applets and Java web start applications require 6.0 to run. (The one exception are the applets in the deployment/applet section that will run under 1.4 and 1.5.)

You may notice that some very old parts of the tutorial have been removed. The previous version of the tutorial is now available via download. See the download page.

Finally, the tutorial itself has gotten a facelift, with a new look and feel. Let us know what you think about these changes and please let us know if you find any problems. Send feedback via our feedback form.

Nutcracker Release, 23 December 2005 —

The Java Tutorial update to JDK 5.0 is now complete. This includes these sections of the tutorial:

  • Getting Started
  • Object-Oriented Programming Concepts
  • Language Basics
  • Objects Basics and Simple Data Objects
  • Classes and Inheritance
  • Interfaces and Packages
  • Handling Errors Using Exceptions
  • Threads: Doing Two or More Tasks at Once
  • Collections
  • I/O
  • Deployment, a new trail that includes:
    • Applets
    • Java Web Start
    • Packaging Programs in JAR Files
Other changes include:
  • Several of the very old, out-of-date sections have been archived and are now available via download. See the download page for a complete list of available bundles.
  • You'll notice that the old applet and JAR sections have been updated and moved to the new Deployment trail. You may notice redirects if you have absolute links to the old pages.
  • We fixed the broken search feature: it wasn't limiting its search to the tutorial. This is now working correctly.
  • Across the tutorial, 1.0 and 1.1 examples have been removed. The release 5 examples are located in "ex5" directories.
  • We have a new feedback form. It looks different, but your feedback goes to the same place. Although our workload prevents us from responding to each email, rest assured we do read it.
  • Finally, we fixed the usual broken links, typos, and other errata.
Dorothy's Birthday Release, 15 April 2005 —

The following sections have been updated to 5.0:

  • Language Basics
  • Classes and Inheritance
  • Object Basics and Simple Data Objects
  • Collections

The following sections were updated to 5.0 in our last release, but have since been updated to reflect reader or reviewer feedback:

  • Object-Oriented Programming Concepts
  • Interfaces and Packages
  • Threads: Doing Two or More Tasks At Once
  • Handling Errors with Exceptions
Other changes include:
  • At readers' request, we changed the Feedback Form link at the top of each window to bring up a new window so you don't lose the page you're giving feedback about.
  • We started adding ZIP files so you can easily download all the examples for a particular chapter.
  • We added 5.0 versions (including web start links) of the examples in two Swing lessons: Getting Started with Swing and Learning Swing by Example.
  • We moved several applets back to the pages where they're referred to. Please let us know how you feel about this. Another alternative for some of these that aren't truly integrated with their page is to make them web started applications.
  • We made many small changes — which you probably won't notice — to clean up our HTML, reduce code sample line length where necessary, and generally enable better generation of book files from the HTML files.
  • Finally, we fixed the usual broken links, typos, and other errata.
Anya's Birthday Release, 14 Feb 2005 —

The following sections have been updated to 5.0 (though most are still pending engineering review):

  • Object-Oriented Programming Concepts
  • Interfaces and Packages
  • Handling Errors Using Exceptions
  • Threads: Doing Two or More Tasks at Once
  • JAR Files
Other, minor changes that you might notice include:
  • In the chapters where the content hasn't yet been updated, we have updated some of the images. In some cases, this might lead to a mismatch between the text (or code) and the image.
  • We have modified the page headers and the copyright notices. This will cause each page to be updated, even if the content hasn't yet changed.
  • Our search page has been fixed. Thanks to those of you who reported that it was broken.
  • Finally, we fixed the usual broken links, typos, and other errata.
Swing Book Release #2, 11 March 2004 —
  • Added an information page for our just-published book, The JFC Swing Tutorial, Second Edition. It includes pointers to other pages describing and book and CD contents, as well as errata.
  • Added questions and exercises, along with answers, to the Swing trail. These reflect the Questions and Exercises section at the end of every non-reference chapter in the new book.
  • Updated the table sorting example to use a much more recent, functional, and robust version of TableSorter.
  • The usual miscellaneous fixes.
Swing Book Release, 20 February 2004 —
  • Updated the first two lessons of the Swing trail to 1.4 (with notes about what's expected in 1.5): Getting Started with Swing and Learning Swing by Example.
  • Throughout the tutorial, made the usual fixes to broken links, typos, and other errata.
Maya's Birthday Release, 3 November 03 —
  • With the exception of the first two lessons, the Swing trail has now been updated to 1.4 (with notes about what's expected in 1.5) and reflects what will be published in the upcoming book. We'll note the biggest changes here, but with so many changes, we can't mention them all.
  • After consulting with the Swing engineers, we changed our thread safety recommendations and updated all but a few straggling 1.4 Swing examples to be thread safe. The newest recommendation is this: Build the GUI on the event-dispatching thread. See How to Use Threads for details.
  • Updated all pages in the Swing layout and events lessons to 1.4.
  • Updated the accessibility, actions, threads, and timer pages in the Using Other Swing Features lesson to 1.4.
  • In the Using Swing Components lesson, updated the applet, root pane, spinner, split pane, tabbed pane, table, tool bar, tool tip, tree, and all text component pages to 1.4. Created pages for separators and formatted text fields.
  • Completely rewrote the painting lesson. Instead of featuring only the API in the Graphics class, it now simply tells you what's special about painting Swing components and refers you to the 2D trail for details.
  • Throughout the tutorial, made the usual fixes to broken links, typos, and other errata.
Victoria Day (Canada), 19 May 03 —
  • Added two completely new and much-requested pages to the Swing part of the tutorial: How to Use Data Transfer (which covers drag and drop and cut/copy/paste) and How to Use the Focus Subsystem. Many thanks to Shannon Hickey and Scott Violet for their reviews of these rather long and technically complex sections.
  • Drastically changed the text and examples for How to Use SpringLayout. It's still unfinished, but should now be more useful. Many of the examples use a SpringUtilities class that makes it easy to build grids of cells, including columns of label-text field pairs.
  • Updated the following Swing component reference pages to 1.4: lists, panels, progress bars, menus, scroll panes, and sliders. Added a list of examples to the formatted text field section.
  • Updated a couple of other Swing reference pages to 1.4: borders, icons.
  • Updated applet tags throughout the tutorial to use APPLET instead of OBJECT/EMBED. This should make them execute successfully in recent versions of Java Plug-in. Changed a couple of applets to use getResourceAsStream instead of getResource to load their images — this is more efficient for applets using Java Plug-in.
  • Throughout the Swing examples, invoked setOpaque(true) on JPanels used as content panes, to account for the fact that panels are no longer opaque by default in every look and feel we distribute. (GTK+, added in 1.4.2, has transparent panels.) Where possible, changed examples that use p = new JPanel(); p.setLayout(l) to use p = new JPanel(l), to avoid the unnecessary creation of FlowLayout objects.
  • Rewrote and reorganized much of the early part of the Swing components lesson. This included adding two new pages, with some new material and some extracted from other pages: Using HTML in Swing Components and Using Models.
  • Miscellaneous fixes to broken links, typos, and the like.
Year of the Black Sheep (China), 3 February 03 —
  • Reorganized and updated Setting the Look and Feel. It even has information on the GTK and Windows XP look and feels, which will be introduced in 1.4.2.
  • Added source code for the 1.4 events demos. We had released the demos in runnable form soon after our last update, but without the source code.
  • Updated the following pages in the components lesson to reflect 1.4 (and make any other improvements we could): JComponent, button, combo box, color chooser, and frame.
  • Updated/added examples in the components lesson. New demo: FrameDemo2. Added PNG support to FileChooserDemo2. Changed ListDemo to not add a person if they already exist. Added a text input dialog to DialogDemo.
  • Fixed the Creating Classes answer page to actually contain answers.
  • Updated our standard headers and footers to be more usable by people with disabilities. These changes should be invisible to our other readers.
  • Miscellaneous fixes to broken links, typos, and the like.
Onion Market Day (Switzerland), 25 November 02 —
  • We changed our external links to bring up new, blank windows instead of named windows. Although this might result in an excess of windows, it should solve the problem of people losing the named windows.
  • We added many 1.4 examples to two of the Swing trail's lessons: Using Swing Components and Using Other Swing Features. These examples can be launched using JavaTM Web Start, and the source files now list what other files they need. The overall Swing example index now points to all versions of the examples for each lesson.
  • We added a page on key bindings to the Using Other Swing Features lesson. We also updated the action and accessibility pages.
  • In the Swing components lesson, we changed the order of the pages and updated all the pages up through and including buttons.
  • We're still in the process of updating the Creating a GUI with JFC/Swing trail to 1.4. You might notice some changes or notes about changes we plan to make.
  • We added a Java Web Start page to help people install and use that software.
  • Miscellaneous fixes to broken links and typos.
Robinson Crusoe's Birthday, 30 September 02 —
  • We added a new lesson! Regular Expressions covers the java.util.regex API introduced in the 1.4 release of the JavaTM 2 Platform Standard Edition. Regular expressions can be used as a tool to search, edit, or manipulate text or data. This package uses Perl-like syntax, but our lesson doesn't assume that you've had previous experience with regular expressions.
  • The Tutorial front page has completely changed, and the java.sun.com one now looks different from the downloaded one. The content of the two pages remains nearly identical.
  • We added a search box to the Tutorial front page.
  • We retired the Servlets trail, since it's out of date and other tutorials have updated servlet coverage. For links to the newer coverage and to a downloadable form of the old trail, see the old trailhead.
  • We added a page of printing tips: Improving Printing Performance. It includes strategies that you can use starting in both 1.3 and 1.4.1.
  • We added a file describing the license for our code examples. Unless otherwise licensed, all our code is available under this license.
  • Notice is hereby given: We plan to retire the Trail Map.
  • We're in the process of updating the Creating a GUI with JFC/Swing trail to 1.4. You might notice some changes or notes about changes we plan to make.
  • Lots of miscellaneous fixes to broken links and typos.
Magha Puja Day (Thailand), 4 March 02 —
  • The 1.4 version of the Java 2 Platform Standard Edition was released recently. We're in the process of updating the Creating a GUI with JFC/Swing trail to 1.4. The Full-Screen Exclusive Mode API covers a brand new API in the 1.4 release; programmers who write games or other graphic-intensive applications should read this trail.
  • Lots of miscellaneous fixes to broken links and typos.
Underdog Day (World), 19 December 01 — Maintenance Release
  • We removed our survey from the Web site. We want to thank everyone for their thoughtful responses. Your feedback will help us improve the Tutorial and plan for the future.
  • Lots of miscellaneous fixes to broken links and typos, including updates in the Creating a GUI with JFC/Swing trail.
Chulalongkorn Day (Thailand), 23 October 01 —
  • New survey! Please spend a few minutes filling out our survey. Your feedback will help us improve the Tutorial and plan for the future. We've also included some localization questions to help us learn what languages you'd like us to provide translations in.
  • Lots of miscellaneous fixes to broken links and typos.
Golden Week (Japan), 3 May 01 —
  • New lesson! User Interfaces that Swing: A Quick Start Guide. is a quick start guide to using Swing components to build user interfaces. It is built around several progressively complicated examples. (This lesson started life as a chapter in our latest book, The Java Tutorial, Third Edition.)
  • Another new lesson! For programmers who write games or other graphic-intensive apps, check out the new Full-Screen Exclusive Mode API lesson. This API will be included in the 1.4 release of the Java 2 Standard Edition.
  • Miscellaneous fixes to broken links and typos.
Glarius Festival (Switzerland), 1 April 01 —
  • Completely updated the I/O: Reading and Writing (but no 'rithmetic) lesson.
  • Reorganized the order of lessons in the Essential trail.
  • Miscellaneous fixes to broken links and typos.
Minor Update, 28 Feb 01 —
  • Miscellaneous fixes to broken links and typos.

Rolling Blackouts Release, 3 Feb 01 —

  • Added Questions and Exercises for all trails included in the new book, The Java Tutorial Third Edition.
  • Added new book pages to support the new book, The Java Tutorial Third Edition. (The TOC includes a handy set of links to all the answers for the Questions & Exercises.)
  • Updated the Getting Started trail. We updated the material for 1.3 and added Questions and Exercises.
  • Updated the Interfaces and Packages lesson. We updated the material for 1.3 and added Questions and Exercises.
  • Miscellaneous fixes to broken links and typos.

Edvard Munch's Birthday, 12 Dec 00 —

  • Updated the Learning the Java Language trail. We updated the material for 1.3 and added Questions and Exercises to the Language Basics section.
  • Updated the servlets trail to refer to the Tomcat 3.x and 4.0 implementations. These releases support the 2.2 and 2.3 versions of Java Servlet technology.
  • The Tomcat version of the Servlets Bookstore Example can now be downloaded as a zip file.
  • Miscellaneous fixes to broken links and typos.

Friday the 13th, 13 Oct 00 —

  • Added information to the IDL trail about the idlj compiler, which is part of the 1.3 release. Updated links to the idlj compiler, its documentation, and the OMG site.
  • Updated the servlets trail to refer to Java Servlet 2.2 API Docs.
  • Updated the Bingo example to fix some thread safety issues.
  • Updated the API links in most of the basic trails to point to the 1.3 versions (instead of 1.2).
  • Miscellaneous fixes to broken links and typos.

Tutorial Fifth Anniversary, 31 May 00 —

  • Added Werner van Mook's Mac adaptation of the instructions for writing and compiling your first programs: First Cup of Java (Mac OS).
  • Added questions and exercises to the end of the Getting Started trail and to the first three lessons in the Learning the Java Language trail.
  • Rewrote portions of the first lessons in the Learning the Java Language trail.
  • Miscellaneous fixes to broken links and typos.

Zeppo Marx's Birthday (1901), 25 February 00 —

  • Did reconstructive work on the Learning the Java Language trail. Lots of new examples added. Cleaned up.
  • Fixed a subtle bug in SwingWorker source code. See How to Use Threads in the Swing trail.
  • Adjusted JTable page, examples to reflect 1.3. See How to Use Tables in the Swing trail.
  • Miscellaneous fixes to broken links and typos.

Thanksgiving (USA), 24 November 99 —

  • Added a new lesson to the JavaBeans(tm) trail, Using the BeanContext API, that covers The Extensible Runtime Containment and Services Protocol.
  • Added some information about JTable in 1.3 in the Swing trail. Also, added a new 1.3 JTable example.
  • Began updating and rewriting the Learning the Java Language trail. This work includes adding exercises and questions to each section.
  • Added the glossary from the java.sun.com website and began linking terms to it.
  • Did a partial conversion to our new icon scheme for identifying the target of our links.
    • looks up a glossary term
    • links to a .java file
    • link to a page within the javadocs hosted at java.sun.com
    • links to a page outside of the tutorial
    • links to a page in a different lesson within the tutorial
    Intra-tutorial links (black) update the page in the current browser window, while extra-tutorial links (colored links) bring up a new browser window.

Vegetarian Day (World), 1 October 99 —

  • Removed the survey. Thank you for your responses.
  • Added a really big index that lists every content page in the tutorial in order.
  • Added a resources page that lists Java programming resources outside of the tutorial.
  • Added Your First Cup of Java (for UNIX).
  • Added feedback form. Please use this form to contact us instead of sending mail directly. It will help direct your mail to the right person.
  • Modified our tools to provide automatic next and previous links, automatic page titles, and automatic page headers and footers. This change should be largely unnoticeable to readers except that these page elements should contain fewer errors and inconsistencies.
  • Created a tool that automatically generated trail-level TOC pages. This change should be largely unnoticeable to readers except that these pages should contain fewer errors and inconsistencies.
  • Fixed various broken links, typographical, and other errors.
  • Put all of the images on the Swing Components Visual Index.
  • Updated API links to point to Java 2 SDK docs.
  • Thanks to our two delightful summer interns, Ray and Indra, we were able to do a lot of clean up including fixing omissions, making clarifications, adding examples, and so on.
  • We did a pass and cleaned up most of the pending issues. The only remaining pendings are in the BINGO lesson, which has not been completed, and in one of the book pages for the Second Edition. We hope, but do not promise, to clean up the remaining ones for the next tutorial update.

National Smile Week :), 3 August 99 —

  • Added the 2D applets to the list of applets page, for a total of 77 applets in the Tutorial. Also, provided Java Plug-in tags for running the 2D applets.
  • Added detailed instructions for compiling and running a Java program in Windows.
  • Posted a survey.
  • Created a tutorial announcements mailing list to which tutorial readers can subscribe.
  • Added common problems pages to some trails that didn't have them.
  • Clarified and fixed various errors reported by readers.

Fiesta de San Fermin (Spain), 7 July 99 —

  • Fixed most of the pending issues in the Swing trail. Fixed a few pending issues in other trails.
  • Fixed some problems with one example in the security trail.
  • Made some minor modifications to the page format and did some clean up on our tools. This has minor repercussions for API links.
  • Cleaned up the image directories and removed unused images. This reduced the size of the tutorial by about 1.5 Meg.
  • Added coverage of JSDK 2.1 in the servlets trail.
  • Modified our coverage of finalization in the Java language trail and in effected examples.
  • Fixed typos, broken links, a couple of broken applets, and other reader reported problems.
  • Updated the instructions for running the BINGO program.
  • Became a mirror for WinHelp version of tutorial.

Memorial Day (USA), 28 May 99 —

  • Announced the Swing book.
  • Due to overwhelming reader feedback, we changed our format again. We removed the left-hand border and modified the headers and footers to include a link to the search page.
  • Fixed typos and other errors in the Learning Java, Essential Classes, and Custom Networking trails in response to reader e-mail.

Lei Day (Hawaii) update, 5 May 99 — We made some changes to our new page format in resonse to reader feedback.

  • Because of reader feedback, we added a navigation area to the bottom of each page.
  • Implemented a max width of 460 for images to prevent large images from creating a page that is too wide.

Lei Day (Hawaii), 1 May 99 —

  • Modified our page format. It now includes search on every content page.
  • Created examples indexes for all examples in the Swing trail. If readers like it, we plan to do this for all trails.
  • Reviewed the code for all example programs in the Swing trail.
  • Did a final pass in preparation for converting from HTML to book format. This included everything from fixing typos to tweaking comments in source files to adding a few paragraphs of new information.
  • Added a second custom layout manager example: GraphPaperLayout.
  • Added new examples and content to the 2d trail.

World Culture Day, 12 March 99 — We marched through the Swing trail preparing for copyedit. Here's what we did:

  • Internally reviewed and edited all .html pages in the Swing trail in the first 7 lessons. In some cases, this amounted to a major rewrite.
  • Added *a lot* of material to the component how-to pages that covers aspects of the components that had previously been omitted. Typically, the additional material covers more advanced component features.
  • Reviewed example code, ran all examples, and modified as appropriate.
  • Researched and resolved many pending issues. (Some still remain.)
  • Performed "example audits" and updated the tables of examples.
  • Reviewed and updated API tables everywhere.
  • Fixed various bugs and clarity issues reported by readers.
  • Filled in "glue" pages.
  • Added information about common problems in many places.
  • Tied sections together better by adding links.
  • Made the layout and events sections similar to how-to pages by adding API and examples tables.

Joe's 40th Birthday, 21 Jan 99

  • Updated the drawing lesson to Swing.
  • Made various improvements to the Swing trail.
  • Some front page cleanup.

Winter Solstice, 21 Dec 98

  • Added Search Capability!
  • Added preliminary draft of Converting to Swing lesson.
  • Added links to resources and examples for Drag 'n Drop.
  • Some image clean up, which shrunk the tutorial by about .75 Megs.
  • Made various improvements to the Swing trail,
  • Fixed various broken link and typos.

Enlightenment of the Buddha (Japan), 8 Dec 98

  • Minor typo and broken link fixes.
  • Getting first two lessons in Swing trail ready for copyedit.
  • Removed all .class files from tutorial except those necessary for running applets. This shrank the tutorial by 1.5 Megs.

Day of the Artisans (Mexico), 4 Dec 98

  • Note: CD-ROM build. This is the version of the tutorial that appears on the CD-ROM for The Java Tutorial Continued.
  • Integrated all copyedits and other changes from the continued book into 5 trails: overview, internationalization, sound, 2D, and RMI.
  • Made lots of little improvements to the Swing trail, especially in swingOverview and swingStart. Reorganized material about text.
  • Updated programs to use Swing 1.1 (from Swing 1.0.3 and Swing 1.1 Beta 3) and JDK 1.2.

Aron's Birthday, 6 Nov 98

  • Substantially reorganized the Creating a GUI with JFC/Swing trail. The Swing-based User Interface trail replaces the old AWT-based User Interface trail, which is available only by download. We still have some work to do to complete the transition. Please bear with us during construction!
  • Miscellaneous fixes to typos, broken links, and program bugs.

Universal Children's Day, 5 Oct 98

  • Converted the examples and text in Laying Out Components within a Container to use Swing.
  • Several updates to the Using Swing Components lesson.
  • Converted many applets to use Java Plug-in.
  • Updated to JDK 1.1.7 and Swing 1.1 Beta 3.
  • Converted old UI trail to a downloadable archive.
  • Removed reference objects trail.
  • Miscellaneous fixes to typos, broken links, and program bugs.

Labor Day Release, 7 Sept 98

  • Added Overview of the JDK.
  • Added Java Sound trail.
  • Added Working with Java 2D Graphics trail.
  • Added JDBC Database Access trail.
  • Added Using Java RMI trail.
  • Reviewed and edited Programming with Java IDL trail.
  • Added new material and examples to the Using Swing Components lesson.

Laine's Birthday Release, An Update, 14 Aug 98

  • Added Programming with Java IDL trail.
  • Added Security in JDK 1.2 trail.
  • Reviewed and edited various trails and lesson.
  • Added new material and examples to the Using Swing Components lesson.
  • Fixed miscellaneous typos and broken links. Made minor improvements to text and examples all over the place.

Laine's Birthday Release, 3 Aug 98

  • Added Collections trail.
  • Added Servlets trail.
  • Added The Java Extensions Mechanism trail.
  • Added Reference Objects trail.
  • Added new material and examples to the Using Swing Components lesson. Completed technical reviews for many pages and integrated engineering feedback.
  • Reviewed and edited javabeans and jar trails.
  • Fixed miscellaneous typos and broken links. Made minor improvements to text and examples all over the place.

The Summer Solstice Release, 26 June 98

  • Added a lot of new material and examples to the Using Swing Components lesson.
  • Updated information about hashCode and equals.
  • Added a bios page that contains information about our contributing authors.
  • Reviewed and edited internationalization, reflection, and native trails.
  • Fixed miscellaneous typos and broken links. Improved some text and some examples.

Nettle Day (UK), 29 May 98

  • Added JAR trail.
  • Added 4 new topics to the internationalization trail: comparing strings, text boundaries, conversions, and a checklist for internationalizing existing programs.
  • Added demo programs to the date and number formatting lessons.
  • Reorganized JavaBeans trail.
  • Added a lot of new material and examples to the Using Swing Components lesson.
  • Reviewed native methods trail and made associated changes and fixes.
  • Fixed miscellaneous typos and broken links. Improved some text and some examples.

Arbor Day, 24 April 98

  • WooHoo! New front page! New Trail map!
  • New look for trail-level TOC.html files. Also, removed lesson-level TOC.html files. Instead we now provide a link to the appropriate place within the trail-level TOC.html files.
  • Continued to add new pages to the Using Swing Components lesson.
  • Added a new lesson to the internationalizaton trail covering formatting.
  • Added trail on reflection.
  • Added some information to the native methods trail for Mac programmers.
  • Fixed typos, broken links, and various other minor problems with content
  • Removed the old internationalization trail.
  • Removed old native methods trail...provide a downloadable archive instead.
  • Updated errata page for second edition of the book.

The Vernal Equinox, 20 March 98

  • Changed the background color to white.
  • Finished integrating figures from the new, second, edition of the book. Figures and images are now kept together at the top-level instead of sprinkled throughout the lesson directories.
  • Added book.html and related pages for the second editon of the book. Changed the page design of the book.html and related pages for the first edition to match the second edition.
  • Did a bunch of work behind the scenes on our tools and processes. This is the first update of the tutorial from our new workspace with our new makefiles and build process.
  • Because of our lovely new tools, we can now easily provide a downloadable archive of all of the examples in the book. See Download the Tutorial for the ftp links.
  • Fixed various typos and other minor problems with content.
  • Updated the Swing material relating to the JDK 1.2.
Saturnalia, 22 December 97
The long awaited update! — this is a major update of the tutorial. Almost every file has been touched in some way.

This release of the online tutorial corresponds with the release of the 2nd edition of The Java Tutorial book and is the version of the online tutorial that appears on the CD-ROM that accompanies that book.

The changes are in progress, but to a large extent we have integrated 1.1 information into the existing trails, lessons, and examples. This is in sharp contrast to the 1.1 notes that were littered throughout the previous version of the tutorial and were, admittedly, somewhat confusing.

Also, we are in the process of integrating copyedit and other changes made to the book version, into the online version. This has been completed thoroughly in some areas of the online tutorial, and spottily in other areas. We will continue with this process throughout the coming months.

New lessons in this tutorial that first appeared in print in the 2nd edition of The Java Tutorial book:

  • The Java Phenomenon
  • Migrating to 1.1
  • A Preview of Things to Come
New trails for this version of the tutorial that haven't yet made it to print:
  • Added a Putting It All Together trail that provides a large, real-world, client/server example and analyzes it.
  • Got a totally new JavaBeans Tutorial by Andy Quinn!
8 July 97
  • One of the goals of the tutorial is to document the latest and greatest from JavaSoft as it is released. To this end, we've added a lesson about Using Swing Components. The Swing release is an early release of part of the JFC. This information is only available from the Java Tutorial.
  • Added a trail, Java Security 1.1, covering the new 1.1 security APIs.
  • Updated the The JavaBeans(tm) Tutorial by Greg Voss.
  • Promoted Writing Global Programs to a trail. This trail is still in progress, but it contains new material including several excellent demos from Taligent.
  • Added information about the 1.1 release in our To 1.1 — And Beyond! trail.
  • Made the usual fixes to broken links, typos, and other errata.

14 May 97

We improved and added more 1.1 information in existing sections. We added more examples of and information about the various types of event listeners to Handling Events. We also fixed the AroundTheWorld applet used in Writing Global Programs.

28 April 97

We added a new trail, To 1.1 — And Beyond!, which is the headquarters for features added to the JDK after 1.0. Also, the Learning the Java Language and Essential Java Classes trails now have notes that point out material that is affected by 1.1. And finally, we reorganized our top-level files to make them more accessible.
3 March 97
Added a brand new trail introducing JavaBeans! This trail, JavaBeans Tutorial, written by Greg Voss, shows you the ins and outs of developing programs using the JavaBeans technology.
19 February 97
  • Our new "guest author" program debuts in this release of the tutorial with a completely new trail about writing native methods by Beth Stearns. Check it out: Using the Java Native Interface (JNI).
  • Merged copyediting changes from the book into the on-line version in these two trails: Getting Started and Writing Applets.
  • Updated Writing Global Programs to work with the FCS JDK 1.1 release.
  • The usual miscellaneous fixes.
24 December 96
Miscellaneous fixes. Also, added a new lesson describing new features of the JDK for Writing Global Programs.
6 June 96 — Released the Sixth DRAFT.
This draft is the version on which the book version is based. The book and online versions aren't exactly the same — for example, none of the copyeditor's changes have made it into the online tutorial yet. Also, the online tutorial's figures haven't been updated to be the same as those in the book. Notable content changes since the fifth draft include:
  • Finished the Common Problems pages.
  • Added information on the Macintosh JDK.
  • Added an applet anatomy section to Getting Started.
  • Improved the talk server example in the applet communication lesson.
28 Mar 96 — Released the Fifth DRAFT.
Many pages in this draft have been rewritten or expanded upon. (If you've sent us comments and don't see them reflected in this draft, please don't be insulted — we haven't finished incorporating reviewer comments.) Some of the notable changes include:
  • Revised Application Anatomy lesson and moved it to the Getting Started trail: The Anatomy of a Java Application. We plan to write an equivalent section for applets.
  • Did major rewrites of the following lessons in the Java trail: The Nuts and Bolts of the Java Language and Objects and Classes in Java.
  • Added new pages to the applet overview: Adding an Applet to an HTML Page and Summary.
  • Beefed up the applet threads pages: Threads in Applets.
  • Added a discussion of peers to the UI trail: Details of the Component Architecture.
  • Added material to the native methods trail, Integrating Native Methods into Java Programs, including passing data into and out of native methods and accessing Java objects.
  • Removed some trails: comparison to C/C++, troubleshooting, and tools. This information has been (or will be) incorporated into other trails/lessons.
4 Mar 96 — Released the Fourth DRAFT
Among the normal bug, typo and broken link fixes, this draft includes revisions to many of our old trails and lessons, plus this new material:
  • Added a new lesson to Integrating Native Methods into Java Programs trail.
  • Added new material to and/or wrote from scratch 4 lessons in the Writing Applets trail. Including: Creating an Applet User Interface, Communicating with Other Programs, Understanding Applet Capabilities and Restrictions, and Finishing an Applet. (The first three have since been reorganized into two trails: Taking Advantage of the Applet API and Practical Considerations when Writing Applets.
24 Feb 96 — Released the Third DRAFT
Among the normal bug, typo and broken link fixes, this draft includes revisions to many of our old trails and lessons, plus this new material:
  • Added a lot of new material to Creating an Applet User Interface.
  • Added new lessons to the Creating a User Interface trail. Including:
    • Laying Out Components within a Container Please note that 3 pages are still under construction.
    • Using Components, the GUI Building Blocks Each component now has a page describing how to use it.
    • Working with Graphics There's now information on how to draw primitive graphics (including text) and images, plus information on performing animation. The animation pages include information on how to eliminate flashing, using update() and double buffering. They also have information on using MediaTracker.
  • Added a new trail: Custom Networking
  • Added a new lesson, Input and Output Streams to the Essential Java Classes trail.
23 Jan 96 — Updated the Second DRAFT
  • Updated links to point to new FCS1.0 JDK release.
  • Fixed bugs where some applets and sources files were missing.
  • Miscellaneous fixes of typos, bugs, and broken links.
18 Jan 96 — Updated the Second DRAFT
  • Changed the Creating a User Interface trail to reflect the event changes introduced in Beta2. Specifically, keyboard event handlers now have to return false, unless they want the event to be dropped. The Conversion example program and the overview were affected.
  • Revised the structure of the tutorial to reflect what we're going to be able to finish by the time the book version is due to the printer.
  • Added a very preliminary lesson on Java's object features — Java Objects.
  • Fixed various typos, bugs and broken links.

12 Dec 95 — Updated the Second DRAFT

  • Made the few changes necessary to reflect Beta2 instead of Beta.
  • Fixed various typos, bugs and broken links.
  • Added a new lesson, Handling Errors using Exceptions, in the Essential Java Classes trail.

13 Nov 95 — Updated the Second DRAFT

  • Made the few changes necessary to reflect Beta instead of Pre-Beta.
  • Changed the name of this document from "The Java Programmer's Guide" to "The Java Language Tutorial: Object-Oriented Programming for the Internet." Why the long name? This document is going to be published as a book, and we wanted to make sure the title was as descriptive as possible, without requiring much prior knowledge of the potential buyer.
  • Added ALT text to our link graphics, so that people using non-graphical browsers can understand the information the graphic was conveying.
  • Added a new lesson, Laying Out Components Within a Container, in the Creating a User Interface trail.

2 Oct 95 — Released the Second DRAFT

  • Everything was updated to reflect the new APIs (except for The "run:" Protocol Handler and The "text/plain" Content Handler in the Getting Started trail).
  • We fixed many typos, clarified many obfuscations, fixed broken links and miscommunications.
  • We got a face-lift with new icons and a new page design.
  • And, we added these trails and lessons:
    • The Writing Applets trail has a new lesson: Overview of Applets which describes how applets work and how you use the Applet class to create an applet.
    • The new Creating a User Interface trail has two new lessons: Overview of UI Elements which introduces you to the objects that the Java development environment provides for building UIs, and Laying Out Components within a Container which tells you how to use each of the Components provided in the AWT.
    • We've also added the Integrating Native Methods into Java Programs trail that shows you how to integrate native methods into your Java programs.
    • And finally, we've added two new lessons: Threads of Control and Object-Oriented Programming Concepts.

18 May 95

Released the First DRAFT


This Is a Work in Progress!

This tutorial is a work in progress. At any time, it might be incomplete or buggy, and may contain bad links. We make interim versions of this tutorial available to you for two reasons:

  1. So you can learn from it -- some of the information in this tutorial is not documented anywhere else.
  2. So we can get feedback on this tutorial.
To help us with #2, please let us know what's confusing in these lessons, what seems unnecessary, and whether the lessons helped you at all. Write to us at . . .

WAIT! STOP!
Before you send us an e-mail . . . you should be aware that we do not provide technical support at this address! This address is provided so that you can provide us with feedback and let us know of any problems you may be having with the tutorial's content.

Here's where to turn for help with other problems:

  • If you have a Java programming or setup question, go to The Sun Developer Network (SDN). It's the best resource we know of, and it's free! You can download early access versions of new software, scan the known bugs in the Java SDK, search the large database of questions and answers, and much more.
  • Save yourself some time and check out our FAQ.

OK. Now, if you still want to send us e-mail, please use this form: Contact the Tutorial Team.


As defined below, the Licensed Work, including the content (specific Java Tutorial content downloaded in HTML files or graphic image files) and the example code  (.Java, .Class, .Jar, and .Project files) are governed by the following Java Tutorial Limited Non-Commercial License (the "Agreement").

In the alternative, the example code only is also available under the terms of the BSD License [Live link to BSD License].

JAVA TUTORIAL LIMITED NON-COMMERCIAL LICENSE

The Agreement is made between Sun Microsystems, Inc., a Delaware corporation with its address at 4150 Network Circle, Santa Clara, CA 95054 ("Sun"), and the individual, corporation, partnership or other legal entity receiving the Licensed Work ("Licensee") as of the date Licensee downloads the Licensed Work ("Effective Date"). The parties agree as follows:

1 DEFINITIONS.

1.1 "Intellectual Property Rights" means worldwide common law and statutory rights associated with: (i) patents and patent applications; (ii) works of authorship, including mask work rights, copyrights, and moral rights; (iii) protection of trade and industrial secrets and confidential information; (iv) other proprietary rights relating to intangible intellectual property (specifically excluding Sun Trademarks); and (v) divisions, continuations, renewals, reissuances, and extensions of the rights set forth above (as applicable).
1.2 "Licensed Work" means the content (specific Java Tutorial content downloaded in HTML files or graphic image files) and the example code  (.Java, .Class, .Jar, and .Project files)  as provided to Licensee by Sun under this Agreement.
1.3 "Licensors" means Sun licensors that have licensed third party code to Sun that is included in the Licensed Work.
1.4 "Permitted Use" means the following types of use: (i) Research and Instructional Use, whereby Licensee may use or modify the Licensed Work internally and non-commercially to provide instruction on the Java Programming language; and (ii) Individual Use, whereby Licensee may use or modify Licensed Work internally and non-commercially for personal and individual use.
1.5 "Sun Trademarks" means all names, marks, logos, designs, trade dress and other brand designations used by Sun.

2 LIMITED LICENSES.  Subject to and conditioned upon Licensee's compliance with the conditions and restrictions set forth in this Agreement, Sun grants to Licensee a personal, non-exclusive, non-transferable, royalty-free and limited license to view the Licensed Work and to use  the Licensed Work internally solely for the Permitted Use during the term of this Agreement.

3 RESTRICTIONS.
3.1 No license under this Agreement is granted to Licensee for any purpose not specifically set forth in Section 2 (Limited Licenses) of this Agreement.  Except as otherwise provided by law, Licensee is not authorized to transfer the Licensed Work  to any third party for use in commercial or development activities.
3.2 Licensee shall have no right to use the Licensed Work for commercial uses or in a production environment.
3.3 Licensee may copy and use the number of copies of Licensed Work  and make additional copies necessary for the Permitted Use, provided that Licensee reproduces all copyright and other notices appearing on or in the Licensed Work on any such copy.
3.4 Except as expressly provided in Section 2 ("Limited Licenses") of this Agreement, no right, title, or interest in or to the Licensed Work or any Sun Trademarks is granted under this Agreement. Sun retains all right, title and interest, including associated Intellectual Property Rights, in and to the Licensed Work, any Sun Trademarks, and any modifications, improvements or enhancements to the Licensed Work.
3.5 Portions of Licensed Work may be provided with notices and open source licenses from communities and third parties that govern the use of those portions, and any licenses granted hereunder do not alter any rights and obligations Licensee may have under such open source licenses, however, the disclaimer of warranty and limitation of liability provisions in this Agreement will apply to all Licensed Work.

4 NO SUPPORT.
Sun is under no obligation to support the Licensed Work or to provide Licensee with updates .

5TERM AND TERMINATION.
5.1 This Agreement will commence on the Effective Date and will continue so long as Licensee is not in default of any term hereunder, unless terminated earlier in accordance with this Section 5.
5.2 Either party may terminate this Agreement without cause upon ten (10) days' written notice to the other party. In addition, Sun may terminate this Agreement immediately with written notice if (i) the Licensed Work becomes, or in Sun's opinion is likely to become, the subject of a claim of infringement or misappropriation of any Intellectual Property Right; (ii) Licensee breaches any of its obligations under this Agreement; or  (iii) Licensee infringes or challenges the validity of any Sun Intellectual Property Rights.
5.3 Upon termination or expiration of this Agreement, Licensee will immediately cease using the  Licensed Work. Licensee will immediately destroy any and all  copies of the Licensed  Work and provide Sun a written statement by Licensee's authorized representative certifying that Licensee has complied with these obligations.
5.4 Rights and obligations under this Agreement that by their nature should survive will remain in effect after termination or expiration of this Agreement.

6 DISCLAIMER OF WARRANTY.
6.1 Licensee acknowledges that the Licensed Work is not designed or intended for use in the design, construction, operation or maintenance of any nuclear facility.
6.2 THE LICENSED WORK IS PROVIDED "AS IS" AND WITHOUT WARRANTY OF ANY KIND. ALL EXPRESS AND IMPLIED CONDITIONS, REPRESENTATIONS, AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF  MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A PARTICULAR PURPOSE, OR ANY WARRANTY OF NON-INFRINGEMENT, ARE DISCLAIMED, TO THE FULLEST EXTENT PERMITTED BY LAW.

7 LIMITATION OF LIABILITY.
7.1 Licensee acknowledges that the Licensed Work may be experimental. Licensee further acknowledges that the Licensed Work may have defects or deficiencies that cannot or will not be corrected by Sun. Licensee will indemnify and hold Sun harmless from any claims based on Licensee's use of the Licensed Work for any purpose. Neither Sun nor its Licensors are under any obligation to release a commercial version of the Licensed Work.
7.2 Licensee  acknowledges that  the Licensed Work may not have been approved by the United States Federal Communications Commission, any other governmental agency, or any test laboratory (for example without limitation, Underwriter's Laboratories, and TUV).
7.3 Neither Sun nor any of its licensors will be liable for any indirect, punitive, special, incidental or consequential damages in connection with or arising out of this Agreement (including loss of business, revenue, profits, goodwill, use, data, electronically transmitted communications or other economic advantage), however they arise, whether for breach of contract, breach of warranty or in tort, including negligence, and even if that party has previously been advised of the possibility of such damages AND WHETHER OR NOT SUCH DAMAGES ARE FORESEEABLE.  IN NO EVENT WILL SUN'S AGGREGATE LIABILITY TO LICENSEE FOR ALL CLAIMS UNDER THIS AGREEMENT, WHETHER IN CONTRACT, TORT (INCLUDING NEGLIGENCE), OR OTHERWISE, EXCEED THE AMOUNT PAID BY LICENSEE FOR THE TECHNOLOGY UNDER THIS AGREEMENT.
7.4 Liability for damages will be limited and excluded as set forth above even if any exclusive remedy provided in this  Agreement fails of its essential purpose.  Some states do not allow the exclusion of incidental or consequential damages, so some of the terms above may not be applicable to you.

8 U.S. GOVERNMENT RIGHTS.
The Licensed Work is a "commercial item," as that term is defined in 48 C.F.R. 2.101 (Oct. 1995), and may consist of "commercial computer software" (as that term is defined at 48 C.F.R. § 252.227-7014(a)(1)) and "commercial computer software documentation" as such terms are used in 48 C.F.R. 12.212 (Sept. 1995). Consistent with 48 C.F.R. 12.212 and 48 C.F.R. 227.7202-1 through 227.7202-4 (June 1995), all U.S. Government End Users acquire Licensed Work with only those rights set forth herein. This U.S. Government Rights clause is in lieu of, and supersedes, any other FAR, DFAR, or other clause or provision that addresses Government rights in computer software under this Agreement.

9 GENERAL.
9.1 All disputes will be governed by California law and controlling U.S. federal law.  The venue for litigation will be the appropriate courts located in Santa Clara County, California. The parties agree that the Federal District Court for the Northern District of California shall have exclusive jurisdiction over any dispute involving exclusively federal causes of action.  That court and the California state courts in Santa Clara County, California shall have exclusive jurisdiction over all other disputes. The parties hereby submit to the personal jurisdiction of those courts. Choice of law rules of any jurisdiction and the United Nations Convention on Contracts for the International Sale of Goods will not apply to the Agreement or any dispute arising out of or related to this Agreement.
9.2 Licensee agrees that the Licensed Work and technical data delivered under this Agreement are subject to U.S. export laws (including but not limited to the Export Administration Regulations ("EAR": 15  C.F.R. Parts 730-774)) and applicable trade laws of other countries.  Licensee agrees to strictly comply with all such laws and assumes responsibility to obtain licenses to export, re-export, or import as may be required. Unless authorized by United States export laws, Licensee agrees that (i) none of the Licensed Work or technical data or direct product therefrom is being or will be acquired for, shipment, transfer, or re-export, directly or indirectly, to: a) any country subject to U.S. Embargo or terrorist controls or b) a country and its nationals in Country Group D:1 as listed in Part 740 Supplement 1 of the EAR; (ii)  neither Licensee nor any party to whom the Licensed Work and technical data are transferred is not identified on any U.S. Government export exclusion lists; and (iii) the Licensed Work and technical data will not be used for nuclear, missile, chemical biological weaponry, or other weapons of mass destruction. These obligations shall survive expiration or termination of this Agreement.
9.3 Any express waiver or failure to exercise promptly any right under this Agreement will not create a continuing waiver or any expectation on non-enforcement.  To be enforceable, a waiver must be in writing and signed by an authorized representative of the waiving party.
9.4 It is understood and agreed that, notwithstanding any other provision of this Agreement, Licensee's breach of Sections 2.0 (Limited Licenses), 3.0 (Restrictions), and/or 5.0 (Term and Termination) of this Agreement will cause Sun irreparable damage for which recovery of money damages would be inadequate, and that Sun will therefore be entitled to seek injunctive relief to protect Sun's rights under this  Agreement, without posting bond or other security, in addition to any and all other remedies available under this Agreement, at law, and in equity.
9.5 Neither party may assign or otherwise transfer any of its rights or obligations under this Agreement (whether by operation of law or otherwise), without the prior written consent of the other party, except that Sun may assign this Agreement to an affiliated company without such consent.
9.6 If any term or provision of this Agreement is found to be invalid under any applicable statute or rule of law, such provision shall be enforced to the maximum extent permissible to effect the intent of the parties, and the remainder of this Agreement shall continue in full force and effect.
9.7 No modification to this Agreement will be binding, unless in writing and manually signed by an authorized representative of each party.
9.8 This Agreement, constitutes the parties' entire agreement relating to its subject matter. It cancels and supersedes all prior and contemporaneous oral and written communications, proposals, conditions, representations and warranties and prevails over any conflicting or additional terms contained in any quote, purchase order, acknowledgment, or other communication between the parties relating to its subject matter during its term, including but not limited to terms of any Binary Code Licenses, Supplemental Terms, or other standard licenses accompanying the Licensed Work.


Online Resources for Java Programmers

The Web offers many resources to help you use the Java platform. This section lists some that we use ourselves, or that we've heard good things about.

Caveat: A Web site that's good one year might stagnate the next, and it can be difficult to tell unless you know the site well. Please tell us if any of these Web sites is obsolete, or if you have a URL for an excellent resource not mentioned here.

We list three kinds of resources:

General Programming Resources
Web sites that provide information useful to most developers.
Specialized Programming Resources
Sources of more specialized programming information. Examples include assorted tutorials, The Swing Connection, and a Web site for Macintosh programmers. Don't forget that our Tutorial has many examples, and that you can search all the java.sun.com tutorials. Another source of resources is the Help section of java.sun.com.

General Programming Resources

The Java Developer ConnectionSM
http://developer.java.sun.com

Essential. Here are some of the things you can do at the JDC:

  • research bugs
  • vote for which bugs should be fixed first
  • view tutorials and book samples
  • download early access software
  • chat with developers and API architects
Code Conventions
http://java.sun.com/docs/codeconv/
Conventions that developers within Sun try to follow when writing programs in the Java programming language.
About.com Focus on Java
http://java.about.com
Has articles and links to many resources.
JavaWorld Magazine
http://www.javaworld.net
Has articles about current programming topics.
Java Boutique
http://javaboutique.internet.com
Has applets (some including source code), tutorials, book reviews, and more.
Java Developer's Journal
http://www.sys-con.com/java/
An online subset of a print magazine. Includes source code and selected articles.

Specialized Programming Resources
The J2EETM Tutorial
http://java.sun.com/j2ee/tutorial/index.html
A beginner's guide to developing enterprise applications on the Java 2 Platform, Enterprise Edition SDK.

Java 3DTM API Tutorial
http://java.sun.com/products/java-media/3D/collateral/

Has descriptions and examples of the most commonly used features in the Java 3D API.

XML Technologies
http://java.sun.com/xml/tutorial_intro.html

Introduces XML and tells you how to use the Java XML APIs.

The JNDI Tutorial
http://java.sun.com/products/jndi/tutorial/

Tells you how to use the JavaTM Naming and Directory Interface (JNDI) for associating names and attributes with objects.

JDC Tutorials
http://developer.java.sun.com/developer/onlineTraining/

Many tutorials, covering a wealth of topics. Subjects include JavaBeans, Enterprise JavaBeans, JDBC, and Java 2D.

The Swing Connection
http://java.sun.com/products/jfc/tsc/

The Swing engineering team's Web site. Has articles written both by Swing creators and by external programmers who use Swing.

The Swing/JFC FAQ
http://www.drye.com/java/faq.html

Unofficial answers to frequently asked questions about Swing.

Apple's Developer Site
http://developer.apple.com/java/

For programmers who use Macs.


Compiling and Running the Examples: FAQs (The Java™ Tutorials)

Home Page
Compiling and Running the Examples: FAQs
  • How do I compile and run the examples?
  • Why do I get an error message when I try to compile or run an example?
  • I already have the JRE. Why do I need the JDK?
  • I'm just not ready to upgrade to JDK 6. Can I get the old Tutorials?
  • Downloading the examples one at a time is a pain. Is there a single download containing all the examples?
  • Why doesn't Sun provide software for Mac OS X?.

How do I compile and run the examples? For instructions, refer to The "Hello World!" Application lesson in the Getting Started trail. This lesson includes links to download the Java SE Development Kit 6 (also known as JDK™ 6) for Windows, Linux, Solaris, and Mac OS X. There are also instructions and links for the NetBeans™ IDE, which runs on all the above platforms.

Why do I get an error message when I try to compile or run an example? Check out Common Problems (and Their Solutions).

I already have the JRE. Why do I need the JDK? The Java SE Runtime Environment, or JRE, allows you to run programs that have already been compiled and deployed. We hope you will use the Tutorials to expand your understanding of Java technology by modifying and extending the examples. To do this, you need the JDK.

I'm just not ready to upgrade to JDK 6. Can I get the old Tutorials? You can get the old tutorials (and a lot of other stuff) from the Tutorials download page. But note that a lot of material in the old Tutorials is very out of date, even for version 5.0 of the platform. You can actually use the new Tutorials with JDK 5.0; just recompile the examples. Most of the current examples will recompile without change; the rest will recompile with minor changes.

Downloading the examples one at a time is a pain. Is there a single download containing all the examples? That's also on the download page.

Why doesn't Sun provide software for Mac OS X?. Java platform software for Macintosh OS X is maintained by Apple Computer; the OS X version of JDK 5.0 is included with the OS. Apple also provides JDK 6 as Beta software; to download it, go to connect.apple.com. For more information about the Java platform on Mac OS X, go to developer.apple.com/java.

Complaints? Compliments? Suggestions? Give us your feedback.

Copyright 1995-2007 Sun Microsystems, Inc. All rights reserved.


Learning the Java Language: End of Trail (The Java™ Tutorials)

Home
Trail
Learning the Java Language: End of Trail
You've reached the end of the "Learning the Java Language" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

Essential Java Classes: Learn about the most-used classes in the JDK APIs including String, System, Thread and the classes in java.io.

Creating a GUI with JFC/Swing: Once you know how to create applications or applets, follow this trail to learn how to create their user interfaces.

Custom Networking and Security: If you're interested in writing applications or applets that use the network, follow this trail. You'll learn about URLs, sockets, datagrams, and security.

TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Solving Common Coding Problems


Trail: Learning the Java Language: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: Learning the Java Language: Table of Contents
Object-Oriented Programming Concepts
What Is an Object?
What Is a Class?
What Is Inheritance?
What Is an Interface?
What Is a Package?
Questions and Exercises: Object-Oriented Programming Concepts
Language Basics
Variables
Primitive Data Types
Arrays
Summary of Variables
Questions and Exercises: Variables
Operators
Assignment, Arithmetic, and Unary Operators
Equality, Relational, and Conditional Operators
Bitwise and Bit Shift Operators
Summary of Operators
Questions and Exercises: Operators
Expressions, Statements, and Blocks
Questions and Exercises: Expressions, Statements, and Blocks
Control Flow Statements
The if-then and if-then-else Statements
The switch Statement
The while and do-while Statements
The for Statement
Branching Statements
Summary of Control Flow Statements
Questions and Exercises: Control Flow Statements
Classes and Objects
Classes
Declaring Classes
Declaring Member Variables
Defining Methods
Providing Constructors for Your Classes
Passing Information to a Method or a Constructor
Objects
Creating Objects
Using Objects
More on Classes
Returning a Value from a Method
Using the this Keyword
Controlling Access to Members of a Class
Understanding Instance and Class Members
Initializing Fields
Summary of Creating and Using Classes and Objects
Questions and Exercises: Classes
Questions and Exercises: Objects
Nested Classes
Inner Class Example
Summary of Nested Classes
Questions and Exercises: Nested Classes
Enum Types
Questions and Exercises: Enum Types
Annotations
Questions and Exercises: Annotations
Interfaces and Inheritance
Interfaces
Defining an Interface
Implementing an Interface
Using an Interface as a Type
Rewriting Interfaces
Summary of Interfaces
Questions and Exercises: Interfaces
Inheritance
Overriding and Hiding Methods
Hiding Fields
Using the Keyword super
Object as a Superclass
Writing Final Classes and Methods
Abstract Methods and Classes
Summary of Inheritance
Questions and Exercises: Inheritance
Numbers and Strings
Numbers
The Numbers Classes
Formatting Numeric Print Output
Beyond Basic Arithmetic
Summary of Numbers
Questions and Exercises: Numbers
Characters
Strings
Converting Between Numbers and Strings
Manipulating Characters in a String
Comparing Strings and Portions of Strings
The StringBuilder Class
Summary of Characters and Strings
Questions and Exercises: Characters and Strings
Generics
Introduction
Generic Types
Generic Methods and Constructors
Bounded Type Parameters
Subtyping
Wildcards
Type Erasure
Summary of Generics
Questions and Exercises: Generics
Packages
Creating and Using Packages
Creating a Package
Naming a Package
Using Package Members
Managing Source and Class Files
Summary of Creating and Using Packages
Questions and Exercises: Creating and Using Packages
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Answers to Questions and Exercises: Object-Oriented Programming Concepts (The Java™ Tutorials > Learning the Java Language > Object-Oriented Programming Concepts)

Trail: Learning the Java Language
Lesson: Object-Oriented Programming Concepts
Home Page > Learning the Java Language > Object-Oriented Programming Concepts
« Previous • TOC
Answers to Questions and Exercises: Object-Oriented Programming Concepts

Answers to Questions

  1. Real-world objects contain state and behavior.

  2. A software object's state is stored in fields.

  3. A software object's behavior is exposed through methods.

  4. Hiding internal data from the outside world, and accessing it only through publicly exposed methods is known as data encapsulation.

  5. A blueprint for a software object is called a class.

  6. Common behavior can be defined in a superclass and inherited into a subclass using the extends keyword.

  7. A collection of methods with no implementation is called an interface.

  8. A namespace that organizes classes and interfaces by functionality is called a package.

  9. The term API stands for Application Programming Interface.

Answers to Exercises

  1. Your answers will vary depending on the real-world objects that you are modeling.

  2. Your answers will vary here as well, but the error message will specifically list the required methods that have not been implemented.
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Object-Oriented Programming Concepts


This section describes how to use the DecimalFormat class in the package. For general-purpose formatting use the Formatter API, introduced in Java SE 5. See for more information. You can use the DecimalFormat class to format decimal numbers into strings. This class allows you to control the display of leading and trailing zeros, prefixes and suffixes, grouping (thousands) separators, and the decimal separator. If you want to change formatting symbols, such as the decimal separator, you can use the DecimalFormatSymbols in conjunction with the DecimalFormat class. These classes offer a great deal of flexibility in the formatting of numbers, but they can make your code more complex.

The text that follows uses examples that demonstrate the DecimalFormat and DecimalFormatSymbols classes. The code examples in this material are from a sample program called .

Constructing Patterns

You specify the formatting properties of DecimalFormat with a pattern String. The pattern determines what the formatted number looks like. The example that follows creates a formatter by passing a pattern String to the DecimalFormat constructor. The format method accepts a double value as an argument and returns the formatted number in a String: DecimalFormat myFormatter = new DecimalFormat(pattern); String output = myFormatter.format(value); System.out.println(value + " " + pattern + " " + output); The output for the preceding lines of code is described in the following table. The value is the number, a double , that is to be formatted. The pattern is the String that specifies the formatting properties. The output, which is a String, represents the formatted number.

Output from DecimalFormatDemo Program
value | pattern | output | Explanation
123456.789 ###,###.### 123,456.789 The pound sign (#) denotes a digit, the comma is a placeholder for the grouping separator, and the period is a placeholder for the decimal separator.
123456.789 ###.## 123456.79 The value has three digits to the right of the decimal point, but the pattern has only two. The format method handles this by rounding up.
123.78 | 000000.000 | 000123.780 | The pattern specifies leading and trailing zeros, because the 0 character is used instead of the pound sign (#).
12345.67 $###,###.### $12,345.67 The first character in the pattern is the dollar sign ($). Note that it immediately precedes the leftmost digit in the formatted output.
12345.67 | \u00A5###,###.### | ¥12,345.67 | The pattern specifies the currency sign for Japanese yen (¥) with the Unicode value 00A5.

Altering the Formatting Symbols

You can use the class to change the symbols that appear in the formatted numbers produced by the format method. These symbols include the decimal separator, the grouping separator, the minus sign, and the percent sign, among others.

The next example demonstrates the DecimalFormatSymbols class by applying a strange format to a number. The unusual format is the result of the calls to the setDecimalSeparator, setGroupingSeparator, and setGroupingSize methods. DecimalFormatSymbols unusualSymbols = new DecimalFormatSymbols(currentLocale); unusualSymbols.setDecimalSeparator('|'); unusualSymbols.setGroupingSeparator('^'); String strange = "#,##0.###"; DecimalFormat weirdFormatter = new DecimalFormat(strange, unusualSymbols); weirdFormatter.setGroupingSize(4); String bizarre = weirdFormatter.format(12345.678); System.out.println(bizarre);

When run, this example prints the number in a bizarre format: 1^2345|678


Answers to Questions and Exercises: Characters and Strings (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Home Page > Learning the Java Language > Numbers and Strings
« Previous • TOC
Answers to Questions and Exercises: Characters and Strings

Questions

Question 1: What is the initial capacity of the following string builder?
StringBuilder sb = new StringBuilder("Able was I ere I saw Elba.");
Answer 1: It's the length of the initial string + 16: 26 + 16 = 42.

Question 2: Consider the following string:

String hannah = "Did Hannah see bees? Hannah did.";
Question 2a: What is the value displayed by the expression hannah.length()?
Answer 2a: 32.

Question 2b: What is the value returned by the method call hannah.charAt(12)?
Answer 2b: e.

Question 2c: Write an expression that refers to the letter b in the string referred to by hannah.
Answer 2c: hannah.charAt(15).

Question 3: How long is the string returned by the following expression? What is the string?
"Was it a car or a cat I saw?".substring(9, 12)
Answer 3: It's 3 characters in length: car. It does not include the space after car.

Question 4: In the following program, called ComputeResult, what is the value of result after each numbered line executes?

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class ComputeResult {
    public static void main(String[] args) {
        String original = "software";
        StringBuilder result = new StringBuilder("hi");
        int index = original.indexOf('a');

/*1*/   result.setCharAt(0, original.charAt(0));
/*2*/   result.setCharAt(1, original.charAt(original.length()-1));
/*3*/   result.insert(1, original.charAt(4));
/*4*/   result.append(original.substring(1,4));
/*5*/   result.insert(3, (original.substring(index, index+2) + " "));

        System.out.println(result);
    }
}
Answer 4:
  1. si
  2. se
  3. swe
  4. sweoft
  5. swear oft

Exercises

Exercise 1: Show two ways to concatenate the following two strings together to get the string "Hi, mom.":
String hi = "Hi, ";
String mom = "mom.";
Answer 1: hi.concat(mom) and hi + mom.

Exercise 2: Write a program that computes your initials from your full name and displays them.
Answer 2: ComputeInitials

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class ComputeInitials {
    public static void main(String[] args) {
        String myName = "Fred F. Flintstone";
        StringBuffer myInitials = new StringBuffer();
        int length = myName.length();

        for (int i = 0; i < length; i++) {
            if (Character.isUpperCase(myName.charAt(i))) {
                myInitials.append(myName.charAt(i));
            }
        }
        System.out.println("My initials are: " + myInitials);
    }
}

Exercise 3: An anagram is a word or a phrase made by transposing the letters of another word or phrase; for example, "parliament" is an anagram of "partial men," and "software" is an anagram of "swear oft." Write a program that figures out whether one string is an anagram of another string. The program should ignore white space and punctuation.
Answer 3: Anagram

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class Anagram {

    /**
     * Tests whether the passed-in strings are anagrams --
     * containing the exact same number of each letter.
     * Punctuation, case, and order don't matter.
     *
     * @return true if the strings are anagrams; otherwise, false
     */
    public static boolean areAnagrams(String string1,
                                      String string2) {

        String workingCopy1 = removeJunk(string1);
        String workingCopy2 = removeJunk(string2);

        workingCopy1 = workingCopy1.toLowerCase();
        workingCopy2 = workingCopy2.toLowerCase();

        workingCopy1 = sort(workingCopy1);
        workingCopy2 = sort(workingCopy2);

        return workingCopy1.equals(workingCopy2);
    }

    /**
     * Removes punctuation & spaces -- everything except
     * letters from the passed-in string.
     *
     * @return a stripped copy of the passed-in string
     */
    protected static String removeJunk(String string) {
        int i, len = string.length();
        StringBuilder dest = new StringBuilder(len);
          char c;

        for (i = (len - 1); i >= 0; i--) {
            c = string.charAt(i);
            if (Character.isLetter(c)) {
                dest.append(c);
            }
        }

        return dest.toString();
    }

    /**
     * Sorts the passed-in string.
     *
     * @return a sorted copy of the passed-in string
     */
    protected static String sort(String string) {
        char[] charArray = string.toCharArray();

        java.util.Arrays.sort(charArray);

        return new String(charArray);
    }

    public static void main(String[] args) {
        String string1 = "Cosmo and Laine:";
        String string2 = "Maid, clean soon!";

        System.out.println();
        System.out.println("Testing whether the following "
                         + "strings are anagrams:");
        System.out.println("    String 1: " + string1);
        System.out.println("    String 2: " + string2);
        System.out.println();

        if (areAnagrams(string1, string2)) {
            System.out.println("They ARE anagrams!");
        } else {
            System.out.println("They are NOT anagrams!");
        }
        System.out.println();
    }
}
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Characters and Strings


Answers to Questions and Exercises: Numbers (The Java™ Tutorials > Learning the Java Language > Numbers and Strings)

Trail: Learning the Java Language
Lesson: Numbers and Strings
Home Page > Learning the Java Language > Numbers and Strings
« Previous • TOC
Answers to Questions and Exercises: Numbers

Questions

Question 1: Use the API documentation to find the answers to the following questions:
Question 1a: What Integer method can you use to convert an int into a string that expresses the number in hexadecimal? For example, what method converts the integer 65 into the string "41"?
Answer 1a: toHexString

Question 1b: What Integer method would you use to convert a string expressed in base 5 into the equivalent int? For example, how would you convert the string "230" into the integer value 65? Show the code you would use to accomplish this task.
Answer 1b: valueOf. Here's how:

String base5String = "230";
int result = Integer.valueOf(base5String, 5);

Question 1c: What Double method can you use to detect whether a floating-point number has the special value Not a Number (NaN)?
Answer 1c: isNaN

Question 2: What is the value of the following expression, and why?
Integer.valueOf(1).equals(Long.valueOf(1))
Answer 2: False. The two objects (the Integer and the Long) have different types.

Exercises

Exercise 1: Change MaxVariablesDemo to show minimum values instead of maximum values. You can delete all code related to the variables aChar and aBoolean. What is the output?
Answer 1: See MinVariablesDemo. Here is the output:
The smallest byte value is -128
The smallest short value is -32768
The smallest integer value is -2147483648
The smallest long value is -9223372036854775808
The smallest float value is 1.4E-45
The smallest double value is 4.9E-324

Exercise 2: Create a program that reads an unspecified number of integer arguments from the command line and adds them together. For example, suppose that you enter the following:

       java Adder 1 3 2 10
The program should display 16 and then exit. The program should display an error message if the user enters only one argument. You can base your program on ValueOfDemo.
Answer 2: See Adder.

Exercise 3: Create a program that is similar to the previous one but has the following differences:

  • Instead of reading integer arguments, it reads floating-point arguments.
  • It displays the sum of the arguments, using exactly two digits to the right of the decimal point.
For example, suppose that you enter the following:
java FPAdder 1 1e2 3.0 4.754
The program would display 108.75. Depending on your locale, the decimal point might be a comma (,) instead of a period (.).
Answer 3: See FPAdder.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Numbers


Answers to Questions and Exercises: Generics (The Java™ Tutorials > Learning the Java Language > Generics)

Trail: Learning the Java Language
Lesson: Generics
Home Page > Learning the Java Language > Generics
« Previous • TOC
Answers to Questions and Exercises: Generics

Questions

Question 1. Consider the following classes:
public class AnimalHouse<E> {
    private E animal;
    public void setAnimal(E x) {
        animal = x;
    }
    public E getAnimal() {
        return animal;
    }
}

public class Animal{
}

public class Cat extends Animal {
}

public class Dog extends Animal {
}
For the following code snippets, identify whether the code:
  • fails to compile,
  • compiles with a warning,
  • generates an error at runtime, or
  • none of the above (compiles and runs without problem.)
Question 1a. AnimalHouse<Animal> house = new AnimalHouse<Cat>();
Answer 1a: 1. fails to compile
AnimalHouse<Cat> and AnimalHouse<Animal> are not compatible types, even though Cat is a subtype of Animal.

Question 1b. AnimalHouse<Cat> house = new AnimalHouse<Animal>();
Answer 1b: 1. fails to compile
Same as 1a: AnimalHouse<Cat> and AnimalHouse<Animal> are not compatible types, even though Cat is a subtype of Animal.

Question 1c. AnimalHouse<?> house = new AnimalHouse<Cat>();
             house.setAnimal(new Cat());
Answer 1c: 1. fails to compile
While the first line is acceptable — it is OK to define an instance of unknown type — the compiler doesn't know the type of animal stored in house so the setAnimal method cannot be used.

Question 1d. AnimalHouse house = new AnimalHouse();
             house.setAnimal(new Dog());
Answer 1d: 2. compiles with a warning
The compiler doesn't know what type house contains. It will accept the code, but warn that there might be a problem when setting the animal to an instance of Dog.

Using a generic type as a raw type might be a way to work around a particular compiler error, but you lose the type checking that generics provides, so it is not recommended.

Exercises

Exercise 1. Design a class that acts as a library for the following kinds of media: book, video, and newspaper. Provide one version of the class that uses generics and one that does not. Feel free to use any additional APIs for storing and retrieving the media.

Answer 1:

Non-Generic Version

import java.util.List;
import java.util.ArrayList;

public class Library {
    private List resources = new ArrayList();
    public void addMedia(Media x) {
        resources.add(x);
    }
    public Media retrieveLast() {
        int size = resources.size();
        if (size > 0) {
            return (Media)resources.get(size - 1);
        }
        return null;
    }
}

interface Media {
}

interface Book extends Media {
}

interface Video extends Media {
}

interface Newspaper extends Media {
}

Generic Version

import java.util.List;
import java.util.ArrayList;

public class Library<E extends Media> {
    private List<E> resources = new ArrayList<E>();
    public void addMedia(E x) {
        resources.add(x);
    }
    public E retrieveLast() {
        int size = resources.size();
        if (size > 0) {
            return resources.get(size - 1);
        }
        return null;
    }
}

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Generics


Answers to Questions and Exercises: Inheritance (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • TOC
Answers to Questions and Exercises: Inheritance

Questions

Question 1: Consider the following two classes:
public class ClassA {
    public void methodOne(int i) {
    }
    public void methodTwo(int i) {
    }
    public static void methodThree(int i) {
    }
    public static void methodFour(int i) {
    }
}

public class ClassB extends ClassA {
    public static void methodOne(int i) {
    }
    public void methodTwo(int i) {
    }
    public void methodThree(int i) {
    }
    public static void methodFour(int i) {
    }
}
Question 1a: Which method overrides a method in the superclass?
Answer 1a: methodTwo

Question 1b: Which method hides a method in the superclass?
Answer 1b: methodFour

Question 1c: What do the other methods do?
Answer 1c: They cause compile-time errors.

Question 2: Consider the Card, Deck, and DisplayDeck classes you wrote in the previous exercise. What Object methods should each of these classes override?
Answer 2: Card and Deck should override equals, hashCode, and toString.

Exercises

Exercise 1: Write the implementations for the methods that you answered in question 2.
Answer 1: See Card2.
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Inheritance


Answers to Questions and Exercises: Interfaces (The Java™ Tutorials > Learning the Java Language > Interfaces and Inheritance)

Trail: Learning the Java Language
Lesson: Interfaces and Inheritance
Home Page > Learning the Java Language > Interfaces and Inheritance
« Previous • TOC
Answers to Questions and Exercises: Interfaces

Questions

Question 1: What methods would a class that implements the java.lang.CharSequence interface have to implement?
Answer 1: charAt, length, subSequence, and toString.

Question 2: What is wrong with the following interface?

public interface SomethingIsWrong {
    void aMethod(int aValue) {
        System.out.println("Hi Mom");
    }
}
Answer 2: It has a method implementation in it. It should just have a declaration.

Question 3: Fix the interface in Question 2.
Answer 3:

public interface SomethingIsWrong {
    void aMethod(int aValue);
}

Question 4: Is the following interface valid?

public interface Marker {
}
Answer 4: Yes. Methods are not required. Empty interfaces can be used as types and to mark classes without requiring any particular method implementations. For an example of a useful empty interface, see java.io.Serializable.

Exercises

Exercise 1: Write a class that implements the CharSequence interface found in the java.lang package. Select one of the sentences from this book to use as the data. Write a small main method to test your class; make sure to call all four methods.
Answer 1: See CharSequenceDemo.java

Exercise 2: Suppose that you have written a time server, which periodically notifies its clients of the current date and time. Write an interface that the server could use to enforce a particular protocol on its clients.
Answer 2: See TimeClient.java

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Interfaces


You create an object from a class by using the new operator and a constructor. The new operator returns a reference to the object that was created. You can assign the reference to a variable or use it directly.

A class controls access to its instance variables and methods by using the Java platform's access mechanism. Instance variables and methods that are accessible to code outside of the class that they are declared in can be referred to by using a qualified name. The qualified name of an instance variable looks like this: objectReference.variableName The qualified name of a method looks like this: objectReference.methodName(argumentList) or objectReference.methodName() The garbage collector automatically cleans up unused objects. An object is unused if the program holds no more references to it. You can explicitly drop a reference by setting the variable holding the reference to null.


Answers to Questions and Exercises: Annotations (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Home Page > Learning the Java Language > Classes and Objects
« Previous • TOC
Answers to Questions and Exercises: Annotations

Questions

Question 1: What is wrong with the following interface:
public interface House {
    @Deprecated
    public void open();
    public void openFrontDoor();
    public void openBackDoor();
}
Answer 1:The documentation should reflect why open is deprecated and what to use instead. For example:
public interface House {
    /**
     * @deprecated use of open is discouraged, use
     * openFrontDoor or openBackDoor instead.
     */
    @Deprecated
    public void open();
    public void openFrontDoor();
    public void openBackDoor();
}

Question 2: Compile this program:

interface Closable {
    void close();
}

class File implements Closable {
    @Override
    public void close() {
        //... close this file...
    }
}

What happens? Can you explain why?

Answer 2: The compiler generates an error complaining that File.close doesn't override any method from its superclass. This is because it is not overriding Closable.close, it is implementing it!

Question 3: Consider this implementation of the House interface, shown in Question 1.

public class MyHouse implements House {
    public void open() {}
    public void openFrontDoor() {}
    public void openBackDoor() {}
}
If you compile this program, the compiler complains that open has been deprecated (in the interface). What can you do to get rid of that warning?

Answer 3: You can deprecate the implementation of open:

public class MyHouse implements House {
    //The documentation is inherited from the interface.
    @Deprecated
    public void open() {}
    public void openFrontDoor() {}
    public void openBackDoor() {}
}

Alternatively, you can suppress the warning:

public class MyHouse implements House {
    @SuppressWarnings("deprecation")
    public void open() {}
    public void openFrontDoor() {}
    public void openBackDoor() {}
}

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Annotations


Answers to Questions and Exercises: Classes (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Home Page > Learning the Java Language > Classes and Objects
« Previous • TOC
Answers to Questions and Exercises: Classes

Questions

Question 1: Consider the following class:
public class IdentifyMyParts {
    public static int x = 7;
    public int y = 3;
}
Question 1a. What are the class variables?
Answer 1a: x

Question 1b. What are the instance variables?
Answer 1b: y

Question 1c. What is the output from the following code:

IdentifyMyParts a = new IdentifyMyParts();
IdentifyMyParts b = new IdentifyMyParts();
a.y = 5;
b.y = 6;
a.x = 1;
b.x = 2;
System.out.println("a.y = " + a.y);
System.out.println("b.y = " + b.y);
System.out.println("a.x = " + a.x);
System.out.println("b.x = " + b.x);
System.out.println("IdentifyMyParts.x = " + IdentifyMyParts.x);
Answer 1c: Here is the output:
 a.y = 5
 b.y = 6
 a.x = 2
 b.x = 2
 IdentifyMyParts.x = 2

Because x is defined as a public static int in the class IdentifyMyParts, every reference to x will have the value that was last assigned because x is a static variable (and therefore a class variable) shared across all instances of the class. That is, there is only one x: when the value of x changes in any instance it affects the value of x for all instances of IdentifyMyParts.

This is covered in the Class Variables section of Understanding Instance and Class Members.

Exercises

Exercise 1: Write a class whose instances represent a single playing card from a deck of cards. Playing cards have two distinguishing properties: rank and suit. Be sure to keep your solution as you will be asked to rewrite it in Enum Types.
Answer 1: Card.java (in a .java source file)

Exercise 2: Write a class whose instances represents a full deck of cards. You should also keep this solution.
Answer 2: See Deck.java (in a .java source file) .

Exercise 3: Write a small program to test your deck and card classes. The program can be as simple as creating a deck of cards and displaying its cards.
Answer 3: See DisplayDeck.java (in a .java source file) .

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Classes


Answers to Questions and Exercises: Enum Types (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Home Page > Learning the Java Language > Classes and Objects
« Previous • TOC
Answers to Questions and Exercises: Enum Types

Exercises

Exercise 1: Rewrite the class Card from the exercise in Questions and Exercises: Classes so that it represents the rank and suit of a card with enum types.
Answer 1: See Card3.java, Suit.java, and Rank.java.

Exercise 2: Rewrite the Deck class.
Answer 2: See Deck3.java.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Enum Types


Answers to Questions and Exercises: Nested Classes (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Home Page > Learning the Java Language > Classes and Objects
« Previous • TOC
Answers to Questions and Exercises: Nested Classes

Questions

Question 1: The program Problem.java doesn't compile. What do you need to do to make it compile? Why?
Answer 1: Delete static in front of the declaration of the Inner class. An static inner class does not have access to the instance fields of the outer class. See ProblemSolved.java.

Question 2: Use the Java API documentation for the Box class (in the javax.swing package) to help you answer the following questions.

a. What static nested class does Box define?
Answer 2a: Box.Filler

 b. What inner class does Box define?
Answer 2b: Box.AccessibleBox

c. What is the superclass of Box’s inner class?
Answer 2c:[java.awt.]Container.AccessibleAWTContainer

d. Which of Box’s nested classes can you use from any class?
Answer 2d: Box.Filler

 e. How do you create an instance of Box’s Filler class?
Answer 2e: new Box.Filler(minDimension, prefDimension, maxDimension)

Exercises

Exercise 1: Get the file Class1.java.
a. Compile and run Class1. What is the output?
Answer:
InnerClass1: getString invoked.
InnerClass1: getAnotherString invoked.
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Nested Classes


Answers to Questions and Exercises: Objects (The Java™ Tutorials > Learning the Java Language > Classes and Objects)

Trail: Learning the Java Language
Lesson: Classes and Objects
Home Page > Learning the Java Language > Classes and Objects
« Previous • TOC
Answers to Questions and Exercises: Objects

Questions

Question 1: What's wrong with the following program?
public class SomethingIsWrong {
    public static void main(String[] args) {
        Rectangle myRect;
        myRect.width = 40;
        myRect.height = 50;
        System.out.println("myRect's area is " + myRect.area());
    }
}
Answer 1: The code never creates a Rectangle object. With this simple program, the compiler generates an error. However, in a more realistic situation, myRect might be initialized to null in one place, say in a constructor, and used later. In that case, the program will compile just fine, but will generate a NullPointerException at runtime.

Question 2: The following code creates one Point object and one Rectangle object. How many references to those objects exist after the code executes? Is either object eligible for garbage collection?

...
Point point = new Point(2,4);
Rectangle rectangle = new Rectangle(point, 20, 20);
point = null;
...
Answer 2: There is one reference to the Point object and one to the Rectangle object. Neither object is eligible for garbage collection.

Question: How does a program destroy an object that it creates?
Answer: A program does not explicitly destroy objects. A program can set all references to an object to null so that it becomes eligible for garbage collection. But the program does not actually destroy objects.

Exercises

Exercise 1: Fix the program called SomethingIsWrong shown in Question 1.
Answer 1: See SomethingIsRight

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class SomethingIsRight {
    public static void main(String[] args) {
        Rectangle myRect = new Rectangle();
        myRect.width = 40;
        myRect.height = 50;
        System.out.println("myRect's area is " + myRect.area());
    }
}

Exercise 2: Given the following class, called NumberHolder, write some code that creates an instance of the class, initializes its two member variables, and then displays the value of each member variable.

/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class NumberHolder {
    public int anInt;
    public float aFloat;
}

Answer 2: See NumberHolderDisplay
/*
 * Copyright (c) 1995 - 2008 Sun Microsystems, Inc.  All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 *   - Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 *
 *   - Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 *
 *   - Neither the name of Sun Microsystems nor the names of its
 *     contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
 * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

public class NumberHolderDisplay {
    public static void main(String[] args) {
    NumberHolder aNumberHolder = new NumberHolder();
    aNumberHolder.anInt = 1;
    aNumberHolder.aFloat = 2.3f;
    System.out.println(aNumberHolder.anInt);
    System.out.println(aNumberHolder.aFloat);
    }
}
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Objects


Java Language Keywords (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Home Page > Learning the Java Language > Language Basics
« Previous • TOC
Java Language Keywords
Here's a list of keywords in the Java programming language. You cannot use any of the following as identifiers in your programs. The keywords const and goto are reserved, even though they are not currently used. true, false, and null might seem like keywords, but they are actually literals; you cannot use them as identifiers in your programs.

abstract | continue | for | new | switch
assert*** | default | goto* | package | synchronized
boolean | do | if | private | this
break | double | implements | protected | throw
byte | else | import | public | throws
case | enum**** | instanceof | return | transient
catch | extends | int | short | try
char | final | interface | static | void
class | finally | long | strictfp** | volatile
const* | float | native | super | while

* not used
** added in 1.2
*** added in 1.4
**** added in 5.0

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Arrays


Answers to Questions and Exercises: Expressions, Statements, and Blocks (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Home Page > Learning the Java Language > Language Basics
« Previous • TOC
Answers to Questions and Exercises: Expressions, Statements, and Blocks

Questions

  1. Operators may be used in building expressions, which compute values.

  2. Expressions are the core components of statements.

  3. Statements may be grouped into blocks.

  4. The following code snippet is an example of a compound expression.

     1 * 2 * 3
  5. Statements are roughly equivalent to sentences in natural languages, but instead of ending with a period, a statement ends with a semicolon.

  6. A block is a group of zero or more statements between balanced braces and can be used anywhere a single statement is allowed.

Exercises

Identify the following kinds of expression statements:
  • aValue = 8933.234; // assignment statement
  • aValue++; // increment statement
  • System.out.println("Hello World!"); // method invocation statement
  • Bicycle myBike = new Bicycle(); // object creation statement
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Expressions, Statements, and Blocks


Answers to Questions and Exercises: Control Flow Statements (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Home Page > Learning the Java Language > Language Basics
« Previous • TOC
Answers to Questions and Exercises: Control Flow Statements

Answers to Questions

  1. The most basic control flow statement supported by the Java programming language is the if-then statement.

  2. The switch statement allows for any number of possible execution paths.

  3. The do-while statement is similar to the while statement, but evaluates its expression at the bottom of the loop.

  4. Question: How do you write an infinite loop using the for statement?

    Answer:

    for ( ; ; ) {

}

  5. Question: How do you write an infinite loop using the while statement?

    Answer:

    while (true) {

}

Exercises

  1. Consider the following code snippet.
    if (aNumber >= 0)
    if (aNumber == 0) System.out.println("first string");
else System.out.println("second string");
System.out.println("third string");
    1. Exercise: What output do you think the code will produce if aNumber is 3?

      Solution:

      second string
third string
    2. Exercise: Write a test program containing the previous code snippet; make aNumber 3. What is the output of the program? Is it what you predicted? Explain why the output is what it is. In other words, what is the control flow for the code snippet?

      Solution: NestedIf

      second string
third string
      3 is greater than or equal to 0, so execution progresses to the second if statement. The second if statement's test fails because 3 is not equal to 0. Thus, the else clause executes (since it's attached to the second if statement). Thus, second string is displayed. The final println is completely outside of any if statement, so it always gets executed, and thus third string is always displayed.

    3. Exercise: Using only spaces and line breaks, reformat the code snippet to make the control flow easier to understand.

      Solution:

      if (aNumber >= 0)
    if (aNumber == 0)
        System.out.println("first string");
    else
        System.out.println("second string");

System.out.println("third string");
    4. Exercise: Use braces { and } to further clarify the code and reduce the possibility of errors by future maintainers of the code.

      Solution:

      if (aNumber >= 0) {
    if (aNumber == 0) {
        System.out.println("first string");
    } else {
        System.out.println("second string");
    }
}

System.out.println("third string");
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Control Flow Statements


Answers to Questions and Exercises: Operators (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Home Page > Learning the Java Language > Language Basics
« Previous • TOC
Answers to Questions and Exercises: Operators

Answers to Questions

  1. Consider the following code snippet:
    arrayOfInts[j] > arrayOfInts[j+1]
    Question: What operators does the code contain?
    Answer: >, +

  2. Consider the following code snippet:
    int i = 10;
int n = i++%5;
    1. Question: What are the values of i and n after the code is executed?
      Answer: i is 11, and n is 0.

    2. Question: What are the final values of i and n if instead of using the postfix increment operator (i++), you use the prefix version (++i))?
      Answer: i is 11, and n is 1.

  3. Question: To invert the value of a boolean, which operator would you use?
    Answer: The logical complement operator "!".

  4. Question: Which operator is used to compare two values, = or == ?
    Answer: The == operator is used for comparison, and = is used for assignment.

  5. Question: Explain the following code sample: result = someCondition ? value1 : value2;
    Answer: This code should be read as: "If someCondition is true, assign the value of value1 to result. Otherwise, assign the value of value2 to result."

Exercises

  1. Change the following program to use compound assignments:
    class ArithmeticDemo {

     public static void main (String[] args){

          int result = 1 + 2; // result is now 3
          System.out.println(result);

          result = result - 1; // result is now 2
          System.out.println(result);

          result = result * 2; // result is now 4
          System.out.println(result);

          result = result / 2; // result is now 2
          System.out.println(result);

          result = result + 8; // result is now 10
          result = result % 7; // result is now 3
          System.out.println(result);

     }
}

    Here is one solution:

    class ArithmeticDemo {

     public static void main (String[] args){
          int result = 3;
          System.out.println(result);

          result -= 1; // result is now 2
          System.out.println(result);

          result *= 2; // result is now 4
          System.out.println(result);

          result /= 2; // result is now 2
          System.out.println(result);

          result += 8; // result is now 10
          result %= 7; // result is now 3
          System.out.println(result);

     }
}
  2. In the following program, explain why the value "6" is printed twice in a row:
    class PrePostDemo {
     public static void main(String[] args){
          int i = 3;
      i++;
      System.out.println(i);	// "4"
      ++i;
      System.out.println(i);	// "5"
      System.out.println(++i);	// "6"
      System.out.println(i++);	// "6"
      System.out.println(i);	// "7"
     }
}
    The code System.out.println(++i); evaluates to 6, because the prefix version of ++ evaluates to the incremented value. The next line, System.out.println(i++); evaluates to the current value (6), then increments by one. So "7" doesn't get printed until the next line.
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Operators


Answers to Questions and Exercises: Variables (The Java™ Tutorials > Learning the Java Language > Language Basics)

Trail: Learning the Java Language
Lesson: Language Basics
Home Page > Learning the Java Language > Language Basics
« Previous • TOC
Answers to Questions and Exercises: Variables

Answers to Questions

  1. The term "instance variable" is another name for non-static field.

  2. The term "class variable" is another name for static field.

  3. A local variable stores temporary state; it is declared inside a method.

  4. A variable declared within the opening and closing parenthesis of a method is called a parameter.

  5. What are the eight primitive data types supported by the Java programming language? byte, short, int, long, float, double, boolean, char

  6. Character strings are represented by the class java.lang.String.

  7. An array is a container object that holds a fixed number of values of a single type.

Answers to Exercises

  1. Create a small program that defines some fields. Try creating some illegal field names and see what kind of error the compiler produces. Use the naming rules and conventions as a guide.

    There is no single correct answer here. Your results will vary depending on your code.

  2. In the program you created in Exercise 1, try leaving the fields uninitialized and print out their values. Try the same with a local variable and see what kind of compiler errors you can produce. Becoming familiar with common compiler errors will make it easier to recognize bugs in your code.

    Again, there is no single correct answer for this exercise. Your results will vary depending on your code.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Variables


Answers to Questions and Exercises: Creating and Using Packages (The Java™ Tutorials > Learning the Java Language > Packages)

Trail: Learning the Java Language
Lesson: Packages
Home Page > Learning the Java Language > Packages
« Previous • TOC
Answers to Questions and Exercises: Creating and Using Packages

Answers

Question 1: Assume that you have written some classes. Belatedly, you decide that they should be split into three packages, as listed in the table below. Furthermore, assume that the classes are currently in the default package (they have no package statements).

Package Name

Class Name

mygame.server

Server

mygame.shared

Utilities

mygame.client

Client

a. What line of code will you need to add to each source file to put each class in the right package?
Answer 1a: The first line of each file must specify the package:

In Client.java add:
package mygame.client;
In Server.java add:
package mygame.server;:
In Utilities.java add:
package mygame.shared;
b. To adhere to the directory structure, you will need to create some subdirectories in your development directory, and put source files in the correct subdirectories. What subdirectories must you create? Which subdirectory does each source file go in?
Answer 1b: Within the mygame directory, you need to create three subdirectories: client, server, and shared.
In mygame/client/ place:
Client.java
In mygame/server/ place:
Server.java
In mygame/shared/ place:
Utilities.java
c. Do you think you'll need to make any other changes to the source files to make them compile correctly? If so, what?
Answer 1c: Yes, you need to add import statements. Client.java and Server.java need to import the Utilities class, which they can do in one of two ways:
import mygame.shared.*;
       --or--
import mygame.shared.Utilities;
Also, Server.java needs to import the Client class:
import mygame.client.Client;

Exercises

Exercise 1: Download three source files:
  • Client
  • Server
  • Utilities
a. Implement the changes you proposed in question 1, using the source files you just downloaded.
b. Compile the revised source files. (Hint: If you're invoking the compiler from the command line (as opposed to using a builder), invoke the compiler from the directory that contains the mygame directory you just created.)
Answer 1: Download this zip file with the solution: mygame.zip
You might need to change your proposed import code to reflect our implementation.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Creating and Using Packages


JavaBeans(TM): End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
JavaBeans(TM): End of Trail
You've reached the end of the "JavaBeans(TM)" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

Creating a GUI with JFC/Swing: Here is where you learn how to produce graphical user interfaces. This trail includes information on using the Swing components, which are JavaBeans-compliant.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: AWT Containers and the BeanContextProxy Interface


Trail: JavaBeans(TM): Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: JavaBeans(TM): Table of Contents
JavaBeans Concepts
Using the NetBeans GUI Builder
Writing a Simple Bean
Properties
Simple Properties
Bound Properties
Constrained Properties
Indexed Properties
Manipulating Events
Bean Persistence
Long Term Persistence
Introspection
Bean Customization
Using the BeanContext API
Overview of the BeanContext API
Bean Context #1: Containment Only
Bean Context #2: Containment and Services
AWT Containers and the BeanContextProxy Interface
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


This   text will  be analyzed

 by the WordCount

service.


  • Prioritized List of Improvements
  • Highlights of User Feedback

Name of Reviewer: | Ray Ortigas
Current Trail Author(s): | Andy Quinn
Was the author contacted? | No If yes, Date:
Comments: Needs a rewrite.

Prioritized List of Improvements/Corrections:

 Priority Scale:
(1-5)
1 = immediate attention required
3 = fix in next public push (2-3 weeks)
5 = when you get a chance...

  1. At

    • GNUmakefile and Makefile do not have .gmk and .mk suffixes.
    • There is no beans/apis directory.
    • beans/demos renamed to beans/demo; beans/demos/sunw/demos renamed to beans/demo/sunw/demo.
    • beans/lib contains methodtracer.jar; this needs to be explained.

    2. priority (1-5): 4

  2. At the Java applet shown is not the one that is generated by following the instructions. We should have the correct screen shot to reduce confusion.

    priority (1-5): 4

  3. At

    • Trying to complete step 4, many readers forget to enter a CR after the "Java-Bean: True" line, so when the manifest is added to the JAR, that line is omitted. We should have a warning about that.
    • You cannot find the sources for the font and color property editors at beans/apis/sun/beans/editors, since beans/apis doesn't even exist.

    priority (1-5): 4

  4. At , near the bottom of the page, it says:

    "The ChangeReporter Bean need not implement the PropertyChangeListener interface; instead, the BeanBox generated adapter class implements PropertyChangeListener, and the adapter's propertyChange method calls the appropriate method in the target object (ChangeReporter)."

    The explanation for this is not given on this page, but on another page. Nevertheless, it definitely should be explained on this page too, even if briefly, because people are going to start wondering why this works.

    priority (1-5): 4

  5. At

    There is no OurListBox class!!! It must have been removed in the recent release.

    Previous point notwithstanding, I still have no idea what an indexed property is after reading this lesson as well as the specification. While there is an example, there is no context for the example, which makes it useless. In my opinion, this lesson has to be rewritten from scratch.

    priority (1-5): 4

  6. At ,in the section "Hooking Up Events in the BeanBox", it says that in the Juggler's EventTargetDialog,

    "This list contains Juggler methods that take no arguments, or arguments of type actionPerformed."

    "actionPerformed" should really be "ActionEvent".

    priority (1-5): 4

  7. At in the section "Property Editors", it says that

    "To support the custom property editor, you need to override two more methods: Override supportsCustomEditor to return true, and override getCustomEditor to return a custom editor instance. ColorEditor.getCustomEditor returns this."

    Not to be too picky, but I think we want "implement" rather than "override", since PropertyEditor is an interface.

    priority (1-5): 4

  8. In the section "How Property Editors are Associated with Properties", it says that

    "Property editors are discovered and associated with a given property by ... [e]xplicit association via a BeanInfo object. The Molecule demo Bean uses this technique. Within the MoleculeBeanInfo class, the Molecule Bean's property editor is set with the following line of code:

    pd.setPropertyEditorClass(MoleculeNameEditor.class);"

    Two things:

    1) We are setting the property editor for the Molecule Bean's "MoleculeName" property, not the MoleculeBean itself.

    2) What is "pd"? When you look at the code, it's a property descriptor. We should include the code that defines "pd" so that people know what is going on.

    priority (1-5): 4

  9. In the section "The BDK Property Editors", there is a reference to beans/apis/sun/beans/editors, which doesn't exist.

    priority (1-5): 4

  10. In the section "BDK Customizers", there is a reference to OurButtonCustomizer, which seems to have been replaced by ExplicitButtonCustomizer in the latest BDK.

    priority (1-5): 4

  11. Also, there is the snippet: public BeanDescriptor getBeanDescriptor() { return new BeanDescriptor(beanClass, customizerClass); } ... private final static Class customizerClass = OurButtonCustomizer.class;

    We should add the line that defines beanClass.

    priority (1-5): 4

Highlights of User Feedback:

  • Date:
    User1's email

  • Date:
    User2's email

  • Date:
    User3's email

  • Date:
    User4's email


JDBC(TM) Database Access: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
JDBC(TM) Database Access: End of Trail
You've reached the end of the "JDBC(TM) Database Access" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

Creating a GUI with JFC/Swing: Using the JDBC to connect and interact with a database is generally considered the back-end of an application. You can use Swing to put a user interface on the front-end of your database application.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Creating an Applet from an Application


Trail: JDBC(TM) Database Access: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: JDBC(TM) Database Access: Table of Contents
JDBC Introduction
JDBC Architecture
A Relational Database Overview
JDBC Basics
Getting Started
Setting Up a Database
Establishing a Connection
Setting Up Tables
Retrieving Values from Result Sets
Updating Tables
Milestone: The Basics of JDBC
Using Prepared Statements
Using Joins
Using Transactions
Stored Procedures
SQL Statements for Creating a Stored Procedure
Creating Complete JDBC Applications
Running the Sample Applications
Creating an Applet from an Application
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Use of ResultSet.getXXX: Table-Free Versions (The Java™ Tutorials > JDBC(TM) Database Access > JDBC Basics)

Trail: JDBC(TM) Database Access
Lesson: JDBC Basics
Home Page > JDBC(TM) Database Access > JDBC Basics
« Previous • TOC
Use of ResultSet.getXXX: Table-Free Versions
Because the large table in Getting Started can be hard to read (especially with screen readers), this page presents two alternate versions of the table's data. The first version displays the information you can get by looking down each column of the table. The second displays the information for each row of the table.
  • Version 1: How to read each JDBC type
  • Version 2: Which types each ResultSet.getXXX method can read
If you have any suggestions for improving this page, please tell us.

Version 1: How to read each JDBC type

This section lists the ResultSet.getXXX methods recommended and allowed for retrieving data of each JDBC type.
TINYINT: getByte (recommended)
Can also be read using getShort, getInt, getLong, getFloat, getDouble, getBigDecimal, getBoolean, getString, getObject

SMALLINT: getShort (recommended)
Can also be read using getByte, getInt, getLong, getFloat, getDouble, getBigDecimal, getBoolean, getString, getObject

INTEGER: getInt (recommended)
Can also be read using getByte, getShort, getLong, getFloat, getDouble, getBigDecimal, getBoolean, getString, getObject

BIGINT: getLong (recommended)
Can also be read using getByte, getShort, getInt, getFloat, getDouble, getBigDecimal, getBoolean, getString, getObject

REAL: getFloat (recommended)
Can also be read using getByte, getShort, getInt, getLong, getDouble, getBigDecimal, getBoolean, getString, getObject

FLOAT: getDouble (recommended)
Can also be read using getByte, getShort, getInt, getLong, getFloat, getBigDecimal, getBoolean, getString, getObject

DOUBLE: getDouble (recommended)
Can also be read using getByte, getShort, getInt, getLong, getFloat, getBigDecimal, getBoolean, getString, getObject

DECIMAL: getBigDecimal (recommended)
Can also be read using getByte, getShort, getInt, getLong, getFloat, getDouble, getBoolean, getString, getObject

NUMERIC: getBigDecimal (recommended)
Can also be read using getByte, getShort, getInt, getLong, getFloat, getDouble, getBoolean, getString, getObject

BIT: getBoolean (recommended)
Can also be read using getByte, getShort, getInt, getLong, getFloat, getDouble, getBigDecimal, getString, getObject

CHAR: getString (recommended)
Can also be read using getByte, getShort, getInt, getLong, getFloat, getDouble, getBigDecimal, getBoolean, getDate, getTime, getTimestamp, getAsciiStream, getUnicodeStream, getObject

VARCHAR: getString (recommended)
Can also be read using getByte, getShort, getInt, getLong, getFloat, getDouble, getBigDecimal, getBoolean, getDate, getTime, getTimestamp, getAsciiStream, getUnicodeStream, getObject

LONGVARCHAR: getAsciiStream, getUnicodeStream (both recommended)
Can also be read using getByte, getShort, getInt, getLong, getFloat, getDouble, getBigDecimal, getBoolean, getString, getDate, getTime, getTimestamp, getObject

BINARY: getBytes (recommended)
Can also be read using getString, getAsciiStream, getUnicodeStream, getBinaryStream, getObject

VARBINARY: getBytes (recommended)
Can also be read using getString, getAsciiStream, getUnicodeStream, getBinaryStream, getObject

LONGVARBINARY: getBinaryStream (recommended)
Can also be read using getString, getBytes, getAsciiStream, getUnicodeStream, getObject

DATE: getDate (recommended)
Can also be read using getString, getTimestamp, getObject

TIME: getTime (recommended)
Can also be read using getString, getTimestamp, getObject

TIMESTAMP: getTimestamp (recommended)
Can also be read using getString, getDate, getTime, getObject

Version 2: Which types each ResultSet.getXXX method can read

This section lists the JDBC types that each ResultSet.getXXX method supports.
getByte: TINYINT (recommended)
Can also read SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR, LONGVARCHAR

getShort: SMALLINT (recommended)
Can also read TINYINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR, LONGVARCHAR

getInt: INTEGER (recommended)
Can also read TINYINT, SMALLINT, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR, LONGVARCHAR

getLong: BIGINT (recommended)
Can also read TINYINT, SMALLINT, INTEGER, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR, LONGVARCHAR

getFloat: REAL (recommended)
Can also read TINYINT, SMALLINT, INTEGER, BIGINT, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR, LONGVARCHAR

getDouble: FLOAT, DOUBLE (both recommended)
Can also read TINYINT, SMALLINT, INTEGER, BIGINT, REAL, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR, LONGVARCHAR

getBigDecimal: DECIMAL, NUMERIC (both recommended)
Can also read TINYINT, SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, BIT, CHAR, VARCHAR, LONGVARCHAR

getBoolean: BIT (recommended)
Can also read TINYINT, SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, CHAR, VARCHAR, LONGVARCHAR

getString: CHAR, VARCHAR (both recommended)
Can also read TINYINT, SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, LONGVARCHAR, BINARY, VARBINARY, LONGVARBINARY, DATE, TIME, TIMESTAMP

getBytes: BINARY, VARBINARY (both recommended)
Can also read LONGVARBINARY

getDate: DATE (recommended)
Can also read CHAR, VARCHAR, LONGVARCHAR, TIMESTAMP

getTime: TIME (recommended)
Can also read CHAR, VARCHAR, LONGVARCHAR, TIMESTAMP

getTimestamp: TIMESTAMP (recommended)
Can also read CHAR, VARCHAR, LONGVARCHAR, DATE, TIME

getAsciiStream: LONGVARCHAR (recommended)
Can also read CHAR, VARCHAR, BINARY, VARBINARY, LONGVARBINARY

getUnicodeStream: LONGVARCHAR (recommended)
Can also read CHAR, VARCHAR, BINARY, VARBINARY, LONGVARBINARY

getBinaryStream: LONGVARBINARY (recommended)
Can also read BINARY, VARBINARY

getObject: (no recommended type)
Can read TINYINT, SMALLINT, INTEGER, BIGINT, REAL, FLOAT, DOUBLE, DECIMAL, NUMERIC, BIT, CHAR, VARCHAR, LONGVARCHAR, BINARY, VARBINARY, LONGVARBINARY, DATE, TIME, TIMESTAMP
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Retrieving Values from Result Sets


The JDBC-ODBC Bridge allows applications written in the JavaTM programming language to use the JDBCTM API with many existing ODBC drivers. The Bridge is itself a driver based on JDBC technology ("JDBC driver") that is defined in the class sun.jdbc.odbc.JdbcOdbcDriver. The Bridge defines the JDBC sub protocol odbc.

Status of the JDBC-ODBC Bridge

The JDBC-ODBC Bridge should be considered a transitional solution. Sun Microsystems and DataDirect Technologies are working to make the Bridge more reliable and robust, but they do not consider it a supported product. With the development of pure Java JDBC drivers, the JDBC-ODBC Bridge should become unnecessary.

Why not just use ODBC?

The JDBC-ODBC Bridge offers several advantages over "naked" ODBC.
  • The ODBC API is strongly oriented toward C/C++ programmers. The JDBC-ODBC Bridge makes it unnecessary for programmers using the Java programming language to deal with non-Java language concepts.
  • The ODBC API is extremely complex and intermingles high level and low level functions. The JDBC-ODBC Bridge allows the programmer to rely on the JDBC API, which is relatively simple and easy to learn.
  • The JDBC-ODBC Bridge lets a program deal with ODBC through a standardized JDBC interface. That helps a program avoid being tied to ODBC when a better solution comes along.

Why use ODBC at all?

The ideal is "Pure Java": no native code, no platform dependent features. But you may need to begin your development effort right away, without waiting for your DBMS to offer a Java only JDBC driver. Partly native drivers, such as the JDBC-ODBC Bridge, let you create programs that easily adapt to Pure Java drivers as they become available.

What's New with the JDBC-ODBC Bridge?

  • A jdbc:odbc: connection can now have a charSet property, to specify a Character Encoding Scheme other than the client default. For possible values, see the Internationalization specification on the Java Software Web Site.

    • The following code fragment shows how to set 'Big5' as the character set for all character data. // Load the JDBC-ODBC bridge driver Class.forName(sun.jdbc.odbc.JdbcOdbcDriver) ; // setup the properties java.util.Properties prop = new java.util.Properties(); prop.put("charSet", "Big5"); prop.put("user", username); prop.put("password", password); // Connect to the database con = DriverManager.getConnection(url, prop);
  • The bridge now supports JDBC 2.0 features, which includes batch updates, scrollable cursors, and so on.
  • JDBC-ODBC bridge now offers most of the features required for a J2EE compatible JDBC driver.
  • Sample implementations of DataSource and ConnectionPoolDataSource are available with the JDBC-ODBC bridge.
  • CallableStatement OUT/INOUT parameter handling has been improved.
  • Automatic garbage collection of unclosed Statement objects has been implemented.
  • Improved support for updatable Resultset objects has been implemented.
  • Additional robustness and reliability checking as been introduced.

New DataSource Implementations in the JDBC-ODBC Bridge

Implementations of javax.sql.DataSource and javax.sql.ConnectionPoolDataSource are now available. Both are in the sun.jdbc.odbc.ee package. The following code fragment illustrates how to set DataSource properties.

The last two lines use JNDI API to bind the DataSource object ds to jdbc/OdbcDB1. Assume that the DataSource object is targeting an ODBC DSN "dsn1" connecting to an Oracle Database.

// Establish the DataSource object instance sun.jdbc.odbc.ee.DataSource ds = new sun.jdbc.odbc.ee.DataSource(); // Provide user credentials and database name ds.setUser("scott"); ds.setPassword("tiger"); ds.setDatabaseName("dsn1"); ds.setCharSet("..."); // optional property ds.setLoginTimeout(100); // optional property // Establish initial context and bind to the datasource target InitialContext ic = new InitialContext(); ic.bind("jdbc/OdbcDB1",ds);

In the preceding code, note that some properties are optional while some are required. Properties such as port number and role name are not implemented in the JDBC-ODBC bridge DataSource implementations as these properties are not applicable to ODBC paradigm.

Continuing the previous example, the following code fragment demonstrates retrieving the DataSource object by looking up the JNDI name "jdbc/OdbcDB1". With the DataSource object that is obtained, the code then activates tracing and creates two connections.

// Get the initial context of JNDI and lookup the datasource. InitialContext ic = new InitialContext(); javax.sql.DataSource ds1 = (javax.sql.DataSource) ic.lookup("jdbc/OdbcDB1"); // Set the optional printwriter where the trace log is to be directed. ds1.setLogWriter(new PrintWriter( new FileOutputStream("/tmp/datasource.log"))); Connection con1 = ds1.getConnection(); Connection con2 = ds1.getConnection("system","manager");

The implementation of javax.sql.ConnectionPoolDataSource uses an underlying pool of JDBC-ODBC connections. A ConnectionPoolDataSource object is used to create PooledConnection objects, which are in turn used to get Connection objects. From the user's viewpoint, the Connection object is just like any other connection.

The following code fragment creates the ConnectionPoolDataSource object cpds and sets its properties. The final two lines use JNDI API to bind cpds to jdbc/OdbcPool, which can later be supplied to the method InitialContext.lookup to retrieve cpds.

// Establish ConnectionPoolDataSource instance sun.jdbc.odbc.ee.ConnectionPoolDataSource cpds = new sun.jdbc.odbc.ee.ConnectionPoolDataSource("jdbc/OdbcPool"); // Provide user credentials and database name cpds.setUser("scott"); cpds.setPassword("tiger"); cpds.setDatabaseName("dsn1"); cpds.setCharSet("...") // optional property cpds.setLoginTimeout(100); // optional property cpds.setMinPoolSize("10"); cpds.setInitialPoolSize("15"); cpds.setMaxPoolSize("20"); cpds.setMaxIdleTime("300"); cpds.setTimeoutFromPool("600"); // Maintenance interval of the pool. A maintenance thread will remove // unwanted connections and cleanup the pool at the interval specified. // This cannot be zero. cpds.setMaintenanceInterval("900"); InitialContext ic = new InitialContext(); ic.bind("jdbc/OdbcPool",cpds);

In all cases in order get the ConnectionPoolDataSource to function as a pooled datasource, it is the responsibility of the application to configure the pool as described in the code example above. The default behavior of pooled datasource uses a zero minimum, initial and maximum pool sizes. Note that the JDBC-ODBC bridge implementation of ConnectionPoolDataSource does not yet include the pooling of Statement objects or the property propertyCycle.

The following code fragment shows how to use a ConnectionPoolDataSource object as simply a DataSource object. This is done by doing a JNDI lookup of "jdbc/OdbcPool" and casting it to a DataSource object instead of to a ConnectionPoolDataSource object.

InitialContext ic = new InitialContext(); javax.sql.DataSource ds1 = (javax.sql.DataSource) ic.lookup("jdbc/OdbcPool"); // First getConnection will initializes the pool. Connection con1 = ds1.getConnection(); Connection con2 = ds1.getConnection("system","manager"); // An application need to close the connection explicitly. //This will allow the pool to recycle the connection. con1.close(); con2.close();

Using the implementation as a ConnectionPoolDataSource object is shown in the following line of code. Note that closing a PooledConnection object closes the actual physical connection, whereas closing a connection that was created from a PooledConnection object just returns it to the pool of connections.

InitialContext ic = new InitialContext(); javax.sql.ConnectionPoolDataSource cpds = (javax.sql.ConnectionPoolDataSource) ic.lookup("jdbc/OdbcPool"); PooledConnection pc1 = cpds.getPooledConnection(); Connection con1 = pc1.getConnection(); PooledConnection pc2 = cpds.getPooledConnection("system","manager"); Connection con2 = pc2.getConnection(); // An application needs to close the connection explicitly. // This will allow the pool to recycle the connection. con1.close(); con2.close(); Connection con3 = pc1.getConnection(); Connection con4 = pc2.getConnection(); // This will close the physical connection! pc1.close(); pc2.close();

A pool of connections can be shut down in two ways. If the method shutDown is given the argument false, only those connections that are not being used will be closed. If the argument true is supplied, all connections will be closed immediately, regardless of whether they are being used or not.

// Hot shutdown ((sun.jdbc.odbc.ee.ConnectionPoolDataSource) cpds).shutDown(true); // Cold shutdown ((sun.jdbc.odbc.ee.ConnectionPoolDataSource) cpds).shutDown(false);


Query Output

 Output from query select NAME, PRICE from COFFEES


  • Prioritized List of Improvements
  • Highlights of User Feedback

Name of Reviewer: | Indrayana Rustandi
Current Trail Author(s): | Maydene Fisher
Was the author contacted? | No If yes, Date:
Comments:

Prioritized List of Improvements/Corrections:

 Priority Scale:
(1-5)
1 = immediate attention required
3 = fix in next public push (2-3 weeks)
5 = when you get a chance...
  1. Recommendation1
    Add more sample programs to illustrate the concepts explained.
    priority (1-5): 2

  2. Recommendation2
    Fix the applet example.
    Note: I have a working example.
    priority (1-5): 2

  3. Recommendation3
    I don't know how important the issue of closing connections and/or statements is. This should also be covered.
    priority (1-5): 3

  4. Recommendation4
    A reader brings to my attention the issue of obtaining multiple results sets from a statement. Here's an example:

    Connection con = ... // create a connection
    String query = "..."
    Statement stmt = con.createStatement();
    stmt.executeQuery();
    ResultSet rs = stmt.getResultSet();

     The call to executeQuery() also returns a result set. So now there are to result sets. I tried this, and it worked fine. However, I don't about any issues that may arise. Reference: User1's email.
    priority (1-5): 4

  5. Recommendation5
    Also need to be mentioned, how to deal with primary and foreign keys through JDBC.
    priority (1-5): 4

  6. Recommendation6
    There's a reader that criticizes the design of the database, including the omission of primary keys. However, since I haven't been doing anything much in the database field, I'm not sure about the issue here. But you should look at the email. Reference: User2's email.
    priority (1-5): 2

Highlights of User Feedback:

  • Date: 24 November 1998
    User1's email: ad@chooseyourmail.com

  • Date: 4 July 1999
    User2's email: rgparker@west.net

  • Date:
    User3's email

  • Date:
    User4's email


Java Management Extensions (JMX): End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
Java Management Extensions (JMX): End of Trail
You've reached the end of the "Java Management Extensions (JMX)" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

The purpose of this trail has been to provide you with a brief introduction to the basic elements of the JMX technology. More advanced materials can be found elsewhere.

The following resources will be useful if you wish to study the JMX technology further:

  • JMX Technology documentation for the Java SE Platform. The JMX Technology documentation is included in the Java SE platform documentation set.
  • JMX Technology Overview. The Java SE platform documentation for the JMX technology contains the JMX Technology Overview, which provides a more detailed description of the JMX Technology than is provided in the present trail.
  • JMX Technology Tutorial. The lessons in this trail are based on the examples used in the JMX Technology Tutorial. In addition to the basic elements presented in the present trail, the JMX Technology Tutorial presents more advanced aspects of the JMX technology.
  • In addition to the examples presented in the above tutorial, once you have installed the Java Development Kit (JDK) 6, a sample application that demonstrates a real-life implementation of the JMX API can be found in the following directory:
    jdk_home/sample/jmx/jmx-scandir
    Where jdk_home is the directory in which the JDK software is installed. The jmx-scandir example is an advanced example, which presents advanced concepts of the JMX API in a real-world scenario.
  • Monitoring and Management for the Java Platform. The technologies and APIs provided for the monitoring and management of the Java SE platform rely heavily on the JMX technology. The Java SE Monitoring and Management Guide contains a chapter on Monitoring and Management Using JMX Technology.
  • JMX Technology home page. The JMX technology home page is the place to go for all the latest news about the JMX technology.
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Creating a Custom JMX Client


Trail: Java Management Extensions (JMX): Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: Java Management Extensions (JMX): Table of Contents
Trail: Java Management Extensions (JMX)
Overview of JMX Technology
What is the JMX Technology?
Why Use JMX Technology?
Architecture of JMX Technology
Out-of-the-Box Management of the Java VM
Introducing MBeans
Standard MBeans
MXBeans
Notifications
Remote Management
Exposing a Resource For Remote Management By JConsole
Creating a Custom JMX Client
Where to Go From Here
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Java Naming and Directory Interface(TM).: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
Java Naming and Directory Interface(TM).: End of Trail
You've reached the end of the "Java Naming and Directory Interface(TM)." trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

RMI: RMI is a Java-to-Java alternative to IDL for writing client/server programs.

Security Features in Java SE: When writing programs that communicate, you need to understand the security implications.

JDBC Database Access: This trail shows you how to access a database from Java programs.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Setting Timeout for Ldap Operations


Trail: Java Naming and Directory Interface(TM).: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: Java Naming and Directory Interface(TM).: Table of Contents
Naming and Directory Concepts
Directory Concepts
Overview of JNDI
Naming Package
Directory and LDAP Packages
Event and Service Provider Packages
Software Setup
LDAP Setup
Java Application Setup
Naming and Directory Operations
Naming Exceptions
Lookup an Object
List the Context
Add, Replace or Remove a Binding
Rename
Create and Destroy Subcontexts
Attribute Names
Read Attributes
Modify Attributes
Add, Replace Bindings with Attributes
Search
Basic Search
Filters
Scope
Result Count
Time Limit
Trouble Shooting Tips
Advanced Topics for LDAP Users
LDAP v3
JNDI as an LDAP API
How LDAP Operations Map to JNDI APIs
How LDAP Error Codes Map to JNDI Exceptions
Security
Modes of Authenticating to LDAP
Authentication Mechanisms
Anonymous
Simple
SASL
Digest-MD5
SSL and Custom Sockets
More LDAP Operations
LDAP Compare
Search Results
LDAP Unsolicited Notifications
Connection Management
Creation
Closing
Pooling
Configuration
Frequently Asked Questions
Java Objects in the Directory
Storing and Reading Objects
Serializable Objects
New features in JDK 5.0 and JDK 6
Retrieving Distinguished Name
Standard LDAP Controls
Paged Results Control
Sort Control
Manage Referral Control
Manipulating LdapName (Distinguished Name)
Manipulating Relative Distringuished Name (RDN)
Setting Timeout for Ldap Operations
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


            Java/CORBA LDAP Schema Tools

This note describes the tools for creating schema entries for storing
Java and CORBA objects.

The Java schema is described in RFC 2713.
      http://www.ietf.org/rfc/rfc2713.txt

The CORBA schema is described in RFC 2714.
      http://www.ietf.org/rfc/rfc2714.txt

1. UPDATING THE DIRECTORY SCHEMA

   You can use your directory's administration tool to update the schema,
   Or, you can use the CreateJavaSchema and CreateCorbaSchema programs.

      java [-Djava.naming.provider.url=<provider_url>] \
         CreateCorbaSchema|CreateJavaSchema \
       [-h|-s[n]] [-n<dn>] [-p<passwd>] [-a<auth>]

     -h		  Print the usage message
     -l		  List the relevant schema in the directory
     -s[n|n41|ad] Update schema:
                    -sn   means use a workaround for schema bugs in
                          pre-4.1 releases of Netscape Directory Server

            -sn41 means use a workaround for schema bugs in
                          Netscape Directory Server version 4.1

            -sad  means use a workaround for schema bugs in
              Microsoft Windows 2000 Active Directory

     -n<dn> 	  Use <dn> as the distinguished name for authentication
     -p<passwd>	  Use <passwd> as the password for authentication
     -a<auth>	  Use <auth> as the authentication mechanism.
          Default is "simple".

   If neither -s, -l, nor -h has been specified, the default is "-l".

   NOTE: If you are using Netscape Directory Server 4.0 (or earlier),
         you need to use the "-sn" option to workaround schema bugs in
         the server.

   NOTE: If you are using Netscape Directory Server 4.1,
         you need to use the "-sn41" option to workaround schema bugs in
         the server. Also, before making any changes to the schema, you
         must make the following schema modification. Locate the ns-schema.conf
         file in the server installation at the directory named:

             <NETSCAPE-DIRECTORY-HOME>/slapd-<SERVER-ID>/config/

         Comment out the line that contains 'java-object-schema.conf'
         because that schema is now out-of-date. Then re-start the
         server and use the CreateJavaSchema program to install the
         updated schema. It is necessary to manually remove the
         reference to the old schema from the list of built-in schemas
         in ns-schema.conf because the server does not permit such
         built-in schemas to be modified via the LDAP protocol.

   NOTE: If you are using Microsoft Active Directory you need to use
         the "-sad" option to workaround schema bugs in the server.
         Also, to enable any schema modifications the following registry
         property must be created and set to (DWORD) 1:

             HKEY_LOCAL_MACHINE
           System
             CurrentControlSet
               Services
                 NTDS
                   Parameters
                     Schema Update Allowed

   If the directory's administration tool supports turning off schema
   checking then do so before running the CreateJavaSchema or
   CreateCorbaSchema programs.

   When you run these programs, you need to login as the directory
   administrator, quoting the "-n" option if there are blanks in the
   distinguished name. After updating the schema, you should use the
   directory server's administration tool to verify that the changes
   have been properly applied. The Netscape Directory Server 3.0, for
   example, ignores some attributes. If the schema has not been properly
   updated, use the administration tool to correct it.

   For example, to create the Java schema in a Netscape Directory Server
   version 4.1,

       java -Djava.naming.provider.url=ldap://myserver CreateJavaSchema\
           -sn41 "-ncn=Directory Administrator" -psecret

   For example, to create the CORBA schema in a Netscape Directory Server
   version 4.0,

       java -Djava.naming.provider.url=ldap://myserver CreateCorbaSchema\
           -sn "-ncn=Directory Administrator" -psecret

   For example, to create the Java schema in a Windows 2000 Active Directory,

       java -Djava.naming.provider.url=ldap://myserver CreateJavaSchema\
           -sad "-ncn=administrator,cn=users,dc=xxx,dc=yyy,dc=zzz" -psecret
----


Custom Networking: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
Custom Networking: End of Trail
You've reached the end of the "Custom Networking" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

RMI: RMI is a Java-to-Java alternative to IDL for writing client/server programs.

Security Features in Java SE: When writing programs that communicate, you need to understand the security implications.

JDBC Database Access: This trail shows you how to access a database from Java programs.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Custom CookieManager


Trail: Custom Networking: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: Custom Networking: Table of Contents
Overview of Networking
What You May Already Know About Networking in Java
Networking Basics
Working with URLs
What Is a URL?
Creating a URL
Parsing a URL
Reading Directly from a URL
Connecting to a URL
Reading from and Writing to a URLConnection
All About Sockets
What Is a Socket?
Reading from and Writing to a Socket
Writing the Server Side of a Socket
All About Datagrams
What Is a Datagram?
Writing a Datagram Client and Server
Broadcasting to Multiple Recipients
Programmatic Access to Network Parameters
What Is a Network Interface?
Retrieving Network Interfaces
Listing Network Interface Addresses
Network Interface Parameters
Working With Cookies
HTTP State Management With Cookies
CookieHandler Callback Mechanism
Default CookieManager
Custom CookieManager
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Platform-Specific Details: Setting the Proxy Host (The Java™ Tutorials > Custom Networking > Working with URLs)

Trail: Custom Networking
Lesson: Working with URLs
Home Page > Custom Networking > Working with URLs
« Previous • TOC
Platform-Specific Details: Setting the Proxy Host
You can set the proxy host through the command line. Depending on your network configuration, you might also need to set the proxy port. If necessary, ask your system administrator for the name of the proxy host on your network.
UNIX
java -Dhttp.proxyHost=proxyhost
    [-Dhttp.proxyPort=portNumber] URLReader
DOS shell (Windows 95/NT)
java -Dhttp.proxyHost=proxyhost
    [-Dhttp.proxyPort=portNumber] URLReader
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Reading Directly from a URL


The Reflection API: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
The Reflection API: End of Trail
You've reached the end of the "The Reflection API" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Troubleshooting


Trail: The Reflection API: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: The Reflection API: Table of Contents
Classes
Retrieving Class Objects
Examining Class Modifiers and Types
Discovering Class Members
Troubleshooting
Members
Fields
Obtaining Field Types
Retrieving and Parsing Field Modifiers
Getting and Setting Field Values
Troubleshooting
Methods
Obtaining Method Type Information
Retrieving and Parsing Method Modifiers
Invoking Methods
Troubleshooting
Constructors
Finding Constructors
Retrieving and Parsing Constructor Modifiers
Creating New Class Instances
Troubleshooting
Arrays and Enumerated Types
Arrays
Identifying Array Types
Creating New Arrays
Getting and Setting Arrays and Their Components
Troubleshooting
Enumerated Types
Examining Enums
Getting and Setting Fields with Enum Types
Troubleshooting
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


RMI: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
RMI: End of Trail
You've reached the end of the "RMI" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

Security: When writing programs that communicate, you need to understand the security implications.

JDBC Database Access: This trail shows you how to access a database from Java programs.

Custom Networking: Describes low-level networking capabilities, such as sockets and datagrams, provided by the JDK.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Running the Example Programs


Trail: RMI: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: RMI: Table of Contents
An Overview of RMI Applications
Writing an RMI Server
Designing a Remote Interface
Implementing a Remote Interface
Creating a Client Program
Compiling and Running the Example
Compiling the Example Programs
Running the Example Programs
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


  • Prioritized List of Improvements
  • Highlights of User Feedback

Name of Reviewer: | Ray Ortigas
Current Trail Author(s): | Ann Wollrath, Jim Waldo
Was the author contacted? | No If yes, Date:
Comments:

Prioritized List of Improvements/Corrections:

 Priority Scale:
(1-5)
1 = immediate attention required
3 = fix in next public push (2-3 weeks)
5 = when you get a chance...

  1. At there is a reference to "JNDI", but nowhere in the tutorial is this acronym ever explained.

    priority (1-5): 4

  2. Should add a link to security trail for running RMI example, since it uses a policy file.

    priority (1-5): 3

  3. Should point out that the RemoteException must be declared in the throws clause of every method in a Remote interface (any interface that extends Remote).

    priority (1-5): 3

  4. Applets and RMI? A few users are asking about it; maybe we should take a look at it, although I doubt this is a worthy topic to pursue.

    priority (1-5): 5

  5. Note that trailing slash is needed when running example and passing directories as parameters.

    priority (1-5): 4

  6. Add a note about unsetting CLASSPATH on Windows (merely "set CLASSPATH=" as opposed to "unset CLASSPATH" on Solaris).

    priority (1-5): 3

Highlights of User Feedback:

  • Date: 16 Jan 1999

    I am currently working on a problem involving RMI. I am faced with a problem that whenever the network load is high, some kind of timeout occurs and 'NoRouteToHost' exception is thrown. I want to change the settings in RMI so that this timeout period is increased.

  • Date: 30 Mar 1999

    Over the past few weeks I've spent quite a bit of time in the RMI trail of the Java Tutorial (March 12, 1999 edition) and I feel there are some very serious problems that should be addressed.

    I sincerely don't mean to sound critical in this e-mail -- overall I think the Java Tutorial is a terrific piece of work -- but the RMI trail needs some fixing up (IMHO). If you'd like to speak with me about any of these issues, you can reach me at: W:(602) 607-4995 or H:(602) 813-4452.

    I'm sorry about the length of this message but I've tried to be complete and clear.

    First, I'd like to direct your attention to the section entitled, "Build a JAR File of Interface Classes", at "/rmi/compiling.html". The second-to-last paragraph in that section begins with this statement:

    "When you build either server- or client-side classes with the javac and rmic compilers, you generally need to specify where the resulting class files should reside so that they are network accessible."

    I believe this is a minor wording problem. Although it is necessary to specify a "network-accessible" location of class files before the client and server begin execution so that classes may be downloaded dynamically, it is *not* necessary to specify their network-accessible location at *build* time, as the statement above implies. I believe the statement above should read:

    "After you build either the server- or client-side classes with the javac and rmic compilers, you will need to ensure the resulting class files are placed in a network accessible location."

    The same paragraph also seems to indicate that it is entirely possible to use a "file:" URL when specifying where classes reside. Now, I'm not sure if the reference to the "file:" URL pertains to the location of class files at compile-time or runtime. I assume it refers to making the class files network-accessible at runtime. In other words, I interpret the reference to the "file:" URL to mean that classes can be made network-accessible using the "file:" URL rather than an "HTTP:" URL. Is this correct? I'll have more to say about this below.

    The last paragraph in the same section makes reference to the use of an HTTP server to download classes. It does not, however, indicate that an HTTP server is an absolute requirement for downloading classes. In fact, the Tutorial says, "RMI uses URL protocols supported by the Java platform..." I assume this includes the "file:" URL. In other words, my impression is that an HTTP server *can* be used but so long as a network connection is available, HTTP is not absolutely required. On the other hand, the Tutorial makes reference to a "simple HTTP server" (ftp://java.sun.com/pub/jdk1.1/rmi/class-server.zip). Does this mean HTTP *is* required? I recently posted this question to a few Java newsgroups, as well as the JDC, and some of the responses I received indicated that an HTTP server *MUST* be running on the machine from which classes will be downloaded. If this is so, the Java Tutorial should say so explicitly. If this is not the case, then it would be extremely helpful if the Tutorial provided a working example using the "file:" URL between two separate machines.

    I'd also like to direct your attention to the section entitled, "A Note about Security" on "rmi/running.html". I think it would be very helpful if the relationship between a "Permissions Policy" file and the use of the RMISecurityManager was described. What does the RMISecurityManager provide that the "Permissions Policy" file doesn't and vice versa? Do I need both the RMISecurityManager *and* a "Permissions Policy" file?

    The next section, entitled, "Start the Server", begins with this statement:

    "If you *do* start the rmiregistry and it *can* find your stub classes in CLASSPATH, it will not remember that the loaded stub class can be loaded from your server's code base, ..."

    Personally, I find this entire paragraph a bit confusing. I believe that somehow the notion of annotating a class is involved here but I really don't have a feel for it's relevance and the Tutorial does not even mention class annotation. I'd like to see a discussion on how class annotation is related to the java.rmi.server.codebase property and also a description of where the java.rmi.server.RMIClassLoader fits into the picture. What's the result if the java.rmi.server.codebase property is *not* set? When will the RMIClassLoader be used and when will it not be used?

    Ealier, I mentioned that it seemed to be possible (according to the Tutorial) to use a "file:" URL to dynamically load classes across the network. Again, in the "Start the Server" section of the Tutorial is an example that specifies a "file:" URL for the java.rmi.server.codebase property:

    java -Djava.rmi.server.codebase=file:/c:\home\ann\public_html\classes/
     -Djava.rmi.server.hostname=zaphod.east.sun.com
     -Djava.security.policy=java.policy
       engine.ComputeEngine

    Once again, I'm assumming this means it is *not* necessary to have any form of HTTP server running. Is this correct?

  • Date:
    User3's email

  • Date:
    User4's email


Security Features in Java SE: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
Security Features in Java SE: End of Trail
You've reached the end of the "Security Features in Java SE" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

RMI: RMI is a Java-to-Java alternative to IDL for writing client/server programs.

Custom Networking: Describes low-level networking capabilities, such as sockets and datagrams, provided by the JDK.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Steps for a User Running TerrysGame (Kim)


Trail: Security Features in Java SE: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: Security Features in Java SE: Table of Contents
Security Features Overview
Quick Tour of Controlling Applets
Observe Applet Restrictions
Set up a Policy File to Grant the Required Permission
Start Policy Tool
Grant the Required Permission
Save the Policy File
See the Policy File Effects
Quick Tour of Controlling Applications
Observe Application Freedom
See How to Restrict Applications
Set up the Policy File to Grant the Required Permissions
Open the Policy File
Grant the Required Permissions
Save the Policy File
See the Policy File Effects
API and Tools Use for Secure Code and File Exchanges
Signing Code and Granting It Permissions
Steps for the Code Signer
Download and Try the Sample Application
Create a JAR File Containing the Class File
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Code Receiver
Observe the Restricted Application
Import the Certificate as a Trusted Certificate
Set Up a Policy File to Grant the Required Permission
Start Policy Tool
Specify the Keystore
Add a Policy Entry with a SignedBy Alias
Save the Policy File
See the Policy File Effects
Exchanging Files
Steps for the Contract Sender
Create a JAR File Containing the Contract
Generate Keys
Sign the JAR File
Export the Public Key Certificate
Steps for the Contract Receiver
Import the Certificate as a Trusted Certificate
Verify the JAR File Signature
Generating and Verifying Signatures
Generating a Digital Signature
Prepare Initial Program Structure
Generate Public and Private Keys
Sign the Data
Save the Signature and the Public Key in Files
Compile and Run the Program
Verifying a Digital Signature
Prepare Initial Program Structure
Input and Convert the Encoded Public Key Bytes
Input the Signature Bytes
Verify the Signature
Compile and Run the Program
Weaknesses and Alternatives
Implementing Your Own Permission
TerrysGame
The HighScore Class
The HighScorePermission Class
A Sample Policy File
Putting It All Together
Steps for the HighScore Developer (Chris)
Steps for the TerrysGame Developer (Terry)
Steps for a User Running TerrysGame (Kim)
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


  • Prioritized List of Improvements
  • Highlights of User Feedback

Name of Reviewer: | Ray Ortigas
Current Trail Author(s): | Mary Dageforde
Was the author contacted? | No If yes, Date:
Comments: It appears that there is no unified method for signing applets and deploying them on the two major browsers. Netscape uses JAR files, while IE uses CAB files. It may be a while...

Prioritized List of Improvements/Corrections:

 Priority Scale:
(1-5)
1 = immediate attention required
3 = fix in next public push (2-3 weeks)
5 = when you get a chance...
  1. Recommendation1
    description
    priority (1-5):

  2. Recommendation2
    description
    priority (1-5):

  3. Recommendation3
    description
    priority (1-5):

  4. Recommendation4
    description
    priority (1-5):

Highlights of User Feedback:

  • Date:
    User1's email

  • Date:
    User2's email

  • Date:
    User3's email

  • Date:
    User4's email


Java Security Example: Writing Files

Here's an applet that tries to write to the file named "writetest".

Here's the source.

This applet won't work unless you've configured your policy to allow it to write such a file; if not, you will see an AccessControlException. If you've configured your system to allow applets from this applets' location to write the specified file, check your current directory! You'll find a file there named "writetest".


Sound: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
Sound: End of Trail
You've reached the end of the "Sound" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

Internationalization: If your program is using sound and is being used by people all over the world, the sounds used by your program should be internationalized.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Providing MIDI Services


Trail: Sound: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: Sound: Table of Contents
Overview of the Sampled Package
Accessing Audio System Resources
Playing Back Audio
Capturing Audio
Processing Audio with Controls
Using Files and Format Converters
Overview of the MIDI Package
Accessing MIDI System Resources
Transmitting and Receiving MIDI Messages
Introduction to Sequencers
Using Sequencer Methods
Using Advanced Sequencer Features
Synthesizing Sound
Introduction to the Service Provider Interfaces
Providing Sampled-Audio Services
Providing MIDI Services
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


  • Prioritized List of Improvements
  • Highlights of User Feedback

Name of Reviewer: | Ray Ortigas
Current Trail Author(s): | Deborah Adair
Was the author contacted? | No If yes, Date:
Comments: Update to include JMF?

Prioritized List of Improvements/Corrections:

 Priority Scale:
(1-5)
1 = immediate attention required
3 = fix in next public push (2-3 weeks)
5 = when you get a chance...
  1. Recommendation1
    description
    priority (1-5):

  2. Recommendation2
    description
    priority (1-5):

  3. Recommendation3
    description
    priority (1-5):

  4. Recommendation4
    description
    priority (1-5):

Highlights of User Feedback:

  • Date:
    User1's email

  • Date:
    User2's email

  • Date:
    User3's email

  • Date:
    User4's email


Graphical User Interfaces: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
Graphical User Interfaces: End of Trail
You've reached the end of the "Graphical User Interfaces" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

Creating a GUI with JFC/Swing: Learn how to create graphical user interfaces for applications and applets, using Swing components.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Graphical User Interfaces


Trail: Graphical User Interfaces: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: Graphical User Interfaces: Table of Contents
A Brief Introduction to the Swing Package
What is Swing?
A Swing Demo
Swing Features
A Visual Guide to Swing Components (Java Look and Feel)
A Visual Guide to Swing Components (Windows Look and Feel)
Pluggable Look and Feel
Data Transfer
Internationalization and Localization
Accessibility
Integrating with the Desktop
System Tray Icon Support
Questions and Exercises: Graphical User Interfaces
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Answers to Questions and Exercises: Graphical User Interfaces (The Java™ Tutorials > Graphical User Interfaces > Swing Features)

Trail: Graphical User Interfaces
Lesson: Swing Features
Home Page > Graphical User Interfaces > Swing Features
« Previous • TOC
Answers to Questions and Exercises: Graphical User Interfaces

Questions

1. Does Swing support multiple look and feels?
Yes. Sun provides implementations for the GTK+ look and feel, Windows look and feel, CDE/Motif look and feel, Synth (a customizable look and feel), and two variants of the Java look and feel.

2. True or False: The Java look and feel is the only look and feel that works across all platforms.

True. The Java look and feel (also called Metal) comes in two themes. Previous to the 5.0 release, the theme was called Steel. The theme for 5.0 and beyond, is called Ocean.

3. True or False: Swing's Undo Framework supports an unlimited number of actions to undo (and redo).

True. Undo support is built-in to Swing's text component and can be added to other components.

4. Can Swing's list component (JList) only display text?

No, as the demo illustrated you can display anything you want in a JList, including rich graphics.

5. Which Swing component provides undo support out of the box?

Swing's text components.

6. Can Java applications interact with the native desktop? components.

Certainly, the Desktop API allows you to open up the browser and various other services and the TrayIcon API allows you to put a Swing component into the desktop tray.

7. Can I deploy my Swing application on the web?

Certainly. You can use either Java Web Start or Java Plugin.
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Graphical User Interfaces


Creating a GUI with JFC/Swing: End of Trail (The Java™ Tutorials)

Home
« Previous • Trail
Creating a GUI with JFC/Swing: End of Trail
You've reached the end of the "Creating a GUI with JFC/Swing" trail.

If you have comments or suggestions about this trail, use our feedback page to tell us about it.

What next?

Once you've caught your breath, you have several choices of where to go next. You can go to the front page to see all of your choices, or you can go directly to one of the following related trails:

Writing Applets: This is the starting point for learning everything about writing applets.

Essential Java Classes: By taking this trail, you can find out about strings, exceptions, threads, and other Java features that are used in all kinds of Java programs.

2D Graphics: If you are using JDK 1,2, you can use 2D graphics when writing Swing components that do custom painting.

Sound: You can use sound to enhance your program's user interface.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Solving Common Painting Problems


Trail: Creating a GUI with JFC/Swing: Examples (The Java™ Tutorials)

Home Page
« Previous • Trail • Next »
Trail: Creating a GUI with JFC/Swing: Examples

The following list has links to the examples indexes for every lesson in this trail. The indexes have links to the files required for each example, as well as to where each example is discussed. The indexes also let you run the examples using Java™ Web Start. If you want to download all the examples at once, you can get them by downloading the Tutorial Examples bundle.

  • Getting Started with Swing
  • Learning Swing by Example
  • Using Swing Components
  • Concurrency in Swing
  • Modifying the Look and Feel
  • Using Other Swing Features
  • Laying Out Components Within a Container
  • Using Drag and Drop and Data Transfer
  • Writing Event Listeners
  • Performing Custom Painting

The examples listed in each examples index compile and run under Java SE release 6.

« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Trail: Creating a GUI with JFC/Swing: Table of Contents (The Java™ Tutorials)

Home Page
« Previous
Trail: Creating a GUI with JFC/Swing: Table of Contents
Getting Started with Swing
About the JFC and Swing
Compiling and Running Swing Programs
Learning Swing with the NetBeans IDE
Setting up the CelsiusConverter Project
NetBeans IDE Basics
Creating the CelsiusConverter GUI
Adjusting the CelsiusConverter GUI
Adding the Application Logic
Questions and Exercises: Learning Swing with the NetBeans IDE
Using Swing Components
Using Top-Level Containers
The JComponent Class
Using Text Components
Text Component Features
The Text Component API
How to Use Various Components
How to Make Applets
How to Use Buttons, Check Boxes, and Radio Buttons
How to Use the ButtonGroup Component
How to Use Color Choosers
How to Use Combo Boxes
How to Make Dialogs
How to Use Editor Panes and Text Panes
How to Use File Choosers
How to Use Formatted Text Fields
How to Make Frames (Main Windows)
How to Use Internal Frames
How to Use Labels
How to Use Layered Panes
How to Use Lists
How to Use Menus
How to Use Panels
How to Use Password Fields
How to Use Progress Bars
How to Use Root Panes
How to Use Scroll Panes
How to Use Separators
How to Use Sliders
How to Use Spinners
How to Use Split Panes
How to Use Tabbed Panes
How to Use Tables
How to Use Text Areas
How to Use Text Fields
How to Use Tool Bars
How to Use Tool Tips
How to Use Trees
How to Use HTML in Swing Components
How to Use Models
How to Use Icons
How to Use Borders
Solving Common Component Problems
Questions and Exercises: Using Swing Components
Concurrency in Swing
Initial Threads
The Event Dispatch Thread
Worker Threads and SwingWorker
Simple Background Tasks
Tasks that Have Interim Results
Canceling Background Tasks
Bound Properties and Status Methods
Questions and Exercises: Concurrency in Swing
Using Other Swing Features
How to Integrate with the Desktop Class
How to Use Actions
How to Use Swing Timers
How to Support Assistive Technologies
How to Use the Focus Subsystem
How to Use Key Bindings
How to Use Modality in Dialogs
How to Print Tables
How to Print Text
How to Create a Splash Screen
How to Use the System Tray
Solving Common Problems Using Other Swing Features
Laying Out Components Within a Container
A Visual Guide to Layout Managers
Using Layout Managers
How Layout Management Works
How to Use Various Layout Managers
How to Use BorderLayout
How to Use BoxLayout
How to Use CardLayout
How to Use FlowLayout
How to Use GridBagLayout
How to Use GridLayout
How to Use GroupLayout
A GroupLayout Example
How to Use SpringLayout
Creating a Custom Layout Manager
Doing Without a Layout Manager (Absolute Positioning)
Solving Common Layout Problems
Questions and Exercises: Laying Out Components within a Container
Modifying the Look and Feel
How to Set the Look and Feel
The Synth Look and Feel
A Synth Example
Drag and Drop and Data Transfer
Introduction to DnD
Default DnD Support
Demo - BasicDnD
TransferHandler Class
Export Methods
Import Methods
TransferSupport Class
Setting the Drop Mode
Demo - DropDemo
Choosing the Drop Action
Demo - ChooseDropAction
Showing the Drop Location
Location Sensitive Drop
Demo - LocationSensitiveDemo
Empty Table Drop
Drop Location Rendering
Top-Level Drop
Adding Cut, Copy and Paste (CCP)
CCP in a Text Component
CCP in a non-Text Component
Using and Creating a DataFlavor
Putting it All Together - DnD and CCP
Further Information
Solving Common Data Transfer Problems
Writing Event Listeners
Introduction to Event Listeners
General Information about Writing Event Listeners
Listeners Supported by Swing Components
Implementing Listeners for Commonly Handled Events
How to Write an Action Listener
How to Write a Caret Listener
How to Write a Change Listener
How to Write a Component Listener
How to Write a Container Listener
How to Write a Document Listener
How to Write a Focus Listener
How to Write an Internal Frame Listener
How to Write an Item Listener
How to Write a Key Listener
How to Write a List Data Listener
How to Write a List Selection Listener
How to Write a Mouse Listener
How to Write a Mouse-Motion Listener
How to Write a Mouse-Wheel Listener
How to Write a Property Change Listener
How to Write a Table Model Listener
How to Write a Tree Expansion Listener
How to Write a Tree Model Listener
How to Write a Tree Selection Listener
How to Write a Tree-Will-Expand Listener
How to Write an Undoable Edit Listener
How to Write Window Listeners
Listener API Table
Solving Common Event-Handling Problems
Questions and Exercises: Writing Event Listeners
Performing Custom Painting
Creating the Demo Application (Step 1)
Creating the Demo Application (Step 2)
Creating the Demo Application (Step 3)
Refining the Design
A Closer Look at the Paint Mechanism
Summary
Solving Common Painting Problems
« Previous
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Using Swing Components: Examples (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Swing Components)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Swing Components
Home Page > Creating a GUI with JFC/Swing > Using Swing Components
« Previous • Trail • Next »
Using Swing Components: Examples
The table that follows lists every example in the Using Swing Components lesson, with links to required files and to where each example is discussed. The first column of the table has links to JNLP files that let you run the examples using JavaTM Web Start.

NOTE: Release 6.0 is required to run all applets and Java Web Start examples. Most examples will run on an earlier release but you must compile and run them locally.

To run an example using Java Web Start, click the [Launch] link in the first column of the table. The first time you run an example, there will be a delay while Java Web Start downloads the JAR file containing the class files for this lesson's examples. Afterward, the examples should execute more quickly.

Compiling and Running the Examples Locally

The second column in the table below has links to zip files for each demo that you can open and run in the NetBeans IDE. Refer to Running Tutorial Examples in NetBeans IDE for more information.

You can get all of the source, image, and other files required for all these examples by downloading the Swing Tutorial Examples bundle, which contains the files in the correct hierarchy.

If you download an individual example, take care to have all the necessary files in the proper hierarchy when you compile and run it. All of the examples in the Swing tutorial are placed in a package. For example, the components examples are placed in a components package. See the following image for the complete structure. Note that any examples using images expect their image files to be in a directory named images that's in the same directory as the example's src files. Here is a typical setup:

ButtonDemo's Directory structure

You can find out which files each example needs by consulting the following table or by looking at the comments at the beginning of each source file.

Table of Examples

Example | Zip File (contains all files necessary for the example plus NetBeans IDE project metadata) | Source Files (first file has the main method, except for examples that run only as applets) | Image and Other Files | Where Described
BorderDemo [Launch] | Border Demo Project | BorderDemo.java | wavy.gif | How to Use Borders
ButtonDemo [Launch] | Button Demo Project | ButtonDemo.java | right.gif, middle.gif, left.gif | How to Use Buttons, ...
ButtonHtmlDemo [Launch] | Button Html Demo Project | ButtonHtmlDemo.java | right.gif, middle.gif, left.gif | How to Use Buttons, ...
CheckBoxDemo [Launch] | Check Box Demo Project | CheckBoxDemo.java | All of the images in the images/geek directory. | How to Use Buttons, ...
ColorChooserDemo [Launch] | Color Chooser Demo Project | ColorChooserDemo.java |  | How to Use Color Choosers
ColorChooserDemo2 [Launch] | Color Chooser 2 Demo Project | ColorChooserDemo2.java CrayonPanel.java | red.gif, yellow.gif, green.gif, blue.gif | How to Use Color Choosers
ComboBoxDemo [Launch] | Combo Box Demo Project | ComboBoxDemo.java | Bird.gif, Cat.gif, Dog.gif, Rabbit.gif, Pig.gif | How to Use Combo Boxes
ComboBoxDemo2 [Launch] | Combo Box 2 Demo Project | ComboBoxDemo2.java |  | How to Use Combo Boxes
Converter [Launch] | Converter Project | Converter.java ConversionPanel.java ConverterRangeModel.java FollowerRangeModel.java Unit.java |  | How to Use Panels; Using Models
CustomComboBoxDemo [Launch] | Custom Combo Box Demo Project | CustomComboBoxDemo.java | Bird.gif, Cat.gif, Dog.gif, Rabbit.gif, Pig.gif | How to Use Combo Boxes
CustomIconDemo [Launch] | Custom Icon Demo Project | CustomIconDemo.java ArrowIcon.java | middle.gif | How to Use Icons
DialogDemo [Launch] | Dialog Demo Project | DialogDemo.java CustomDialog.java | middle.gif | How to Use Dialogs
DynamicTreeDemo [Launch] | Dynamic Tree Demo Project | DynamicTreeDemo.java DynamicTree.java |  | How to Use Trees
FileChooserDemo * | File Chooser Demo Project | FileChooserDemo.java | Open16.gif, Save16.gif | How to Use File Choosers
FileChooserDemo2 * | File Chooser 2 Demo Project | FileChooserDemo2.java ImageFileView.java ImageFilter.java ImagePreview.java Utils.java | jpgIcon.gif, gifIcon.gif, tiffIcon.gif, pngIcon.png | How to Use File Choosers
FormattedTextFieldDemo [Launch] | Formatted Text Field Demo Project | FormattedTextFieldDemo.java |  | How to Use Formatted Text Fields
FormatterFactoryDemo [Launch] | Formatter Factory Demo Project | FormatterFactoryDemo.java |  | How to Use Formatted Text Fields
FrameDemo [Launch] | Frame Demo Project | FrameDemo.java |  | How to Make Frames
FrameDemo2 [Launch] | Frame 2 Demo Project | FrameDemo2.java | FD.jpg | How to Make Frames
Framework [Launch] | Framework Project | Framework.java |  | Nowhere
GenealogyExample [Launch] | Genealogy Example Project | GenealogyExample.java GenealogyModel.java GenealogyTree.java Person.java |  | How to Use Trees
GlassPaneDemo [Launch] | Glass Pane Demo Project | GlassPaneDemo.java |  | How to Use Root Panes
HtmlDemo [Launch] | Html Demo Project | HtmlDemo.java |  | Using HTML in Swing Components
IconDemo [Launch] | Icon Demo Project | IconDemoApp.java | sunw01.jpg, sunw02.jpg, sunw03.jpg, sunw04.jpg, sunw05.jpg | How to Use Icons
InternalFrameDemo [Launch] | Internal Frame Demo Project | InternalFrameDemo.java MyInternalFrame.java |  | How to Use Internal Frames
JWSFileChooserDemo [Launch] | JWS File Chooser Demo Project | JWSFileChooserDemo.java | Open16.gif, Save16.gif | How to Use File Choosers
LabelDemo [Launch] | Label Demo Project | LabelDemo.java | middle.gif | How to Use Labels
LayeredPaneDemo [Launch] | Layered Pane Demo Project | LayeredPaneDemo.java | dukeWaveRed.gif | How to Use Layered Panes
LayeredPaneDemo2 [Launch] | Layered Pane 2 Demo Project | LayeredPaneDemo2.java | dukeWaveRed.gif | How to Use Layered Panes
ListDemo [Launch] | List Demo Project | ListDemo.java |  | How to Use Lists
ListDialogRunner [Launch] | List Dialog Runner Project | ListDialogRunner.java ListDialog.java |  | How to Use Buttons, ...
MenuDemo [Launch] | Menu Demo Project | MenuDemo.java | middle.gif | How to Use Menus
MenuGlueDemo [Launch] | Menu Glue Demo Project | MenuGlueDemo.java |  | How to Use Menus
MenuLayoutDemo [Launch] | Menu Layout Demo Project | MenuLayoutDemo.java |  | How to Use Menus
MenuLookDemo [Launch] | Menu Look Demo Project | MenuLookDemo.java | middle.gif | How to Use Menus
MenuSelectionManagerDemo [Launch] | Menu Selection Manager Demo Project | MenuSelectionManagerDemo.java | middle.gif | How to Use Menus
PasswordDemo [Launch] | Password Demo Project | PasswordDemo.java |  | How to Use Password Fields
PopupMenuDemo [Launch] | Popup Menu Demo Project | PopupMenuDemo.java | middle.gif | How to Use Menus
ProgressBarDemo [Launch] | Progress Bar Demo Project | ProgressBarDemo.java |  | How to Monitor Progress
ProgressBarDemo2 [Launch] | Progress Bar 2 Demo Project | ProgressBarDemo2.java |  | How to Monitor Progress
ProgressMonitorDemo [Launch] | Progress Monitor Demo Project | ProgressMonitorDemo.java |  | How to Monitor Progress
RadioButtonDemo [Launch] | Radio Button Demo Project | RadioButtonDemo.java | Bird.gif, Cat.gif, Dog.gif, Rabbit.gif, Pig.gif | How to Use Buttons, ...
RootLayeredPaneDemo [Launch] | Root Layered Pane Demo Project | RootLayeredPaneDemo.java | dukeWaveRed.gif | How to Use Root Panes
ScrollDemo [Launch] | Scroll Demo Project | ScrollDemo.java Rule.java Corner.java ScrollablePicture.java | youngdad.jpeg | How to Use Scroll Panes
ScrollDemo2 [Launch] | Scroll 2 Demo Project | ScrollDemo2.java |  | How to Use Scroll Panes
SharedModelDemo [Launch] | Shared Model Demo Project | SharedModelDemo.java |  | Using Models
SimpleTableDemo [Launch] | Simple Table Demo Project | SimpleTableDemo.java |  | How to Use Tables
SimpleTableSelectionDemo [Launch] | Simple Table Selection Demo Project | SimpleTableSelectionDemo.java |  | How to Use Tables
SliderDemo [Launch] | Slider Demo Project | SliderDemo.java | All of the images in the images/doggy directory. | How to Use Sliders
SliderDemo2 [Launch] | Slider 2 Demo Project | SliderDemo2.java | All of the images in the images/doggy directory. | How to Use Sliders
SpinnerDemo [Launch] | Spinner Demo Project | SpinnerDemo.java SpringUtilities.java CyclingSpinnerListModel.java |  | How to Use Spinners
SpinnerDemo2 [Launch] | Spinner 2 Demo Project | SpinnerDemo2.java SpinnerDemo.java SpringUtilities.java CyclingSpinnerListModel.java |  | How to Use Spinners
SpinnerDemo3 [Launch] | Spinner Demo 3 Project | SpinnerDemo3.java SpringUtilities.java CyclingSpinnerListModel.java |  | How to Use Spinners
SpinnerDemo4 [Launch] | Spinner Demo 4 Project | SpinnerDemo4.java SpringUtilities.java |  | How to Use Spinners
SplitPaneDemo [Launch] | Split Pane Demo Project | SplitPaneDemo.java | image files | How to Use Split Panes
SplitPaneDemo2 [Launch] | Split Pane 2 Demo Project | SplitPaneDemo2.java | image files | How to Use Split Panes
SplitPaneDividerDemo [Launch] | Split Pane Divider Demo Project | SplitPaneDividerDemo.java SizeDisplayer.java | Cat.gif, Dog.gif | How to Use Split Panes
TabbedPaneDemo [Launch] | Tabbed Pane Demo Project | TabbedPaneDemo.java | middle.gif | How to Use Tabbed Panes
TabComponentsDemo [Launch] | Tab Components Demo Project | TabComponentsDemo.java ButtonTabComponent.java |  | How to Use Tabbed Panes
TableDemo [Launch] | Table Demo Project | TableDemo.java |  | How to Use Tables
TableDialogEditDemo [Launch] | Table Dialog Edit Demo Project | TableDialogEditDemo.java ColorEditor.java ColorRenderer.java |  | How to Use Tables
TableFTFEditDemo [Launch] | Table FTF Edit Demo Project | TableFTFEditDemo.java IntegerEditor.java |  | How to Use Tables
TableFilterDemo [Launch] | Table Filter Demo Project | TableFilterDemo.java SpringUtilities.java |  | How to Use Tables
TablePrintDemo [Launch] | Table Print Demo Project | TablePrintDemo.java |  | How to Use Tables
TableRenderDemo [Launch] | Table Render Demo Project | TableRenderDemo.java |  | How to Use Tables
TableSelectionDemo [Launch] | Table Selection Demo Project | TableSelectionDemo.java |  | How to Use Tables
TableSortDemo [Launch] | Table Sort Demo Project | TableSortDemo.java |  | How to Use Tables
TableToolTipsDemo [Launch] | Table Tool Tips Demo Project | TableToolTipsDemo.java |  | How to Use Tables
TextAreaDemo [Launch] | Text Area Demo Project | TextAreaDemo.java |  | How to Use Text Areas
TextComponentDemo [Launch] | Text Component Demo Project | TextComponentDemo.java DocumentSizeFilter.java |  | Text Component Features
TextDemo [Launch] | Text Demo Project | TextDemo.java |  | How to Use Text Fields and How to Use Text Areas
TextFieldDemo [Launch] | Text Field Demo Project | TextFieldDemo.java | content.txt | How to Use Text Fields
TextInputDemo [Launch] | Text Input Demo Project | TextInputDemo.java SpringUtilities.java |  | How to Use Formatted Text Fields
TextSamplerDemo [Launch] | Text Sampler Demo Project | TextSamplerDemo.java | Pig.gif, sound.gif, dukeWaveRed.gif, TextSamplerDemoHelp.html | Using Text Components and How to Use Editor Panes and Text Panes
ToolBarDemo [Launch] | Tool Bar Demo Project | ToolBarDemo.java | Back24.gif, Forward24.gif, Up24.gif | How to Use Tool Bars
ToolBarDemo2 [Launch] | Tool Bar 2 Demo Project | ToolBarDemo2.java | Back24.gif, Forward24.gif, Up24.gif | How to Use Tool Bars
TopLevelDemo [Launch] | Top Level Demo Project | TopLevelDemo.java |  | Using Top-Level Containers
TreeDemo [Launch] | Tree Demo Project | TreeDemo.java | Several html files. | How to Use Trees
TreeIconDemo [Launch] | Tree Icon Demo Project | TreeIconDemo.java | middle.gif and several html files. | How to Use Trees
TreeIconDemo2 [Launch] | Tree Icon 2 Demo Project | TreeIconDemo2.java | middle.gif and several html files. | How to Use Trees
TumbleItem | Tumble Item Project | TumbleItem.java (an applet) | All of the images in the images/tumble directory. | How to Make Applets
* This application is not currently available with Java Web Start because we distribute only unsigned JAR files. To run it, download and compile it, and then run it as an application.

Geek Images

geek-----.gif, geek-c---.gif, geek--g--.gif, geek---h-.gif,
geek----t.gif, geek-cg--.gif, geek-c-h-.gif, geek-c--t.gif,
geek--gh-.gif, geek--g-t.gif, geek---h-.gif, geek-cg-t.gif,
geek-cgh-.gif, geek-c-ht.gif, geek--ght.gif, geek-cght.gif

Doggy Images

T0.gif, T1.gif, T2.gif, T3.gif, T4.gif, T5.gif, T6.gif,
T7.gif, T8.gif, T9.gif, T10.gif, T11.gif, T12.gif, T13.gif

Tumble Images

T1.gif, T2.gif, T3.gif, T4.gif, T5.gif,
T6.gif, T7.gif, T8.gif, T9.gif, T10.gif,
T11.gif, T12.gif, T13.gif, T14.gif, T15.gif,
T16.gif, T17.gif

Images used in SplitPaneDemo and SplitPaneDemo2

Bird.gif, Cat.gif, Dog.gif, Rabbit.gif, Pig.gif, dukeWaveRed.gif, kathyCosmo.gif, lainesTongue.gif, left.gif, middle.gif, right.gif, stickerface.gif

HTML Files Required for Tree Demos

TreeDemoHelp.html
arnold.html
bloch.html
chanlee.html
jls.html
swingtutorial.html
tutorial.html
tutorialcont.html
vm.html
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


ALICE'S ADVENTURES IN WONDERLAND
by Lewis Carroll

CHAPTER I
DOWN THE RABBIT-HOLE
ALICE was beginning to get very tired of sitting by her sister on the bank and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, "and what is the use of a book," thought Alice, "without pictures or conversations?"

So she was considering, in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.

There was nothing so very remarkable in that; nor did Alice think it so very much out of the way to hear the Rabbit say to itself "Oh dear! Oh dear! I shall be too late!" (when she thought it over afterwards it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but, when the Rabbit actually took a watch out of its waistcoat-pocket, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and was just in time to see it pop down a large rabbit-hole under the hedge.

In another moment down went Alice after it, never once considering how in the world she was to get out again.

The rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly that Alice had not a moment to think about stopping herself before she found herself falling down what seemed to be a very deep well.

Either the well was very deep, or she fell very slowly, for she had plenty of time as she went down to look about her, and to wonder what was going to happen next. First, she tried to look down and make out what she was coming to, but it was too dark to see anything: then she looked at the sides of the well, and noticed that they were filled with cupboards and book-shelves: here and there she saw maps and pictures hung upon pegs. She took down ajar from one of the shelves as she passed: it was labeled "ORANGE MARMALADE" but to her great disappointment it was empty: she did not like to drop the jar, for fear of killing somebody underneath, so managed to put it into one of the cupboards as she fell past it.

"Well!" thought Alice to herself "After such a fall as this, I shall think nothing of tumbling down-stairs! How brave they'll all think me at home! Why, I wouldn't say anything about it, even if I fell off the top of the house!" (which was very likely true.)

Down, down, down. Would the fall never come to an end? "I wonder how many miles I've fallen by this time?" she said aloud. "I must be getting somewhere near the centre of the earth. Let me see: that would be four thousand miles down, I think-" (for, you see, Alice had learnt several things of this sort in her lessons in the school-room, and though this was not a very good opportunity for showing off her knowledge, as there was no one to listen to her, still it was good practice to say it over) "-- yes that's about the right distance -- but then I wonder what Latitude or Longitude I've got to?" (Alice had not the slightest idea what Latitude was, or Longitude either, but she thought they were nice grand words to say.)

Presently she began again. "I wonder if I shall fall fight through the earth! How funny it'll seem to come out among the people that walk with their heads downwards! The antipathies, I think-" (she was rather glad there was no one listening, this time, as it didn't sound at all the right word) "-but I shall have to ask them what the name of the country is, you know. Please, Ma'am, is this New Zealand? Or Australia?" (and she tried to curtsey as she spoke- fancy, curtseying as you're falling through the air! Do you think you could manage it?) "And what an ignorant little girl she'll think me for asking! No, it'll never do to ask: perhaps I shall see it written up somewhere."

Down, down, down. There was nothing else to do, so Alice soon began talking again. "Dinah'll miss me very much to-night, I should think!" (Dinah was the cat.) "I hope they'll remember her saucer of milk at tea-time. Dinah, my dear! I wish you were down here with me! There are no mice in the air, I'm afraid, but you might catch a bat, and that's very like a mouse, you know. But do cats eat bats, I wonder?" And here Alice began to get rather sleepy, and went on saying to herself, in a dreamy son of way, "Do cats eat bats? Do cats eat bats?" and sometimes "Do bats eat cats?" for, you see, as she couldn't answer either question, it didn't much matter which way she put it. She felt that she was dozing off, and had just begun to dream that she was walking hand in hand with Dinah, and was saying to her, very earnestly, "Now, Dinah, tell me the truth: did you ever eat a bat?" when suddenly, thump! thump! down she came upon a heap of sticks and dry leaves, and the fall was over.

Alice was not a bit hurt, and she jumped up on to her feet in a moment: she looked up, but it was all dark overhead: before her was another long passage, and the White Rabbit was still in sight, hurrying down it. There was not a moment to be lost: away went Alice like the wind, and was just in time to hear it say, as it turned a comer, "Oh my ears and whiskers, how late it's getting!" She was close behind it when she turned the comer, but the Rabbit was no longer to be seen: she found herself in a long, low hall, which was lit up by a row of lamps hanging from the roof.

There were doors all round the hall, but they were all locked; and when Alice had been all the way down one side and up the other, trying every door, she walked sadly down the middle, wondering how she was ever to get out again.

Suddenly she came upon a little three-legged table, all made of solid glass: there was nothing on it but a tiny golden key, and Alice's first idea was that this might belong to one of the doors of the hall; but, alas! either the locks were too large, or the key was too small, but at any rate it would not open any of them. However, on the second time round, she came upon a low curtain she had not noticed before, and behind it was a little door about fifteen inches high: she tried the little golden key in the lock, and to her great delight it fitted!

Alice opened the door and found that it led into a small passage, not much larger than a rat-hole: she knelt down and looked along the passage into the loveliest garden you ever saw. How she longed to get out of that dark hall, and wander about among those beds of bright flowers and those cool fountains, but she could not even get her head through the doorway; "and even if my head would go through," thought poor Alice, "it would be of very little use without my shoulders. Oh, how I wish I could shut up like a telescope! I think I could, if I only knew how to begin." For, you see, so many out-of-the- way things had happened lately, that Alice had begun to think that very few things indeed were really impossible.

There seemed to be no use in waiting by the little door, so she went back to the table, half hoping she might find another key on it, or at any rate a book of rules for shutting people up like telescopes: this time she found a little bottle on it, ("which certainly was not here before," said Alice), and tied round the neck of the bottle was a paper label, with the words "DRINK ME" beautifully printed on it in large letters.It was all very well to say "Drink me," but the wise little Alice was not going to do that in a hurry. "No, I'll look first," she said, "and see whether it's marked 'poison' or not"; for she had read several nice little stories about children who had got burnt, and eaten up by wild beasts, and other unpleasant things, all because they would not remember the simple rules their friends had taught them: such as, that a red-hot poker will burn you if you hold it too long; and that, if you cut your finger very deeply with a knife, it usually bleeds; and she had never forgotten that, if you drink much from a bottle marked "poison," it is almost certain to disagree with you, sooner or later.However, this bottle was not marked "poison," so Alice ventured to taste it, and, finding it very nice (it had, in fact, a sort of mixed flavour of cherry-tart, custard, pine-apple, roast turkey, toffy, and hot buttered toast), she very soon finished it off.

"What a curious feeling!" said Alice. "I must be shutting up like a telescope!"

And so it was indeed: she was now only ten inches high, and her face brightened up at the thought that she was now the right size for going through the little door into that lovely garden. First, however, she waited for a few minutes to see if she was going to shrink any further: she felt a little nervous about this; "for it might end, you know," said Alice to herself; "in my going out altogether, like a candle. I wonder what I should be like then?" And she tried to fancy what the flame of a candle looks like after the candle is blown out, for she could not remember ever having seen such a thing.

After a while, finding that nothing more happened, she decided on going into the garden at once; but, alas for poor Alice! when she got to the door, she found she had forgotten the little golden key, and when she went back to the table for it, she found she could not possibly reach it: she could see it quite plainly through the glass, and she tried her best to climb up one of the legs of the table, but it was too slippery; and when she had tired herself out with trying, the poor little thing sat down and cried.

"Come, there's no use in crying like that!" said Alice to herself rather sharply. "I advise you to leave off this minute!" She generally gave herself very good advice (though she very seldom followed it), and sometimes she scolded herself so severely as to bring tears into her eyes; and once she remembered trying to box her own ears for having cheated herself in a game of croquet she was playing against herself, for this curious child was very fond of pretending to be two people. "But it's no use now," thought poor Alice, "to pretend to be two people! Why, there's hardly enough of me left to make one respectable person!"

Soon her eye fell on a little glass box that was lying under the table: she opened it, and found in it a very small cake, on which the words "EAT ME" were beautifully marked in currants. "Well, I'll eat it," said Alice, "and if it makes me grow larger, I can reach the key; and if it makes me grow smaller, I can creep under the door: so either way I'll get into the garden, and I don't care which happens!"

She ate a little bit, and said anxiously to herself "Which way? Which way?", holding her hand on the top of her head to feel which way it was growing; and she was quite surprised to find that she remained the same size. To be sure, this is what generally happens when one eats cake; but Alice had got so much into the way of expecting nothing but out-of-the-way things to happen, that it seemed quite dull and stupid for life to go on in the common way.

So she set to work, and very soon finished off the cake.


 This is an uneditable JEditorPane, which was initialized with HTML text from a URL.

An editor pane uses specialized editor kits to read, write, display, and edit text of different formats. The Swing text package includes editor kits for plain text, HTML, and RTF. You can also develop custom editor kits for other formats.


The Java Programming Language

blah, blah, blah, blah, blah...


Effective Java
Programming Language Guide

blah, blah, blah, blah, blah...


The Java Developers Almanac

blah, blah, blah, blah, blah...


The Java Language Specification

blah, blah, blah, blah, blah...


The JFC Swing Tutorial

This is the UI trail from the original Tutorial, updated and expanded to reflect the Swing components. More fun than a barrel full of monkeys! Much more fun than a root canal!


Tree Demo

This is the help file (TreeDemoHelp.html) for the tree demo. Selecting any branch node in the tree results in this file being displayed. When you select a leaf node (a book), this pane displays an HTML file for that book.

This demo uses a split pane to separate the tree and this HTML view. Drag the divider up or down to change the space distribution.


The Java Tutorial

The one, the only. Well, it hasn't been the only for quite a while now. This is the original Tutorial book. The third edition includes a chapter about Swing.


The Java Tutorial Continued

Latest version online only


The Java Virtual Machine Specification

blah, blah, blah, blah, blah...


Applet HTML Page

Generated by NetBeans IDE


Concurrency in Swing: Examples (The Java™ Tutorials > Creating a GUI with JFC/Swing > Concurrency in Swing)

Trail: Creating a GUI with JFC/Swing
Lesson: Concurrency in Swing
Home Page > Creating a GUI with JFC/Swing > Concurrency in Swing
« Previous • Trail • Next »
Concurrency in Swing: Examples
The table that follows lists every example in the Concurrency in Swing lesson, with links to required files and to where each example is discussed. The first column of the table has links to JNLP files that let you run the examples using JavaTM Web Start.

NOTE: Release 6.0 is required to run all applets and Java Web Start examples. Most examples will run on an earlier release but you must compile and run them locally.

To run an example using Java Web Start, click the [Launch] link in the first column of the table. The first time you run an example, there will be a delay while Java Web Start downloads the JAR file containing the class files for this lesson's examples. Afterward, the examples should execute more quickly.

Compiling and Running the Examples Locally

The second column in the table below has links to zip files for each demo that you can open and run in the NetBeans IDE. Refer to Running Tutorial Examples in NetBeans IDE for more information.

You can get all of the source, image, and other files required for all these examples by downloading the Swing Tutorial Examples bundle, which contains the files in the correct hierarchy.

If you download an individual example, take care to have all the necessary files in the proper hierarchy when you compile and run it. All of the examples in the Swing tutorial are placed in a package. For example, the components examples are placed in a components package. See the following image for the complete structure. Note that any examples using images expect their image files to be in a directory named images that's in the same directory as the example's src files.

You can find out which files each example needs by consulting the following table or by looking at the comments at the beginning of each source file.

Table of Examples

Example | Zip File (contains all files necessary for the example plus NetBeans IDE project metadata) | Source Files (first file has the main method, except for examples that run only as applets) | Image & Other Files | Where Described
Flipper [Launch] | Flipper Project | Flipper.java | None | Tasks that Return Interim Results
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Drag and Drop and Data Transfer: Examples (The Java™ Tutorials > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer)

Trail: Creating a GUI with JFC/Swing
Lesson: Drag and Drop and Data Transfer
Home Page > Creating a GUI with JFC/Swing > Drag and Drop and Data Transfer
« Previous • Trail • Next »
Drag and Drop and Data Transfer: Examples
The table that follows lists every example in the Drag and Drop and Data Transfer lesson, with links to required files and to where each example is discussed. The first column of the table has links to JNLP files that let you run the examples using JavaTM Web Start.

NOTE: Release 6.0 is required to run all applets and Java Web Start examples. Most examples will run on an earlier release but you must compile and run them locally.

To run an example using Java Web Start, click the [Launch] link in the first column of the table. The first time you run an example, there will be a delay while Java Web Start downloads the JAR file containing the class files for this lesson's examples. Afterward, the examples should execute more quickly.

Compiling and Running the Examples Locally

The second column in the table below has links to zip files for each demo that you can open and run in the NetBeans IDE. Refer to Running Tutorial Examples in NetBeans IDE for more information.

You can get all of the source, image, and other files required for all these examples by downloading the Swing Tutorial Examples bundle, which contains the files in the correct hierarchy.

If you download an individual example, take care to have all the necessary files in the proper hierarchy when you compile and run it. All of the examples in the Swing tutorial are placed in a package. For example, the components examples are placed in a components package. See the following image for the complete structure. Note that any examples using images expect their image files to be in a directory named images that's in the same directory as the example's src files.

You can find out which files each example needs by consulting the following table or by looking at the comments at the beginning of each source file.

Table of Examples

Example | Zip File (contains all files necessary for the example plus NetBeans IDE project metadata) | Source Files (first file has the main method, except for examples that run only as applets) | Image & Other Files | Where Described
BasicDnD [Launch] | Basic DnD Project | BasicDnD.java |  | Demo - BasicDnD
ChooseDropActionDemo [Launch] | Choose Drop Action Demo | ChooseDropActionDemo.java |  | Demo - ChooseDropAction
DropDemo [Launch] | Drop Demo Project | DropDemo.java ListTransferHandler.java |  | Demo - Drop List
FillViewportHeightDemo [Launch] | Fill Viewport Height Demo Project | FillViewportHeightDemo.java |  | Empty Table Drop
ListCutPaste [Launch] | List Cut Paste Project | ListCutPaste.java ListTransferHandler.java TransferActionListener.java |  | CCP in a non-Text Component
LocationSensitiveDemo [Launch] | Location Sensitive Demo Project | LocationSensitiveDemo.java |  | Demo - LocationSensitiveDemo
TextCutPaste [Launch] | Text Cut Paste Project | TextCutPaste.java TextTransferHandler.java |  | CCP in a Text Component
TopLevelTransferHandlerDemo | TopLevel TransferHandler Demo Project | TopLevelTransferHandlerDemo.java |  | Top-Level Drop
« Previous • TOC • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Beginning of Tutorial
Next page: End of Trail


Writing Event Listeners: Examples (The Java™ Tutorials > Creating a GUI with JFC/Swing > Writing Event Listeners)

Trail: Creating a GUI with JFC/Swing
Lesson: Writing Event Listeners
Home Page > Creating a GUI with JFC/Swing > Writing Event Listeners
« Previous • Trail • Next »
Writing Event Listeners: Examples
The table that follows lists every example in the Writing Event Listeners lesson, with links to required files and to where each example is discussed. The first column of the table has links to JNLP files that let you run the examples using JavaTM Web Start.

NOTE: Release 6.0 is required to run all applets and Java Web Start examples. Most examples will run on an earlier release but you must compile and run them locally.

To run an example using Java Web Start, click the [Launch] link in the first column of the table. The first time you run an example, there will be a delay while Java Web Start downloads the JAR file containing the class files for this lesson's examples. Afterward, the examples should execute more quickly.

Compiling and Running the Examples Locally

The second column in the table below has links to zip files for each demo that you can open and run in the NetBeans IDE. Refer to Running Tutorial Examples in NetBeans IDE for more information.

Example Zip File
(contains all files necessary for the example plus NetBeans IDE project metadata) 		Source Files (first file has the main method, except for examples that run only as applets) Image & Other Files Where Described
Beeper [Launch] Beeper Project Beeper.java Some Simple Event-Handling Examples
ComponentEventDemo [Launch] Component Event Demo Project ComponentEventDemo.java How to Write a Component Listener
ContainerEventDemo [Launch] Container Event Demo Project ContainerEventDemo.java How to Write a Container Listener
DocumentEventDemo [Launch] Document Event Demo Project DocumentEventDemo.java How to Write a Document Listener
FocusEventDemo [Launch] Focus Event Demo Project FocusEventDemo.java How to Write a Focus Listener
InternalFrameEventDemo [Launch] Internal Frame Event Demo Project InternalFrameEventDemo.java How to Write an Internal Frame Listener
KeyEventDemo [Launch] Key Event Demo Project KeyEventDemo.java How to Write a Key Listener
ListDataEventDemo [Launch] List Data Event Demo Project ListDataEventDemo.java jlfgr-1_0.jar How to Write a List Data Listener
ListSelectionDemo [Launch] List Selection Demo Project ListSelectionDemo.java How to Write a List Selection Listener
TableListSelectionDemo [Launch] Table List Selection Demo Project TableListSelectionDemo.java How to Write a List Selection Listener
MouseEventDemo [Launch] Mouse Event Demo Project MouseEventDemo.java
BlankArea.java 		How to Write a Mouse Listener
MouseMotionEventDemo [Launch] Mouse Motion Event Demo Project MouseMotionEventDemo.java
BlankArea.java 		How to Write a Mouse-Motion Listener
MouseWheelEventDemo [Launch] Mouse Wheel Event Demo Project MouseWheelEventDemo.java How to Write a Mouse-Wheel Listener
MultiListener [Launch] MultiListener Project MultiListener.java Some Simple Event-Handling Examples
TreeExpandEventDemo [Launch] Tree Expand Event Demo Project TreeExpandEventDemo.java How to Write a Tree Expansion Listener
TreeExpandEventDemo2 [Launch] Tree Expand Event 2 Demo Project TreeExpandEventDemo2.java How to Write a Tree Will Expand Listener
WindowEventDemo [Launch] Window Event Demo Project WindowEventDemo.java How to Write Window Listeners

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Laying Out Components Within a Container: Examples (The Java™ Tutorials > Creating a GUI with JFC/Swing > Laying Out Components Within a Container)

Trail: Creating a GUI with JFC/Swing
Lesson: Laying Out Components Within a Container
Home Page > Creating a GUI with JFC/Swing > Laying Out Components Within a Container
« Previous • Trail • Next »
Laying Out Components Within a Container: Examples
The table that follows lists every example in the Laying Out Components Within a Container lesson, with links to required files and to where each example is discussed. The first column of the table has links to JNLP files that let you run the examples using JavaTM Web Start.

NOTE: Release 6.0 is required to run all applets and Java Web Start examples. Most examples will run on an earlier release but you must compile and run them locally.

To run an example using Java Web Start, click the [Launch] link in the first column of the table. The first time you run an example, there will be a delay while Java Web Start downloads the JAR file containing the class files for this lesson's examples. Afterward, the examples should execute more quickly.

Compiling and Running the Examples Locally

The second column in the table below has links to zip files for each demo that you can open and run in the NetBeans IDE. Refer to Running Tutorial Examples in NetBeans IDE for more information.

You can get all of the source, image, and other files required for all these examples by downloading the Swing Tutorial Examples bundle, which contains the files in the correct hierarchy.

If you download an individual example, take care to have all the necessary files in the proper hierarchy when you compile and run it. All of the examples in the Swing tutorial are placed in a package. For example, the components examples are placed in a components package. See the following image for the complete structure. Note that any examples using images expect their image files to be in a directory named images that's in the same directory as the example's src files.

You can find out which files each example needs by consulting the following table or by looking at the comments at the beginning of each source file.

Table of Examples

Example | Zip File (contains all files necessary for the example plus NetBeans IDE project metadata) | Source Files (first file has the main method) | Image and Other Files | Where Described
AbsoluteLayoutDemo [Launch] | Absolute Layout Demo Project | AbsoluteLayoutDemo.java |  | Doing Without a Layout Manager
BorderLayoutDemo [Launch] | Border Layout Demo Project | BorderLayoutDemo.java |  | How to Use BorderLayout
BoxAlignmentDemo [Launch] | Box Alignment Demo Project | BoxAlignmentDemo.java | geek-cght.gif middle.gif | How to Use BoxLayout
BoxLayoutDemo [Launch] | Box Layout Demo Project | BoxLayoutDemo.java |  | How to Use BoxLayout
BoxLayoutDemo2 [Launch] | Box Layout Demo 2 Project | BoxLayoutDemo2.java |  | How to Use BoxLayout
CardLayoutDemo [Launch] | Card Layout Demo Project | CardLayoutDemo.java |  | How to Use CardLayout
CustomLayoutDemo [Launch] | Custom Layout Demo Project | CustomLayoutDemo.java |  | Creating a Custom Layout Manager
FlowLayoutDemo [Launch] | Flow Layout Demo Project | FlowLayoutDemo.java |  | How to Use FlowLayout
GridBagLayoutDemo [Launch] | Grid Bag Layout Demo Project | GridBagLayoutDemo.java |  | How to Use GridBagLayout
GridLayoutDemo [Launch] | Grid Layout Demo Project | GridLayoutDemo.java |  | How to Use GridLayout
SpringBox [Launch] | Spring Box Project | SpringBox.java SpringUtilities.java |  | How to Use SpringLayout
SpringCompactGrid [Launch] | Spring Compact Grid Project | SpringCompactGrid.java SpringUtilities.java |  | How to Use SpringLayout
SpringDemo1 * | Spring Demo 1 Project | SpringDemo1.java |  | How to Use SpringLayout
SpringDemo2 * | Spring Demo 2 Project | SpringDemo2.java |  | How to Use SpringLayout
SpringDemo3 [Launch] | Spring Demo 3 Project | SpringDemo3.java |  | How to Use SpringLayout
SpringDemo4 [Launch] | Spring Demo 4 Project | SpringDemo4.java |  | How to Use SpringLayout
SpringForm [Launch] | Spring Form Project | SpringForm.java SpringUtilities.java |  | How to Use SpringLayout
SpringGrid [Launch] | Spring Grid Project | SpringGrid.java SpringUtilities.java |  | How to Use SpringLayout
TabDemo [Launch] | Tab Demo Project | TabDemo.java |  | How to Use CardLayout
* SpringDemo1 and SpringDemo2 are intentionally broken, and we don't advise running them using Java Web Start.

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Learning Swing by Example: Examples (The Java™ Tutorials > Creating a GUI with JFC/Swing > Learning Swing by Example)

Trail: Creating a GUI with JFC/Swing
Lesson: Learning Swing by Example
Home Page > Creating a GUI with JFC/Swing > Learning Swing by Example
« Previous • Trail • Next »
Learning Swing by Example: Examples
The table that follows lists every example in the Learning Swing by Example lesson, with links to required files and to where each example is discussed. The first column of the table has links to JNLP files that let you run the examples using JavaTM Web Start.

NOTE: Release 6.0 is required to run all applets and Java Web Start examples. Most examples will run on an earlier release but you must compile and run them locally.

To run an example using Java Web Start, click the [Launch] link in the first column of the table. The first time you run an example, there will be a delay while Java Web Start downloads the JAR file containing the class files for this lesson's examples. Afterward, the examples should execute more quickly.

Compiling and Running the Examples Locally

The second column in the table below has links to zip files for each demo that you can open and run in the NetBeans IDE. Refer to Running Tutorial Examples in NetBeans IDE for more information.

You can get all of the source, image, and other files required for all these examples by downloading the Swing Tutorial Examples bundle, which contains the files in the correct hierarchy.

If you download an individual example, take care to have all the necessary files in the proper hierarchy when you compile and run it. All of the examples in the Swing tutorial are placed in a package. For example, the components examples are placed in a components package. See the following image for the complete structure. Note that any examples using images expect their image files to be in a directory named images that's in the same directory as the example's src files.

You can find out which files each example needs by consulting the following table or by looking at the comments at the beginning of each source file.

Table of Examples

Example Zip File
(contains all files necessary for the example plus NetBeans IDE project metadata) 		Source Files Image & Other Files Where Described
CelsiusConverter [Launch] CelsiusConverter Project CelsiusConverterGUI.java Setting up the CelsiusConverter Project
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Modifying the Look and Feel: Examples (The Java™ Tutorials > Creating a GUI with JFC/Swing > Modifying the Look and Feel)

Trail: Creating a GUI with JFC/Swing
Lesson: Modifying the Look and Feel
Home Page > Creating a GUI with JFC/Swing > Modifying the Look and Feel
« Previous • Trail • Next »
Modifying the Look and Feel: Examples
The table that follows lists every example in the Modifying the Look and Feel lesson, with links to required files and to where each example is discussed. The first column of the table has links to JNLP files that let you run the examples using JavaTM Web Start.

NOTE: Release 6.0 is required to run all applets and Java Web Start examples. Most examples will run on an earlier release but you must compile and run them locally.

To run an example using Java Web Start, click the [Launch] link in the first column of the table. The first time you run an example, there will be a delay while Java Web Start downloads the JAR file containing the class files for this lesson's examples. Afterward, the examples should execute more quickly.

Compiling and Running the Examples Locally

The second column in the table below has links to zip files for each demo that you can open and run in the NetBeans IDE. Refer to Running Tutorial Examples in NetBeans IDE for more information.

You can get all of the source, image, and other files required for all these examples by downloading the Swing Tutorial Examples bundle, which contains the files in the correct hierarchy.

If you download an individual example, take care to have all the necessary files in the proper hierarchy when you compile and run it. All of the examples in the Swing tutorial are placed in a package. For example, the components examples are placed in a components package. See the following image for the complete structure. Note that any examples using images expect their image files to be in a directory named images that's in the same directory as the example's src files.

You can find out which files each example needs by consulting the following table or by looking at the comments at the beginning of each source file.

Table of Examples

Example | Zip File (contains all files necessary for the example plus NetBeans IDE project metadata) | Source Files (first file has the main method, except for examples that run only as applets) | Image & Other Files | Where Described
LookAndFeelDemo | Look and Feel Demo Project | LookAndFeelDemo.java TestTheme.java |  | How to Set the Look and Feel
SynthApplication [Launch] | Synth Application Project | SynthApplication.java |  | The Synth Look and Feel
SynthDialog [Launch] | Synth Dialog Project | SynthDialog.java |  | A Synth Example
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Using Other Swing Features: Examples (The Java™ Tutorials > Creating a GUI with JFC/Swing > Using Other Swing Features)

Trail: Creating a GUI with JFC/Swing
Lesson: Using Other Swing Features
Home Page > Creating a GUI with JFC/Swing > Using Other Swing Features
« Previous • Trail • Next »
Using Other Swing Features: Examples
The table that follows lists every example in the Using Other Swing Features lesson, with links to required files and to where each example is discussed. The first column of the table has links to JNLP files that let you run the examples using JavaTM Web Start.

NOTE: Release 6.0 is required to run all applets and Java Web Start examples. Most examples will run on an earlier release but you must compile and run them locally.

To run an example using Java Web Start, click the [Launch] link in the first column of the table. The first time you run an example, there will be a delay while Java Web Start downloads the JAR file containing the class files for this lesson's examples. Afterward, the examples should execute more quickly.

Compiling and Running the Examples Locally

The second column in the table below has links to zip files for each demo that you can open and run in the NetBeans IDE. Refer to Running Tutorial Examples in NetBeans IDE for more information.

You can get all of the source, image, and other files required for all these examples by downloading the Swing Tutorial Examples bundle, which contains the files in the correct hierarchy.

If you download an individual example, take care to have all the necessary files in the proper hierarchy when you compile and run it. All of the examples in the Swing tutorial are placed in a package. For example, the components examples are placed in a components package. See the following image for the complete structure. Note that any examples using images expect their image files to be in a directory named images that's in the same directory as the example's src files.

You can find out which files each example needs by consulting the following table or by looking at the comments at the beginning of each source file.

Table of Examples

Example | Zip File (contains all files necessary for the example plus NetBeans IDE project metadata) | Source Files (first file has the main method, except for examples that run only as applets) | Image & Other Files | Where Described
AccessibleScrollDemo [Launch] | Accessible Scroll Demo Project | AccessibleScrollDemo.java Rule.java Corner.java ScrollablePicture.java | youngdad.jpeg | How to Support Assistive Technologies
ActionDemo [Launch] | Action Demo Project | ActionDemo.java | jlfgr-1_0.jar | How to Use Actions
DesktopDemo * | Desktop Demo Project | DesktopDemo.java | desk32.gif | How to Integrate with the Desktop Class
FocusConceptsDemo [Launch] | Focus Concepts Demo Project | FocusConceptsDemo.java |  | How to Use the Focus Subsystem
FocusTraversalDemo [Launch] | Focus Traversal Demo Project | FocusTraversalDemo.java |  | How to Use the Focus Subsystem
InputVerificationDemo [Launch] | Input Verification Demo Project | InputVerificationDemo.java |  | How to Use the Focus Subsystem
InputVerificationDialogDemo [Launch] | Input Verification Dialog Demo Project | InputVerificationDialogDemo.java |  | How to Use the Focus Subsystem
ModalityDemo [Launch] | Modality Demo Project | ModalityDemo.java |  | How to Use Modality in Dialogs
SplashDemo | Splash Demo Project | SplashDemo.java | splash.gif | How to Create a Splash Screen
TablePrintDemo1 [Launch] | Table Print Demo1 Project | TablePrintDemo1.java | failed.png, passed.png. | How to Print Tables
TablePrintDemo2 [Launch] | Table Print Demo2 Project | TablePrintDemo2.java TablePrintDemo1.java | failed.png, passed.png failed-BW.png, passed-BW.png. | How to Print Tables
TablePrintDemo3 [Launch] | Table Print Demo3 Project | TablePrintDemo3.java TablePrintDemo2.java TablePrintDemo1.java | failed.png, passed.png failed-BW.png, passed-BW.png clipBottom.png, clipBottomLeft.png clipBottomRight.png, clipLeft.png, clipRight.png, clipTop.png, clipTopCenter.png, clipTopLeft.png, clipTopRight.png, finalGrades.png. | How to Print Tables
TextAreaPrintingDemo [Launch] | Text Area Printing Demo Project | TextAreaPrintingDemo.java | print.png, toprint.txt, guide.txt. | How to Print Text
TextBatchPrintingDemo [Launch] | Text Batch Printing Demo Project | TextBatchPrintingDemo.java | index.html, chapter1.html, chapter2.html, chapter3.html, chapter4.html, chapter5.html, chapter6.html, chapter7.html, chapter8.html, chapter9.html, chapter10.html, chapter11.html. | How to Print Text
TrackFocusDemo [Launch] | Track Focus Demo Project | TrackFocusDemo.java Picture.java | Maya.jpg, Anya.jpg, Laine.jpg, Cosmo.jpg, Adele.jpg, Alexi.jpg. | How to Use the Focus Subsystem
TrayIconDemo * | Tray Icon Demo Project | TrayIconDemo.java | bulb.gif | How to Use the System Tray

* This application is not currently available with Java Web Start because we distribute only unsigned JAR files. To run it, download and compile it, and then run it as an application.
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Enter header and footer formats, if desired. You can use {0} for page number in any format.

Select "Show Progress Dialog" if you would like to track progress of the printing job and/or be able to cancel it.

Select "Print in Background" if you would like printing to occur in a background thread so that interaction with the demo application is not blocked.

Finally, click the Print! button.


Sonnet XXIX

When, in disgrace with fortune and men's eyes,
I all alone beweep my outcast state
And trouble deaf heaven with my bootless cries
And look upon myself and curse my fate,
Wishing me like to one more rich in hope,
Featured like him, like him with friends possess'd,
Desiring this man's art and that man's scope,
With what I most enjoy contented least;
Yet in these thoughts myself almost despising
Haply I think on thee, and then my state,
Like to the lark at break of day arising
From sullen earth, sings hymns at heaven's gate;
For thy sweet love remember'd such wealth brings
That then I scorn to change my state with kings.

Sonnet XXIII

As an unperfect actor on the stage
Who with his fear is put besides his part,
Or some fierce thing replete with too much rage,
Whose strength's abundance weakens his own heart,
So I, for fear of trust, forget to say
The perfect ceremony of love's rite,
And in mine own love's strength seem to decay,
O'ercharged with burden of mine own love's might.
O, let my books be then the eloquence
And dumb presagers of my speaking breast,
Who plead for love and look for recompense
More than that tongue that more hath more express'd.
O, learn to read what silent love hath writ:
To hear with eyes belongs to love's fine wit.


CHAPTER I. Down the Rabbit-Hole

CHAPTER I

Down the Rabbit-Hole

Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, 'and what is the use of a book,' thought Alice 'without pictures or conversation?'

So she was considering in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.

There was nothing so very remarkable in that; nor did Alice think it so very much out of the way to hear the Rabbit say to itself, 'Oh dear! Oh dear! I shall be late!' (when she thought it over afterwards, it occurred to her that she ought to have wondered at this, but at the time it all seemed quite natural); but when the Rabbit actually took a watch out of its waistcoat-pocket, and looked at it, and then hurried on, Alice started to her feet, for it flashed across her mind that she had never before seen a rabbit with either a waistcoat-pocket, or a watch to take out of it, and burning with curiosity, she ran across the field after it, and fortunately was just in time to see it pop down a large rabbit-hole under the hedge.

In another moment down went Alice after it, never once considering how in the world she was to get out again.

The rabbit-hole went straight on like a tunnel for some way, and then dipped suddenly down, so suddenly that Alice had not a moment to think about stopping herself before she found herself falling down a very deep well.

Either the well was very deep, or she fell very slowly, for she had plenty of time as she went down to look about her and to wonder what was going to happen next. First, she tried to look down and make out what she was coming to, but it was too dark to see anything; then she looked at the sides of the well, and noticed that they were filled with cupboards and book-shelves; here and there she saw maps and pictures hung upon pegs. She took down a jar from one of the shelves as she passed; it was labelled 'ORANGE MARMALADE', but to her great disappointment it was empty: she did not like to drop the jar for fear of killing somebody, so managed to put it into one of the cupboards as she fell past it.

'Well!' thought Alice to herself, 'after such a fall as this, I shall think nothing of tumbling down stairs! How brave they'll all think me at home! Why, I wouldn't say anything about it, even if I fell off the top of the house!' (Which was very likely true.)

Down, down, down. Would the fall never come to an end! 'I wonder how many miles I've fallen by this time?' she said aloud. 'I must be getting somewhere near the centre of the earth. Let me see: that would be four thousand miles down, I think--' (for, you see, Alice had learnt several things of this sort in her lessons in the schoolroom, and though this was not a very good opportunity for showing off her knowledge, as there was no one to listen to her, still it was good practice to say it over) '--yes, that's about the right distance--but then I wonder what Latitude or Longitude I've got to?' (Alice had no idea what Latitude was, or Longitude either, but thought they were nice grand words to say.)

Presently she began again. 'I wonder if I shall fall right through the earth! How funny it'll seem to come out among the people that walk with their heads downward! The Antipathies, I think--' (she was rather glad there was no one listening, this time, as it didn't sound at all the right word) '--but I shall have to ask them what the name of the country is, you know. Please, Ma'am, is this New Zealand or Australia?' (and she tried to curtsey as she spoke--fancy curtseying as you're falling through the air! Do you think you could manage it?) 'And what an ignorant little girl she'll think me for asking! No, it'll never do to ask: perhaps I shall see it written up somewhere.'

Down, down, down. There was nothing else to do, so Alice soon began talking again. 'Dinah'll miss me very much to-night, I should think!' (Dinah was the cat.) 'I hope they'll remember her saucer of milk at tea-time. Dinah my dear! I wish you were down here with me! There are no mice in the air, I'm afraid, but you might catch a bat, and that's very like a mouse, you know. But do cats eat bats, I wonder?' And here Alice began to get rather sleepy, and went on saying to herself, in a dreamy sort of way, 'Do cats eat bats? Do cats eat bats?' and sometimes, 'Do bats eat cats?' for, you see, as she couldn't answer either question, it didn't much matter which way she put it. She felt that she was dozing off, and had just begun to dream that she was walking hand in hand with Dinah, and saying to her very earnestly, 'Now, Dinah, tell me the truth: did you ever eat a bat?' when suddenly, thump! thump! down she came upon a heap of sticks and dry leaves, and the fall was over.

Alice was not a bit hurt, and she jumped up on to her feet in a moment: she looked up, but it was all dark overhead; before her was another long passage, and the White Rabbit was still in sight, hurrying down it. There was not a moment to be lost: away went Alice like the wind, and was just in time to hear it say, as it turned a corner, 'Oh my ears and whiskers, how late it's getting!' She was close behind it when she turned the corner, but the Rabbit was no longer to be seen: she found herself in a long, low hall, which was lit up by a row of lamps hanging from the roof.

There were doors all round the hall, but they were all locked; and when Alice had been all the way down one side and up the other, trying every door, she walked sadly down the middle, wondering how she was ever to get out again.

Suddenly she came upon a little three-legged table, all made of solid glass; there was nothing on it except a tiny golden key, and Alice's first thought was that it might belong to one of the doors of the hall; but, alas! either the locks were too large, or the key was too small, but at any rate it would not open any of them. However, on the second time round, she came upon a low curtain she had not noticed before, and behind it was a little door about fifteen inches high: she tried the little golden key in the lock, and to her great delight it fitted!

Alice opened the door and found that it led into a small passage, not much larger than a rat-hole: she knelt down and looked along the passage into the loveliest garden you ever saw. How she longed to get out of that dark hall, and wander about among those beds of bright flowers and those cool fountains, but she could not even get her head though the doorway; 'and even if my head would go through,' thought poor Alice, 'it would be of very little use without my shoulders. Oh, how I wish I could shut up like a telescope! I think I could, if I only know how to begin.' For, you see, so many out-of-the-way things had happened lately, that Alice had begun to think that very few things indeed were really impossible.

There seemed to be no use in waiting by the little door, so she went back to the table, half hoping she might find another key on it, or at any rate a book of rules for shutting people up like telescopes: this time she found a little bottle on it, ('which certainly was not here before,' said Alice,) and round the neck of the bottle was a paper label, with the words 'DRINK ME' beautifully printed on it in large letters.

It was all very well to say 'Drink me,' but the wise little Alice was not going to do that in a hurry. 'No, I'll look first,' she said, 'and see whether it's marked "poison" or not'; for she had read several nice little histories about children who had got burnt, and eaten up by wild beasts and other unpleasant things, all because they would not remember the simple rules their friends had taught them: such as, that a red-hot poker will burn you if you hold it too long; and that if you cut your finger very deeply with a knife, it usually bleeds; and she had never forgotten that, if you drink much from a bottle marked 'poison,' it is almost certain to disagree with you, sooner or later.

However, this bottle was not marked 'poison,' so Alice ventured to taste it, and finding it very nice, (it had, in fact, a sort of mixed flavour of cherry-tart, custard, pine-apple, roast turkey, toffee, and hot buttered toast,) she very soon finished it off.

* * * * *
* * * *
* * * * *

'What a curious feeling!' said Alice; 'I must be shutting up like a telescope.'

And so it was indeed: she was now only ten inches high, and her face brightened up at the thought that she was now the right size for going through the little door into that lovely garden. First, however, she waited for a few minutes to see if she was going to shrink any further: she felt a little nervous about this; 'for it might end, you know,' said Alice to herself, 'in my going out altogether, like a candle. I wonder what I should be like then?' And she tried to fancy what the flame of a candle is like after the candle is blown out, for she could not remember ever having seen such a thing.

After a while, finding that nothing more happened, she decided on going into the garden at once; but, alas for poor Alice! when she got to the door, she found she had forgotten the little golden key, and when she went back to the table for it, she found she could not possibly reach it: she could see it quite plainly through the glass, and she tried her best to climb up one of the legs of the table, but it was too slippery; and when she had tired herself out with trying, the poor little thing sat down and cried.

'Come, there's no use in crying like that!' said Alice to herself, rather sharply; 'I advise you to leave off this minute!' She generally gave herself very good advice, (though she very seldom followed it), and sometimes she scolded herself so severely as to bring tears into her eyes; and once she remembered trying to box her own ears for having cheated herself in a game of croquet she was playing against herself, for this curious child was very fond of pretending to be two people. 'But it's no use now,' thought poor Alice, 'to pretend to be two people! Why, there's hardly enough of me left to make one respectable person!'

Soon her eye fell on a little glass box that was lying under the table: she opened it, and found in it a very small cake, on which the words 'EAT ME' were beautifully marked in currants. 'Well, I'll eat it,' said Alice, 'and if it makes me grow larger, I can reach the key; and if it makes me grow smaller, I can creep under the door; so either way I'll get into the garden, and I don't care which happens!'

She ate a little bit, and said anxiously to herself, 'Which way? Which way?', holding her hand on the top of her head to feel which way it was growing, and she was quite surprised to find that she remained the same size: to be sure, this generally happens when one eats cake, but Alice had got so much into the way of expecting nothing but out-of-the-way things to happen, that it seemed quite dull and stupid for life to go on in the common way.

So she set to work, and very soon finished off the cake.

* * * * *
* * * *
* * * * *


CHAPTER II. The Pool of Tears

CHAPTER II

The Pool of Tears

'Curiouser and curiouser!' cried Alice (she was so much surprised, that for the moment she quite forgot how to speak good English); 'now I'm opening out like the largest telescope that ever was! Good-bye, feet!' (for when she looked down at her feet, they seemed to be almost out of sight, they were getting so far off). 'Oh, my poor little feet, I wonder who will put on your shoes and stockings for you now, dears? I'm sure I shan't be able! I shall be a great deal too far off to trouble myself about you: you must manage the best way you can; --but I must be kind to them,' thought Alice, 'or perhaps they won't walk the way I want to go! Let me see: I'll give them a new pair of boots every Christmas.'

And she went on planning to herself how she would manage it. 'They must go by the carrier,' she thought; 'and how funny it'll seem, sending presents to one's own feet! And how odd the directions will look!

ALICE'S RIGHT FOOT, ESQ.

HEARTHRUG,

NEAR THE FENDER,

(WITH ALICE'S LOVE).

Oh dear, what nonsense I'm talking!'

Just then her head struck against the roof of the hall: in fact she was now more than nine feet high, and she at once took up the little golden key and hurried off to the garden door.

Poor Alice! It was as much as she could do, lying down on one side, to look through into the garden with one eye; but to get through was more hopeless than ever: she sat down and began to cry again.

'You ought to be ashamed of yourself,' said Alice, 'a great girl like you,' (she might well say this), 'to go on crying in this way! Stop this moment, I tell you!' But she went on all the same, shedding gallons of tears, until there was a large pool all round her, about four inches deep and reaching half down the hall.

After a time she heard a little pattering of feet in the distance, and she hastily dried her eyes to see what was coming. It was the White Rabbit returning, splendidly dressed, with a pair of white kid gloves in one hand and a large fan in the other: he came trotting along in a great hurry, muttering to himself as he came, 'Oh! the Duchess, the Duchess! Oh! won't she be savage if I've kept her waiting!' Alice felt so desperate that she was ready to ask help of any one; so, when the Rabbit came near her, she began, in a low, timid voice, 'If you please, sir--' The Rabbit started violently, dropped the white kid gloves and the fan, and skurried away into the darkness as hard as he could go.

Alice took up the fan and gloves, and, as the hall was very hot, she kept fanning herself all the time she went on talking: 'Dear, dear! How queer everything is to-day! And yesterday things went on just as usual. I wonder if I've been changed in the night? Let me think: was I the same when I got up this morning? I almost think I can remember feeling a little different. But if I'm not the same, the next question is, Who in the world am I? Ah, that's the great puzzle!' And she began thinking over all the children she knew that were of the same age as herself, to see if she could have been changed for any of them.

'I'm sure I'm not Ada,' she said, 'for her hair goes in such long ringlets, and mine doesn't go in ringlets at all; and I'm sure I can't be Mabel, for I know all sorts of things, and she, oh! she knows such a very little! Besides, she's she, and I'm I, and--oh dear, how puzzling it all is! I'll try if I know all the things I used to know. Let me see: four times five is twelve, and four times six is thirteen, and four times seven is--oh dear! I shall never get to twenty at that rate! However, the Multiplication Table doesn't signify: let's try Geography. London is the capital of Paris, and Paris is the capital of Rome, and Rome--no, that's all wrong, I'm certain! I must have been changed for Mabel! I'll try and say "How doth the little--"' and she crossed her hands on her lap as if she were saying lessons, and began to repeat it, but her voice sounded hoarse and strange, and the words did not come the same as they used to do:--

'How doth the little crocodile

Improve his shining tail,

And pour the waters of the Nile

On every golden scale!

'How cheerfully he seems to grin,

How neatly spread his claws,

And welcome little fishes in

With gently smiling jaws!'

'I'm sure those are not the right words,' said poor Alice, and her eyes filled with tears again as she went on, 'I must be Mabel after all, and I shall have to go and live in that poky little house, and have next to no toys to play with, and oh! ever so many lessons to learn! No, I've made up my mind about it; if I'm Mabel, I'll stay down here! It'll be no use their putting their heads down and saying "Come up again, dear!" I shall only look up and say "Who am I then? Tell me that first, and then, if I like being that person, I'll come up: if not, I'll stay down here till I'm somebody else"--but, oh dear!' cried Alice, with a sudden burst of tears, 'I do wish they would put their heads down! I am so very tired of being all alone here!'

As she said this she looked down at her hands, and was surprised to see that she had put on one of the Rabbit's little white kid gloves while she was talking. 'How can I have done that?' she thought. 'I must be growing small again.' She got up and went to the table to measure herself by it, and found that, as nearly as she could guess, she was now about two feet high, and was going on shrinking rapidly: she soon found out that the cause of this was the fan she was holding, and she dropped it hastily, just in time to avoid shrinking away altogether.

'That was a narrow escape!' said Alice, a good deal frightened at the sudden change, but very glad to find herself still in existence; 'and now for the garden!' and she ran with all speed back to the little door: but, alas! the little door was shut again, and the little golden key was lying on the glass table as before, 'and things are worse than ever,' thought the poor child, 'for I never was so small as this before, never! And I declare it's too bad, that it is!'

As she said these words her foot slipped, and in another moment, splash! she was up to her chin in salt water. Her first idea was that she had somehow fallen into the sea, 'and in that case I can go back by railway,' she said to herself. (Alice had been to the seaside once in her life, and had come to the general conclusion, that wherever you go to on the English coast you find a number of bathing machines in the sea, some children digging in the sand with wooden spades, then a row of lodging houses, and behind them a railway station.) However, she soon made out that she was in the pool of tears which she had wept when she was nine feet high.

'I wish I hadn't cried so much!' said Alice, as she swam about, trying to find her way out. 'I shall be punished for it now, I suppose, by being drowned in my own tears! That will be a queer thing, to be sure! However, everything is queer to-day.'

Just then she heard something splashing about in the pool a little way off, and she swam nearer to make out what it was: at first she thought it must be a walrus or hippopotamus, but then she remembered how small she was now, and she soon made out that it was only a mouse that had slipped in like herself.

'Would it be of any use, now,' thought Alice, 'to speak to this mouse? Everything is so out-of-the-way down here, that I should think very likely it can talk: at any rate, there's no harm in trying.' So she began: 'O Mouse, do you know the way out of this pool? I am very tired of swimming about here, O Mouse!' (Alice thought this must be the right way of speaking to a mouse: she had never done such a thing before, but she remembered having seen in her brother's Latin Grammar, 'A mouse--of a mouse--to a mouse--a mouse--O mouse!') The Mouse looked at her rather inquisitively, and seemed to her to wink with one of its little eyes, but it said nothing.

'Perhaps it doesn't understand English,' thought Alice; 'I daresay it's a French mouse, come over with William the Conqueror.' (For, with all her knowledge of history, Alice had no very clear notion how long ago anything had happened.) So she began again: 'Ou est ma chatte?' which was the first sentence in her French lesson-book. The Mouse gave a sudden leap out of the water, and seemed to quiver all over with fright. 'Oh, I beg your pardon!' cried Alice hastily, afraid that she had hurt the poor animal's feelings. 'I quite forgot you didn't like cats.'

'Not like cats!' cried the Mouse, in a shrill, passionate voice. 'Would you like cats if you were me?'

'Well, perhaps not,' said Alice in a soothing tone: 'don't be angry about it. And yet I wish I could show you our cat Dinah: I think you'd take a fancy to cats if you could only see her. She is such a dear quiet thing,' Alice went on, half to herself, as she swam lazily about in the pool, 'and she sits purring so nicely by the fire, licking her paws and washing her face--and she is such a nice soft thing to nurse--and she's such a capital one for catching mice--oh, I beg your pardon!' cried Alice again, for this time the Mouse was bristling all over, and she felt certain it must be really offended. 'We won't talk about her any more if you'd rather not.'

'We indeed!' cried the Mouse, who was trembling down to the end of his tail. 'As if I would talk on such a subject! Our family always hated cats: nasty, low, vulgar things! Don't let me hear the name again!'

'I won't indeed!' said Alice, in a great hurry to change the subject of conversation. 'Are you--are you fond--of--of dogs?' The Mouse did not answer, so Alice went on eagerly: 'There is such a nice little dog near our house I should like to show you! A little bright-eyed terrier, you know, with oh, such long curly brown hair! And it'll fetch things when you throw them, and it'll sit up and beg for its dinner, and all sorts of things--I can't remember half of them--and it belongs to a farmer, you know, and he says it's so useful, it's worth a hundred pounds! He says it kills all the rats and--oh dear!' cried Alice in a sorrowful tone, 'I'm afraid I've offended it again!' For the Mouse was swimming away from her as hard as it could go, and making quite a commotion in the pool as it went.

So she called softly after it, 'Mouse dear! Do come back again, and we won't talk about cats or dogs either, if you don't like them!' When the Mouse heard this, it turned round and swam slowly back to her: its face was quite pale (with passion, Alice thought), and it said in a low trembling voice, 'Let us get to the shore, and then I'll tell you my history, and you'll understand why it is I hate cats and dogs.'

It was high time to go, for the pool was getting quite crowded with the birds and animals that had fallen into it: there were a Duck and a Dodo, a Lory and an Eaglet, and several other curious creatures. Alice led the way, and the whole party swam to the shore.


CHAPTER III. A Caucus-Race and a Long Tale

CHAPTER III

A Caucus-Race and a Long Tale

They were indeed a queer-looking party that assembled on the bank--the birds with draggled feathers, the animals with their fur clinging close to them, and all dripping wet, cross, and uncomfortable.

The first question of course was, how to get dry again: they had a consultation about this, and after a few minutes it seemed quite natural to Alice to find herself talking familiarly with them, as if she had known them all her life. Indeed, she had quite a long argument with the Lory, who at last turned sulky, and would only say, 'I am older than you, and must know better'; and this Alice would not allow without knowing how old it was, and, as the Lory positively refused to tell its age, there was no more to be said.

At last the Mouse, who seemed to be a person of authority among them, called out, 'Sit down, all of you, and listen to me! I'll soon make you dry enough!' They all sat down at once, in a large ring, with the Mouse in the middle. Alice kept her eyes anxiously fixed on it, for she felt sure she would catch a bad cold if she did not get dry very soon.

'Ahem!' said the Mouse with an important air, 'are you all ready? This is the driest thing I know. Silence all round, if you please! "William the Conqueror, whose cause was favoured by the pope, was soon submitted to by the English, who wanted leaders, and had been of late much accustomed to usurpation and conquest. Edwin and Morcar, the earls of Mercia and Northumbria--"'

'Ugh!' said the Lory, with a shiver.

'I beg your pardon!' said the Mouse, frowning, but very politely: 'Did you speak?'

'Not I!' said the Lory hastily.

'I thought you did,' said the Mouse. '--I proceed. "Edwin and Morcar, the earls of Mercia and Northumbria, declared for him: and even Stigand, the patriotic archbishop of Canterbury, found it advisable--"'

'Found what?' said the Duck.

'Found it,' the Mouse replied rather crossly: 'of course you know what "it" means.'

'I know what "it" means well enough, when I find a thing,' said the Duck: 'it's generally a frog or a worm. The question is, what did the archbishop find?'

The Mouse did not notice this question, but hurriedly went on, '"--found it advisable to go with Edgar Atheling to meet William and offer him the crown. William's conduct at first was moderate. But the insolence of his Normans--" How are you getting on now, my dear?' it continued, turning to Alice as it spoke.

'As wet as ever,' said Alice in a melancholy tone: 'it doesn't seem to dry me at all.'

'In that case,' said the Dodo solemnly, rising to its feet, 'I move that the meeting adjourn, for the immediate adoption of more energetic remedies--'

'Speak English!' said the Eaglet. 'I don't know the meaning of half those long words, and, what's more, I don't believe you do either!' And the Eaglet bent down its head to hide a smile: some of the other birds tittered audibly.

'What I was going to say,' said the Dodo in an offended tone, 'was, that the best thing to get us dry would be a Caucus-race.'

'What is a Caucus-race?' said Alice; not that she wanted much to know, but the Dodo had paused as if it thought that somebody ought to speak, and no one else seemed inclined to say anything.

'Why,' said the Dodo, 'the best way to explain it is to do it.' (And, as you might like to try the thing yourself, some winter day, I will tell you how the Dodo managed it.)

First it marked out a race-course, in a sort of circle, ('the exact shape doesn't matter,' it said,) and then all the party were placed along the course, here and there. There was no 'One, two, three, and away,' but they began running when they liked, and left off when they liked, so that it was not easy to know when the race was over. However, when they had been running half an hour or so, and were quite dry again, the Dodo suddenly called out 'The race is over!' and they all crowded round it, panting, and asking, 'But who has won?'

This question the Dodo could not answer without a great deal of thought, and it sat for a long time with one finger pressed upon its forehead (the position in which you usually see Shakespeare, in the pictures of him), while the rest waited in silence. At last the Dodo said, 'everybody has won, and all must have prizes.'

'But who is to give the prizes?' quite a chorus of voices asked.

'Why, she, of course,' said the Dodo, pointing to Alice with one finger; and the whole party at once crowded round her, calling out in a confused way, 'Prizes! Prizes!'

Alice had no idea what to do, and in despair she put her hand in her pocket, and pulled out a box of comfits, (luckily the salt water had not got into it), and handed them round as prizes. There was exactly one a-piece all round.

'But she must have a prize herself, you know,' said the Mouse.

'Of course,' the Dodo replied very gravely. 'What else have you got in your pocket?' he went on, turning to Alice.

'Only a thimble,' said Alice sadly.

'Hand it over here,' said the Dodo.

Then they all crowded round her once more, while the Dodo solemnly presented the thimble, saying 'We beg your acceptance of this elegant thimble'; and, when it had finished this short speech, they all cheered.

Alice thought the whole thing very absurd, but they all looked so grave that she did not dare to laugh; and, as she could not think of anything to say, she simply bowed, and took the thimble, looking as solemn as she could.

The next thing was to eat the comfits: this caused some noise and confusion, as the large birds complained that they could not taste theirs, and the small ones choked and had to be patted on the back. However, it was over at last, and they sat down again in a ring, and begged the Mouse to tell them something more.

'You promised to tell me your history, you know,' said Alice, 'and why it is you hate--C and D,' she added in a whisper, half afraid that it would be offended again.

'Mine is a long and a sad tale!' said the Mouse, turning to Alice, and sighing.

'It is a long tail, certainly,' said Alice, looking down with wonder at the Mouse's tail; 'but why do you call it sad?' And she kept on puzzling about it while the Mouse was speaking, so that her idea of the tale was something like this:--

'Fury said to a mouse, That he met in the house, "Let us both go to law: I will prosecute you. --Come, I'll take no denial; We must have a trial: For really this morning I've nothing to do." Said the mouse to the cur, "Such a trial, dear Sir,With no jury or judge, would be wasting our breath." "I'll be judge, I'll be jury," said cunning old Fury:"I'll try the whole cause, and condemn you to death."'

'You are not attending!' said the Mouse to Alice severely. 'What are you thinking of?'

'I beg your pardon,' said Alice very humbly: 'you had got to the fifth bend, I think?'

'I had not!' cried the Mouse, sharply and very angrily.

'A knot!' said Alice, always ready to make herself useful, and looking anxiously about her. 'Oh, do let me help to undo it!'

'I shall do nothing of the sort,' said the Mouse, getting up and walking away. 'You insult me by talking such nonsense!'

'I didn't mean it!' pleaded poor Alice. 'But you're so easily offended, you know!'

The Mouse only growled in reply.

'Please come back and finish your story!' Alice called after it; and the others all joined in chorus, 'Yes, please do!' but the Mouse only shook its head impatiently, and walked a little quicker.

'What a pity it wouldn't stay!' sighed the Lory, as soon as it was quite out of sight; and an old Crab took the opportunity of saying to her daughter 'Ah, my dear! Let this be a lesson to you never to lose your temper!' 'Hold your tongue, Ma!' said the young Crab, a little snappishly. 'You're enough to try the patience of an oyster!'

'I wish I had our Dinah here, I know I do!' said Alice aloud, addressing nobody in particular. 'She'd soon fetch it back!'

'And who is Dinah, if I might venture to ask the question?' said the Lory.

Alice replied eagerly, for she was always ready to talk about her pet: 'Dinah's our cat. And she's such a capital one for catching mice you can't think! And oh, I wish you could see her after the birds! Why, she'll eat a little bird as soon as look at it!'

This speech caused a remarkable sensation among the party. Some of the birds hurried off at once: one old Magpie began wrapping itself up very carefully, remarking, 'I really must be getting home; the night-air doesn't suit my throat!' and a Canary called out in a trembling voice to its children, 'Come away, my dears! It's high time you were all in bed!' On various pretexts they all moved off, and Alice was soon left alone.

'I wish I hadn't mentioned Dinah!' she said to herself in a melancholy tone. 'Nobody seems to like her, down here, and I'm sure she's the best cat in the world! Oh, my dear Dinah! I wonder if I shall ever see you any more!' And here poor Alice began to cry again, for she felt very lonely and low-spirited. In a little while, however, she again heard a little pattering of footsteps in the distance, and she looked up eagerly, half hoping that the Mouse had changed his mind, and was coming back to finish his story.


CHAPTER IV. The Rabbit Sends in a Little Bill

CHAPTER IV

The Rabbit Sends in a Little Bill

It was the White Rabbit, trotting slowly back again, and looking anxiously about as it went, as if it had lost something; and she heard it muttering to itself 'The Duchess! The Duchess! Oh my dear paws! Oh my fur and whiskers! She'll get me executed, as sure as ferrets are ferrets! Where can I have dropped them, I wonder?' Alice guessed in a moment that it was looking for the fan and the pair of white kid gloves, and she very good-naturedly began hunting about for them, but they were nowhere to be seen--everything seemed to have changed since her swim in the pool, and the great hall, with the glass table and the little door, had vanished completely.

Very soon the Rabbit noticed Alice, as she went hunting about, and called out to her in an angry tone, 'Why, Mary Ann, what are you doing out here? Run home this moment, and fetch me a pair of gloves and a fan! Quick, now!' And Alice was so much frightened that she ran off at once in the direction it pointed to, without trying to explain the mistake it had made.

'He took me for his housemaid,' she said to herself as she ran. 'How surprised he'll be when he finds out who I am! But I'd better take him his fan and gloves--that is, if I can find them.' As she said this, she came upon a neat little house, on the door of which was a bright brass plate with the name 'W. RABBIT' engraved upon it. She went in without knocking, and hurried upstairs, in great fear lest she should meet the real Mary Ann, and be turned out of the house before she had found the fan and gloves.

'How queer it seems,' Alice said to herself, 'to be going messages for a rabbit! I suppose Dinah'll be sending me on messages next!' And she began fancying the sort of thing that would happen: '"Miss Alice! Come here directly, and get ready for your walk!" "Coming in a minute, nurse! But I've got to see that the mouse doesn't get out." Only I don't think,' Alice went on, 'that they'd let Dinah stop in the house if it began ordering people about like that!'

By this time she had found her way into a tidy little room with a table in the window, and on it (as she had hoped) a fan and two or three pairs of tiny white kid gloves: she took up the fan and a pair of the gloves, and was just going to leave the room, when her eye fell upon a little bottle that stood near the looking- glass. There was no label this time with the words 'DRINK ME,' but nevertheless she uncorked it and put it to her lips. 'I know something interesting is sure to happen,' she said to herself, 'whenever I eat or drink anything; so I'll just see what this bottle does. I do hope it'll make me grow large again, for really I'm quite tired of being such a tiny little thing!'

It did so indeed, and much sooner than she had expected: before she had drunk half the bottle, she found her head pressing against the ceiling, and had to stoop to save her neck from being broken. She hastily put down the bottle, saying to herself 'That's quite enough--I hope I shan't grow any more--As it is, I can't get out at the door--I do wish I hadn't drunk quite so much!'

Alas! it was too late to wish that! She went on growing, and growing, and very soon had to kneel down on the floor: in another minute there was not even room for this, and she tried the effect of lying down with one elbow against the door, and the other arm curled round her head. Still she went on growing, and, as a last resource, she put one arm out of the window, and one foot up the chimney, and said to herself 'Now I can do no more, whatever happens. What will become of me?'

Luckily for Alice, the little magic bottle had now had its full effect, and she grew no larger: still it was very uncomfortable, and, as there seemed to be no sort of chance of her ever getting out of the room again, no wonder she felt unhappy.

'It was much pleasanter at home,' thought poor Alice, 'when one wasn't always growing larger and smaller, and being ordered about by mice and rabbits. I almost wish I hadn't gone down that rabbit-hole--and yet--and yet--it's rather curious, you know, this sort of life! I do wonder what can have happened to me! When I used to read fairy-tales, I fancied that kind of thing never happened, and now here I am in the middle of one! There ought to be a book written about me, that there ought! And when I grow up, I'll write one--but I'm grown up now,' she added in a sorrowful tone; 'at least there's no room to grow up any more here.'

'But then,' thought Alice, 'shall I never get any older than I am now? That'll be a comfort, one way--never to be an old woman-- but then--always to have lessons to learn! Oh, I shouldn't like that!'

'Oh, you foolish Alice!' she answered herself. 'How can you learn lessons in here? Why, there's hardly room for you, and no room at all for any lesson-books!'

And so she went on, taking first one side and then the other, and making quite a conversation of it altogether; but after a few minutes she heard a voice outside, and stopped to listen.

'Mary Ann! Mary Ann!' said the voice. 'Fetch me my gloves this moment!' Then came a little pattering of feet on the stairs. Alice knew it was the Rabbit coming to look for her, and she trembled till she shook the house, quite forgetting that she was now about a thousand times as large as the Rabbit, and had no reason to be afraid of it.

Presently the Rabbit came up to the door, and tried to open it; but, as the door opened inwards, and Alice's elbow was pressed hard against it, that attempt proved a failure. Alice heard it say to itself 'Then I'll go round and get in at the window.'

'That you won't' thought Alice, and, after waiting till she fancied she heard the Rabbit just under the window, she suddenly spread out her hand, and made a snatch in the air. She did not get hold of anything, but she heard a little shriek and a fall, and a crash of broken glass, from which she concluded that it was just possible it had fallen into a cucumber-frame, or something of the sort.

Next came an angry voice--the Rabbit's--'Pat! Pat! Where are you?' And then a voice she had never heard before, 'Sure then I'm here! Digging for apples, yer honour!'

'Digging for apples, indeed!' said the Rabbit angrily. 'Here! Come and help me out of this!' (Sounds of more broken glass.)

'Now tell me, Pat, what's that in the window?'

'Sure, it's an arm, yer honour!' (He pronounced it 'arrum.')

'An arm, you goose! Who ever saw one that size? Why, it fills the whole window!'

'Sure, it does, yer honour: but it's an arm for all that.'

'Well, it's got no business there, at any rate: go and take it away!'

There was a long silence after this, and Alice could only hear whispers now and then; such as, 'Sure, I don't like it, yer honour, at all, at all!' 'Do as I tell you, you coward!' and at last she spread out her hand again, and made another snatch in the air. This time there were two little shrieks, and more sounds of broken glass. 'What a number of cucumber-frames there must be!' thought Alice. 'I wonder what they'll do next! As for pulling me out of the window, I only wish they could! I'm sure I don't want to stay in here any longer!'

She waited for some time without hearing anything more: at last came a rumbling of little cartwheels, and the sound of a good many voices all talking together: she made out the words: 'Where's the other ladder?--Why, I hadn't to bring but one; Bill's got the other--Bill! fetch it here, lad!--Here, put 'em up at this corner--No, tie 'em together first--they don't reach half high enough yet--Oh! they'll do well enough; don't be particular-- Here, Bill! catch hold of this rope--Will the roof bear?--Mind that loose slate--Oh, it's coming down! Heads below!' (a loud crash)--'Now, who did that?--It was Bill, I fancy--Who's to go down the chimney?--Nay, I shan't! you do it!--That I won't, then!--Bill's to go down--Here, Bill! the master says you're to go down the chimney!'

'Oh! So Bill's got to come down the chimney, has he?' said Alice to herself. 'Shy, they seem to put everything upon Bill! I wouldn't be in Bill's place for a good deal: this fireplace is narrow, to be sure; but I think I can kick a little!'

She drew her foot as far down the chimney as she could, and waited till she heard a little animal (she couldn't guess of what sort it was) scratching and scrambling about in the chimney close above her: then, saying to herself 'This is Bill,' she gave one sharp kick, and waited to see what would happen next.

The first thing she heard was a general chorus of 'There goes Bill!' then the Rabbit's voice along--'Catch him, you by the hedge!' then silence, and then another confusion of voices--'Hold up his head--Brandy now--Don't choke him--How was it, old fellow? What happened to you? Tell us all about it!'

Last came a little feeble, squeaking voice, ('That's Bill,' thought Alice,) 'Well, I hardly know--No more, thank ye; I'm better now--but I'm a deal too flustered to tell you--all I know is, something comes at me like a Jack-in-the-box, and up I goes like a sky-rocket!'

'So you did, old fellow!' said the others.

'We must burn the house down!' said the Rabbit's voice; and Alice called out as loud as she could, 'If you do. I'll set Dinah at you!'

There was a dead silence instantly, and Alice thought to herself, 'I wonder what they will do next! If they had any sense, they'd take the roof off.' After a minute or two, they began moving about again, and Alice heard the Rabbit say, 'A barrowful will do, to begin with.'

'A barrowful of what?' thought Alice; but she had not long to doubt, for the next moment a shower of little pebbles came rattling in at the window, and some of them hit her in the face. 'I'll put a stop to this,' she said to herself, and shouted out, 'You'd better not do that again!' which produced another dead silence.

Alice noticed with some surprise that the pebbles were all turning into little cakes as they lay on the floor, and a bright idea came into her head. 'If I eat one of these cakes,' she thought, 'it's sure to make some change in my size; and as it can't possibly make me larger, it must make me smaller, I suppose.'

So she swallowed one of the cakes, and was delighted to find that she began shrinking directly. As soon as she was small enough to get through the door, she ran out of the house, and found quite a crowd of little animals and birds waiting outside. The poor little Lizard, Bill, was in the middle, being held up by two guinea-pigs, who were giving it something out of a bottle. They all made a rush at Alice the moment she appeared; but she ran off as hard as she could, and soon found herself safe in a thick wood.

'The first thing I've got to do,' said Alice to herself, as she wandered about in the wood, 'is to grow to my right size again; and the second thing is to find my way into that lovely garden. I think that will be the best plan.'

It sounded an excellent plan, no doubt, and very neatly and simply arranged; the only difficulty was, that she had not the smallest idea how to set about it; and while she was peering about anxiously among the trees, a little sharp bark just over her head made her look up in a great hurry.

An enormous puppy was looking down at her with large round eyes, and feebly stretching out one paw, trying to touch her. 'Poor little thing!' said Alice, in a coaxing tone, and she tried hard to whistle to it; but she was terribly frightened all the time at the thought that it might be hungry, in which case it would be very likely to eat her up in spite of all her coaxing.

Hardly knowing what she did, she picked up a little bit of stick, and held it out to the puppy; whereupon the puppy jumped into the air off all its feet at once, with a yelp of delight, and rushed at the stick, and made believe to worry it; then Alice dodged behind a great thistle, to keep herself from being run over; and the moment she appeared on the other side, the puppy made another rush at the stick, and tumbled head over heels in its hurry to get hold of it; then Alice, thinking it was very like having a game of play with a cart-horse, and expecting every moment to be trampled under its feet, ran round the thistle again; then the puppy began a series of short charges at the stick, running a very little way forwards each time and a long way back, and barking hoarsely all the while, till at last it sat down a good way off, panting, with its tongue hanging out of its mouth, and its great eyes half shut.

This seemed to Alice a good opportunity for making her escape; so she set off at once, and ran till she was quite tired and out of breath, and till the puppy's bark sounded quite faint in the distance.

'And yet what a dear little puppy it was!' said Alice, as she leant against a buttercup to rest herself, and fanned herself with one of the leaves: 'I should have liked teaching it tricks very much, if--if I'd only been the right size to do it! Oh dear! I'd nearly forgotten that I've got to grow up again! Let me see--how is it to be managed? I suppose I ought to eat or drink something or other; but the great question is, what?'

The great question certainly was, what? Alice looked all round her at the flowers and the blades of grass, but she did not see anything that looked like the right thing to eat or drink under the circumstances. There was a large mushroom growing near her, about the same height as herself; and when she had looked under it, and on both sides of it, and behind it, it occurred to her that she might as well look and see what was on the top of it.

She stretched herself up on tiptoe, and peeped over the edge of the mushroom, and her eyes immediately met those of a large caterpillar, that was sitting on the top with its arms folded, quietly smoking a long hookah, and taking not the smallest notice of her or of anything else.


CHAPTER V. Advice from a Caterpillar

CHAPTER V

Advice from a Caterpillar

The Caterpillar and Alice looked at each other for some time in silence: at last the Caterpillar took the hookah out of its mouth, and addressed her in a languid, sleepy voice.

'Who are you?' said the Caterpillar.

This was not an encouraging opening for a conversation. Alice replied, rather shyly, 'I--I hardly know, sir, just at present-- at least I know who I was when I got up this morning, but I think I must have been changed several times since then.'

'What do you mean by that?' said the Caterpillar sternly. 'Explain yourself!'

'I can't explain myself, I'm afraid, sir' said Alice, 'because I'm not myself, you see.'

'I don't see,' said the Caterpillar.

'I'm afraid I can't put it more clearly,' Alice replied very politely, 'for I can't understand it myself to begin with; and being so many different sizes in a day is very confusing.'

'It isn't,' said the Caterpillar.

'Well, perhaps you haven't found it so yet,' said Alice; 'but when you have to turn into a chrysalis--you will some day, you know--and then after that into a butterfly, I should think you'll feel it a little queer, won't you?'

'Not a bit,' said the Caterpillar.

'Well, perhaps your feelings may be different,' said Alice; 'all I know is, it would feel very queer to me.'

'You!' said the Caterpillar contemptuously. 'Who are you?'

Which brought them back again to the beginning of the conversation. Alice felt a little irritated at the Caterpillar's making such very short remarks, and she drew herself up and said, very gravely, 'I think, you ought to tell me who you are, first.'

'Why?' said the Caterpillar.

Here was another puzzling question; and as Alice could not think of any good reason, and as the Caterpillar seemed to be in a very unpleasant state of mind, she turned away.

'Come back!' the Caterpillar called after her. 'I've something important to say!'

This sounded promising, certainly: Alice turned and came back again.

'Keep your temper,' said the Caterpillar.

'Is that all?' said Alice, swallowing down her anger as well as she could.

'No,' said the Caterpillar.

Alice thought she might as well wait, as she had nothing else to do, and perhaps after all it might tell her something worth hearing. For some minutes it puffed away without speaking, but at last it unfolded its arms, took the hookah out of its mouth again, and said, 'So you think you're changed, do you?'

'I'm afraid I am, sir,' said Alice; 'I can't remember things as I used--and I don't keep the same size for ten minutes together!'

'Can't remember what things?' said the Caterpillar.

'Well, I've tried to say "How doth the little busy bee," but it all came different!' Alice replied in a very melancholy voice.

'Repeat, "you are old, Father William,"' said the Caterpillar.

Alice folded her hands, and began:--

'You are old, Father William,' the young man said, 'And your hair has become very white; And yet you incessantly stand on your head-- Do you think, at your age, it is right?'

'In my youth,' Father William replied to his son, 'I feared it might injure the brain; But, now that I'm perfectly sure I have none, Why, I do it again and again.'

'You are old,' said the youth, 'as I mentioned before, And have grown most uncommonly fat; Yet you turned a back-somersault in at the door-- Pray, what is the reason of that?'

'In my youth,' said the sage, as he shook his grey locks, 'I kept all my limbs very supple By the use of this ointment--one shilling the box-- Allow me to sell you a couple?'

'You are old,' said the youth, 'and your jaws are too weak For anything tougher than suet; Yet you finished the goose, with the bones and the beak-- Pray how did you manage to do it?'

'In my youth,' said his father, 'I took to the law, And argued each case with my wife; And the muscular strength, which it gave to my jaw, Has lasted the rest of my life.'

'You are old,' said the youth, 'one would hardly suppose That your eye was as steady as ever; Yet you balanced an eel on the end of your nose-- What made you so awfully clever?'

'I have answered three questions, and that is enough,' Said his father; 'don't give yourself airs! Do you think I can listen all day to such stuff? Be off, or I'll kick you down stairs!'

'That is not said right,' said the Caterpillar.

'Not quite right, I'm afraid,' said Alice, timidly; 'some of the words have got altered.'

'It is wrong from beginning to end,' said the Caterpillar decidedly, and there was silence for some minutes.

The Caterpillar was the first to speak.

'What size do you want to be?' it asked.

'Oh, I'm not particular as to size,' Alice hastily replied; 'only one doesn't like changing so often, you know.'

'I don't know,' said the Caterpillar.

Alice said nothing: she had never been so much contradicted in her life before, and she felt that she was losing her temper.

'Are you content now?' said the Caterpillar.

'Well, I should like to be a little larger, sir, if you wouldn't mind,' said Alice: 'three inches is such a wretched height to be.'

'It is a very good height indeed!' said the Caterpillar angrily, rearing itself upright as it spoke (it was exactly three inches high).

'But I'm not used to it!' pleaded poor Alice in a piteous tone. And she thought of herself, 'I wish the creatures wouldn't be so easily offended!'

'You'll get used to it in time,' said the Caterpillar; and it put the hookah into its mouth and began smoking again.

This time Alice waited patiently until it chose to speak again. In a minute or two the Caterpillar took the hookah out of its mouth and yawned once or twice, and shook itself. Then it got down off the mushroom, and crawled away in the grass, merely remarking as it went, 'One side will make you grow taller, and the other side will make you grow shorter.'

'One side of what? The other side of what?' thought Alice to herself.

'Of the mushroom,' said the Caterpillar, just as if she had asked it aloud; and in another moment it was out of sight.

Alice remained looking thoughtfully at the mushroom for a minute, trying to make out which were the two sides of it; and as it was perfectly round, she found this a very difficult question. However, at last she stretched her arms round it as far as they would go, and broke off a bit of the edge with each hand.

'And now which is which?' she said to herself, and nibbled a little of the right-hand bit to try the effect: the next moment she felt a violent blow underneath her chin: it had struck her foot!

She was a good deal frightened by this very sudden change, but she felt that there was no time to be lost, as she was shrinking rapidly; so she set to work at once to eat some of the other bit. Her chin was pressed so closely against her foot, that there was hardly room to open her mouth; but she did it at last, and managed to swallow a morsel of the lefthand bit.

* * * * *

'Come, my head's free at last!' said Alice in a tone of delight, which changed into alarm in another moment, when she found that her shoulders were nowhere to be found: all she could see, when she looked down, was an immense length of neck, which seemed to rise like a stalk out of a sea of green leaves that lay far below her.

'What can all that green stuff be?' said Alice. 'And where have my shoulders got to? And oh, my poor hands, how is it I can't see you?' She was moving them about as she spoke, but no result seemed to follow, except a little shaking among the distant green leaves.

As there seemed to be no chance of getting her hands up to her head, she tried to get her head down to them, and was delighted to find that her neck would bend about easily in any direction, like a serpent. She had just succeeded in curving it down into a graceful zigzag, and was going to dive in among the leaves, which she found to be nothing but the tops of the trees under which she had been wandering, when a sharp hiss made her draw back in a hurry: a large pigeon had flown into her face, and was beating her violently with its wings.

'Serpent!' screamed the Pigeon.

'I'm not a serpent!' said Alice indignantly. 'Let me alone!'

'Serpent, I say again!' repeated the Pigeon, but in a more subdued tone, and added with a kind of sob, 'I've tried every way, and nothing seems to suit them!'

'I haven't the least idea what you're talking about,' said Alice.

'I've tried the roots of trees, and I've tried banks, and I've tried hedges,' the Pigeon went on, without attending to her; 'but those serpents! There's no pleasing them!'

Alice was more and more puzzled, but she thought there was no use in saying anything more till the Pigeon had finished.

'As if it wasn't trouble enough hatching the eggs,' said the Pigeon; 'but I must be on the look-out for serpents night and day! Why, I haven't had a wink of sleep these three weeks!'

'I'm very sorry you've been annoyed,' said Alice, who was beginning to see its meaning.

'And just as I'd taken the highest tree in the wood,' continued the Pigeon, raising its voice to a shriek, 'and just as I was thinking I should be free of them at last, they must needs come wriggling down from the sky! Ugh, Serpent!'

'But I'm not a serpent, I tell you!' said Alice. 'I'm a--I'm a--'

'Well! what are you?' said the Pigeon. 'I can see you're trying to invent something!'

'I--I'm a little girl,' said Alice, rather doubtfully, as she remembered the number of changes she had gone through that day.

'A likely story indeed!' said the Pigeon in a tone of the deepest contempt. 'I've seen a good many little girls in my time, but never one with such a neck as that! No, no! You're a serpent; and there's no use denying it. I suppose you'll be telling me next that you never tasted an egg!'

'I have tasted eggs, certainly,' said Alice, who was a very truthful child; 'but little girls eat eggs quite as much as serpents do, you know.'

'I don't believe it,' said the Pigeon; 'but if they do, why then they're a kind of serpent, that's all I can say.'

This was such a new idea to Alice, that she was quite silent for a minute or two, which gave the Pigeon the opportunity of adding, 'You're looking for eggs, I know that well enough; and what does it matter to me whether you're a little girl or a serpent?'

'It matters a good deal to me,' said Alice hastily; 'but I'm not looking for eggs, as it happens; and if I was, I shouldn't want yours: I don't like them raw.'

'Well, be off, then!' said the Pigeon in a sulky tone, as it settled down again into its nest. Alice crouched down among the trees as well as she could, for her neck kept getting entangled among the branches, and every now and then she had to stop and untwist it. After a while she remembered that she still held the pieces of mushroom in her hands, and she set to work very carefully, nibbling first at one and then at the other, and growing sometimes taller and sometimes shorter, until she had succeeded in bringing herself down to her usual height.

It was so long since she had been anything near the right size, that it felt quite strange at first; but she got used to it in a few minutes, and began talking to herself, as usual. 'Come, there's half my plan done now! How puzzling all these changes are! I'm never sure what I'm going to be, from one minute to another! However, I've got back to my right size: the next thing is, to get into that beautiful garden--how is that to be done, I wonder?' As she said this, she came suddenly upon an open place, with a little house in it about four feet high. 'Whoever lives there,' thought Alice, 'it'll never do to come upon them this size: why, I should frighten them out of their wits!' So she began nibbling at the righthand bit again, and did not venture to go near the house till she had brought herself down to nine inches high.


CHAPTER VI. Pig and Pepper

CHAPTER VI

Pig and Pepper

For a minute or two she stood looking at the house, and wondering what to do next, when suddenly a footman in livery came running out of the wood--(she considered him to be a footman because he was in livery: otherwise, judging by his face only, she would have called him a fish)--and rapped loudly at the door with his knuckles. It was opened by another footman in livery, with a round face, and large eyes like a frog; and both footmen, Alice noticed, had powdered hair that curled all over their heads. She felt very curious to know what it was all about, and crept a little way out of the wood to listen.

The Fish-Footman began by producing from under his arm a great letter, nearly as large as himself, and this he handed over to the other, saying, in a solemn tone, 'For the Duchess. An invitation from the Queen to play croquet.' The Frog-Footman repeated, in the same solemn tone, only changing the order of the words a little, 'From the Queen. An invitation for the Duchess to play croquet.'

Then they both bowed low, and their curls got entangled together.

Alice laughed so much at this, that she had to run back into the wood for fear of their hearing her; and when she next peeped out the Fish-Footman was gone, and the other was sitting on the ground near the door, staring stupidly up into the sky.

Alice went timidly up to the door, and knocked.

'There's no sort of use in knocking,' said the Footman, 'and that for two reasons. First, because I'm on the same side of the door as you are; secondly, because they're making such a noise inside, no one could possibly hear you.' And certainly there was a most extraordinary noise going on within--a constant howling and sneezing, and every now and then a great crash, as if a dish or kettle had been broken to pieces.

'Please, then,' said Alice, 'how am I to get in?'

'There might be some sense in your knocking,' the Footman went on without attending to her, 'if we had the door between us. For instance, if you were inside, you might knock, and I could let you out, you know.' He was looking up into the sky all the time he was speaking, and this Alice thought decidedly uncivil. 'But perhaps he can't help it,' she said to herself; 'his eyes are so very nearly at the top of his head. But at any rate he might answer questions.--How am I to get in?' she repeated, aloud.

'I shall sit here,' the Footman remarked, 'till tomorrow--'

At this moment the door of the house opened, and a large plate came skimming out, straight at the Footman's head: it just grazed his nose, and broke to pieces against one of the trees behind him.

'--or next day, maybe,' the Footman continued in the same tone, exactly as if nothing had happened.

'How am I to get in?' asked Alice again, in a louder tone.

'Are you to get in at all?' said the Footman. 'That's the first question, you know.'

It was, no doubt: only Alice did not like to be told so. 'It's really dreadful,' she muttered to herself, 'the way all the creatures argue. It's enough to drive one crazy!'

The Footman seemed to think this a good opportunity for repeating his remark, with variations. 'I shall sit here,' he said, 'on and off, for days and days.'

'But what am I to do?' said Alice.

'Anything you like,' said the Footman, and began whistling.

'Oh, there's no use in talking to him,' said Alice desperately: 'he's perfectly idiotic!' And she opened the door and went in.

The door led right into a large kitchen, which was full of smoke from one end to the other: the Duchess was sitting on a three-legged stool in the middle, nursing a baby; the cook was leaning over the fire, stirring a large cauldron which seemed to be full of soup.

'There's certainly too much pepper in that soup!' Alice said to herself, as well as she could for sneezing.

There was certainly too much of it in the air. Even the Duchess sneezed occasionally; and as for the baby, it was sneezing and howling alternately without a moment's pause. The only things in the kitchen that did not sneeze, were the cook, and a large cat which was sitting on the hearth and grinning from ear to ear.

'Please would you tell me,' said Alice, a little timidly, for she was not quite sure whether it was good manners for her to speak first, 'why your cat grins like that?'

'It's a Cheshire cat,' said the Duchess, 'and that's why. Pig!'

She said the last word with such sudden violence that Alice quite jumped; but she saw in another moment that it was addressed to the baby, and not to her, so she took courage, and went on again:--

'I didn't know that Cheshire cats always grinned; in fact, I didn't know that cats could grin.'

'They all can,' said the Duchess; 'and most of 'em do.'

'I don't know of any that do,' Alice said very politely, feeling quite pleased to have got into a conversation.

'You don't know much,' said the Duchess; 'and that's a fact.'

Alice did not at all like the tone of this remark, and thought it would be as well to introduce some other subject of conversation. While she was trying to fix on one, the cook took the cauldron of soup off the fire, and at once set to work throwing everything within her reach at the Duchess and the baby --the fire-irons came first; then followed a shower of saucepans, plates, and dishes. The Duchess took no notice of them even when they hit her; and the baby was howling so much already, that it was quite impossible to say whether the blows hurt it or not.

'Oh, please mind what you're doing!' cried Alice, jumping up and down in an agony of terror. 'Oh, there goes his precious nose'; as an unusually large saucepan flew close by it, and very nearly carried it off.

'If everybody minded their own business,' the Duchess said in a hoarse growl, 'the world would go round a deal faster than it does.'

'Which would not be an advantage,' said Alice, who felt very glad to get an opportunity of showing off a little of her knowledge. 'Just think of what work it would make with the day and night! You see the earth takes twenty-four hours to turn round on its axis--'

'Talking of axes,' said the Duchess, 'chop off her head!'

Alice glanced rather anxiously at the cook, to see if she meant to take the hint; but the cook was busily stirring the soup, and seemed not to be listening, so she went on again: 'Twenty-four hours, I think; or is it twelve? I--'

'Oh, don't bother me,' said the Duchess; 'I never could abide figures!' And with that she began nursing her child again, singing a sort of lullaby to it as she did so, and giving it a violent shake at the end of every line:

'Speak roughly to your little boy,

And beat him when he sneezes:

He only does it to annoy,

Because he knows it teases.'

CHORUS

(In which the cook and the baby joined):--

'Wow! wow! wow!'

While the Duchess sang the second verse of the song, she kept tossing the baby violently up and down, and the poor little thing howled so, that Alice could hardly hear the words:--

'I speak severely to my boy,

I beat him when he sneezes;

For he can thoroughly enjoy

The pepper when he pleases!'

CHORUS

'Wow! wow! wow!'

'Here! you may nurse it a bit, if you like!' the Duchess said to Alice, flinging the baby at her as she spoke. 'I must go and get ready to play croquet with the Queen,' and she hurried out of the room. The cook threw a frying-pan after her as she went out, but it just missed her.

Alice caught the baby with some difficulty, as it was a queer- shaped little creature, and held out its arms and legs in all directions, 'just like a star-fish,' thought Alice. The poor little thing was snorting like a steam-engine when she caught it, and kept doubling itself up and straightening itself out again, so that altogether, for the first minute or two, it was as much as she could do to hold it.

As soon as she had made out the proper way of nursing it, (which was to twist it up into a sort of knot, and then keep tight hold of its right ear and left foot, so as to prevent its undoing itself,) she carried it out into the open air. 'If I don't take this child away with me,' thought Alice, 'they're sure to kill it in a day or two: wouldn't it be murder to leave it behind?' She said the last words out loud, and the little thing grunted in reply (it had left off sneezing by this time). 'Don't grunt,' said Alice; 'that's not at all a proper way of expressing yourself.'

The baby grunted again, and Alice looked very anxiously into its face to see what was the matter with it. There could be no doubt that it had a very turn-up nose, much more like a snout than a real nose; also its eyes were getting extremely small for a baby: altogether Alice did not like the look of the thing at all. 'But perhaps it was only sobbing,' she thought, and looked into its eyes again, to see if there were any tears.

No, there were no tears. 'If you're going to turn into a pig, my dear,' said Alice, seriously, 'I'll have nothing more to do with you. Mind now!' The poor little thing sobbed again (or grunted, it was impossible to say which), and they went on for some while in silence.

Alice was just beginning to think to herself, 'Now, what am I to do with this creature when I get it home?' when it grunted again, so violently, that she looked down into its face in some alarm. This time there could be no mistake about it: it was neither more nor less than a pig, and she felt that it would be quite absurd for her to carry it further.

So she set the little creature down, and felt quite relieved to see it trot away quietly into the wood. 'If it had grown up,' she said to herself, 'it would have made a dreadfully ugly child: but it makes rather a handsome pig, I think.' And she began thinking over other children she knew, who might do very well as pigs, and was just saying to herself, 'if one only knew the right way to change them--' when she was a little startled by seeing the Cheshire Cat sitting on a bough of a tree a few yards off.

The Cat only grinned when it saw Alice. It looked good- natured, she thought: still it had very long claws and a great many teeth, so she felt that it ought to be treated with respect.

'Cheshire Puss,' she began, rather timidly, as she did not at all know whether it would like the name: however, it only grinned a little wider. 'Come, it's pleased so far,' thought Alice, and she went on. 'Would you tell me, please, which way I ought to go from here?'

'That depends a good deal on where you want to get to,' said the Cat.

'I don't much care where--' said Alice.

'Then it doesn't matter which way you go,' said the Cat.

'--so long as I get somewhere,' Alice added as an explanation.

'Oh, you're sure to do that,' said the Cat, 'if you only walk long enough.'

Alice felt that this could not be denied, so she tried another question. 'What sort of people live about here?'

'In that direction,' the Cat said, waving its right paw round, 'lives a Hatter: and in that direction,' waving the other paw, 'lives a March Hare. Visit either you like: they're both mad.'

'But I don't want to go among mad people,' Alice remarked.

'Oh, you can't help that,' said the Cat: 'we're all mad here. I'm mad. You're mad.'

'How do you know I'm mad?' said Alice.

'You must be,' said the Cat, 'or you wouldn't have come here.'

Alice didn't think that proved it at all; however, she went on 'And how do you know that you're mad?'

'To begin with,' said the Cat, 'a dog's not mad. You grant that?'

'I suppose so,' said Alice.

'Well, then,' the Cat went on, 'you see, a dog growls when it's angry, and wags its tail when it's pleased. Now I growl when I'm pleased, and wag my tail when I'm angry. Therefore I'm mad.'

'I call it purring, not growling,' said Alice.

'Call it what you like,' said the Cat. 'Do you play croquet with the Queen to-day?'

'I should like it very much,' said Alice, 'but I haven't been invited yet.'

'You'll see me there,' said the Cat, and vanished.

Alice was not much surprised at this, she was getting so used to queer things happening. While she was looking at the place where it had been, it suddenly appeared again.

'By-the-bye, what became of the baby?' said the Cat. 'I'd nearly forgotten to ask.'

'It turned into a pig,' Alice quietly said, just as if it had come back in a natural way.

'I thought it would,' said the Cat, and vanished again.

Alice waited a little, half expecting to see it again, but it did not appear, and after a minute or two she walked on in the direction in which the March Hare was said to live. 'I've seen hatters before,' she said to herself; 'the March Hare will be much the most interesting, and perhaps as this is May it won't be raving mad--at least not so mad as it was in March.' As she said this, she looked up, and there was the Cat again, sitting on a branch of a tree.

'Did you say pig, or fig?' said the Cat.

'I said pig,' replied Alice; 'and I wish you wouldn't keep appearing and vanishing so suddenly: you make one quite giddy.'

'All right,' said the Cat; and this time it vanished quite slowly, beginning with the end of the tail, and ending with the grin, which remained some time after the rest of it had gone.

'Well! I've often seen a cat without a grin,' thought Alice; 'but a grin without a cat! It's the most curious thing I ever saw in my life!'

She had not gone much farther before she came in sight of the house of the March Hare: she thought it must be the right house, because the chimneys were shaped like ears and the roof was thatched with fur. It was so large a house, that she did not like to go nearer till she had nibbled some more of the lefthand bit of mushroom, and raised herself to about two feet high: even then she walked up towards it rather timidly, saying to herself 'Suppose it should be raving mad after all! I almost wish I'd gone to see the Hatter instead!'


CHAPTER VII. A Mad Tea-Party

CHAPTER VII

A Mad Tea-Party

There was a table set out under a tree in front of the house, and the March Hare and the Hatter were having tea at it: a Dormouse was sitting between them, fast asleep, and the other two were using it as a cushion, resting their elbows on it, and talking over its head. 'Very uncomfortable for the Dormouse,' thought Alice; 'only, as it's asleep, I suppose it doesn't mind.'

The table was a large one, but the three were all crowded together at one corner of it: 'No room! No room!' they cried out when they saw Alice coming. 'There's plenty of room!' said Alice indignantly, and she sat down in a large arm-chair at one end of the table.

'Have some wine,' the March Hare said in an encouraging tone.

Alice looked all round the table, but there was nothing on it but tea. 'I don't see any wine,' she remarked.

'There isn't any,' said the March Hare.

'Then it wasn't very civil of you to offer it,' said Alice angrily.

'It wasn't very civil of you to sit down without being invited,' said the March Hare.

'I didn't know it was your table,' said Alice; 'it's laid for a great many more than three.'

'Your hair wants cutting,' said the Hatter. He had been looking at Alice for some time with great curiosity, and this was his first speech.

'You should learn not to make personal remarks,' Alice said with some severity; 'it's very rude.'

The Hatter opened his eyes very wide on hearing this; but all he said was, 'Why is a raven like a writing-desk?'

'Come, we shall have some fun now!' thought Alice. 'I'm glad they've begun asking riddles.--I believe I can guess that,' she added aloud.

'Do you mean that you think you can find out the answer to it?' said the March Hare.

'Exactly so,' said Alice.

'Then you should say what you mean,' the March Hare went on.

'I do,' Alice hastily replied; 'at least--at least I mean what I say--that's the same thing, you know.'

'Not the same thing a bit!' said the Hatter. 'You might just as well say that "I see what I eat" is the same thing as "I eat what I see"!'

'You might just as well say,' added the March Hare, 'that "I like what I get" is the same thing as "I get what I like"!'

'You might just as well say,' added the Dormouse, who seemed to be talking in his sleep, 'that "I breathe when I sleep" is the same thing as "I sleep when I breathe"!'

'It is the same thing with you,' said the Hatter, and here the conversation dropped, and the party sat silent for a minute, while Alice thought over all she could remember about ravens and writing-desks, which wasn't much.

The Hatter was the first to break the silence. 'What day of the month is it?' he said, turning to Alice: he had taken his watch out of his pocket, and was looking at it uneasily, shaking it every now and then, and holding it to his ear.

Alice considered a little, and then said 'The fourth.'

'Two days wrong!' sighed the Hatter. 'I told you butter wouldn't suit the works!' he added looking angrily at the March Hare.

'It was the best butter,' the March Hare meekly replied.

'Yes, but some crumbs must have got in as well,' the Hatter grumbled: 'you shouldn't have put it in with the bread-knife.'

The March Hare took the watch and looked at it gloomily: then he dipped it into his cup of tea, and looked at it again: but he could think of nothing better to say than his first remark, 'It was the best butter, you know.'

Alice had been looking over his shoulder with some curiosity. 'What a funny watch!' she remarked. 'It tells the day of the month, and doesn't tell what o'clock it is!'

'Why should it?' muttered the Hatter. 'Does your watch tell you what year it is?'

'Of course not,' Alice replied very readily: 'but that's because it stays the same year for such a long time together.'

'Which is just the case with mine,' said the Hatter.

Alice felt dreadfully puzzled. The Hatter's remark seemed to have no sort of meaning in it, and yet it was certainly English. 'I don't quite understand you,' she said, as politely as she could.

'The Dormouse is asleep again,' said the Hatter, and he poured a little hot tea upon its nose.

The Dormouse shook its head impatiently, and said, without opening its eyes, 'Of course, of course; just what I was going to remark myself.'

'Have you guessed the riddle yet?' the Hatter said, turning to Alice again.

'No, I give it up,' Alice replied: 'what's the answer?'

'I haven't the slightest idea,' said the Hatter.

'Nor I,' said the March Hare.

Alice sighed wearily. 'I think you might do something better with the time,' she said, 'than waste it in asking riddles that have no answers.'

'If you knew Time as well as I do,' said the Hatter, 'you wouldn't talk about wasting it. It's him.'

'I don't know what you mean,' said Alice.

'Of course you don't!' the Hatter said, tossing his head contemptuously. 'I dare say you never even spoke to Time!'

'Perhaps not,' Alice cautiously replied: 'but I know I have to beat time when I learn music.'

'Ah! that accounts for it,' said the Hatter. 'He won't stand beating. Now, if you only kept on good terms with him, he'd do almost anything you liked with the clock. For instance, suppose it were nine o'clock in the morning, just time to begin lessons: you'd only have to whisper a hint to Time, and round goes the clock in a twinkling! Half-past one, time for dinner!'

('I only wish it was,' the March Hare said to itself in a whisper.)

'That would be grand, certainly,' said Alice thoughtfully: 'but then--I shouldn't be hungry for it, you know.'

'Not at first, perhaps,' said the Hatter: 'but you could keep it to half-past one as long as you liked.'

'Is that the way you manage?' Alice asked.

The Hatter shook his head mournfully. 'Not I!' he replied. 'We quarrelled last March--just before he went mad, you know--' (pointing with his tea spoon at the March Hare,) '--it was at the great concert given by the Queen of Hearts, and I had to sing

"Twinkle, twinkle, little bat!

How I wonder what you're at!"

You know the song, perhaps?'

'I've heard something like it,' said Alice.

'It goes on, you know,' the Hatter continued, 'in this way:--

"Up above the world you fly,

Like a tea-tray in the sky.

Twinkle, twinkle--"'

Here the Dormouse shook itself, and began singing in its sleep 'Twinkle, twinkle, twinkle, twinkle--' and went on so long that they had to pinch it to make it stop.

'Well, I'd hardly finished the first verse,' said the Hatter, 'when the Queen jumped up and bawled out, "He's murdering the time! Off with his head!"'

'How dreadfully savage!' exclaimed Alice.

'And ever since that,' the Hatter went on in a mournful tone, 'he won't do a thing I ask! It's always six o'clock now.'

A bright idea came into Alice's head. 'Is that the reason so many tea-things are put out here?' she asked.

'Yes, that's it,' said the Hatter with a sigh: 'it's always tea-time, and we've no time to wash the things between whiles.'

'Then you keep moving round, I suppose?' said Alice.

'Exactly so,' said the Hatter: 'as the things get used up.'

'But what happens when you come to the beginning again?' Alice ventured to ask.

'Suppose we change the subject,' the March Hare interrupted, yawning. 'I'm getting tired of this. I vote the young lady tells us a story.'

'I'm afraid I don't know one,' said Alice, rather alarmed at the proposal.

'Then the Dormouse shall!' they both cried. 'Wake up, Dormouse!' And they pinched it on both sides at once.

The Dormouse slowly opened his eyes. 'I wasn't asleep,' he said in a hoarse, feeble voice: 'I heard every word you fellows were saying.'

'Tell us a story!' said the March Hare.

'Yes, please do!' pleaded Alice.

'And be quick about it,' added the Hatter, 'or you'll be asleep again before it's done.'

'Once upon a time there were three little sisters,' the Dormouse began in a great hurry; 'and their names were Elsie, Lacie, and Tillie; and they lived at the bottom of a well--'

'What did they live on?' said Alice, who always took a great interest in questions of eating and drinking.

'They lived on treacle,' said the Dormouse, after thinking a minute or two.

'They couldn't have done that, you know,' Alice gently remarked; 'they'd have been ill.'

'So they were,' said the Dormouse; 'very ill.'

Alice tried to fancy to herself what such an extraordinary ways of living would be like, but it puzzled her too much, so she went on: 'But why did they live at the bottom of a well?'

'Take some more tea,' the March Hare said to Alice, very earnestly.

'I've had nothing yet,' Alice replied in an offended tone, 'so I can't take more.'

'You mean you can't take less,' said the Hatter: 'it's very easy to take more than nothing.'

'Nobody asked your opinion,' said Alice.

'Who's making personal remarks now?' the Hatter asked triumphantly.

Alice did not quite know what to say to this: so she helped herself to some tea and bread-and-butter, and then turned to the Dormouse, and repeated her question. 'Why did they live at the bottom of a well?'

The Dormouse again took a minute or two to think about it, and then said, 'It was a treacle-well.'

'There's no such thing!' Alice was beginning very angrily, but the Hatter and the March Hare went 'Sh! sh!' and the Dormouse sulkily remarked, 'If you can't be civil, you'd better finish the story for yourself.'

'No, please go on!' Alice said very humbly; 'I won't interrupt again. I dare say there may be one.'

'One, indeed!' said the Dormouse indignantly. However, he consented to go on. 'And so these three little sisters--they were learning to draw, you know--'

'What did they draw?' said Alice, quite forgetting her promise.

'Treacle,' said the Dormouse, without considering at all this time.

'I want a clean cup,' interrupted the Hatter: 'let's all move one place on.'

He moved on as he spoke, and the Dormouse followed him: the March Hare moved into the Dormouse's place, and Alice rather unwillingly took the place of the March Hare. The Hatter was the only one who got any advantage from the change: and Alice was a good deal worse off than before, as the March Hare had just upset the milk-jug into his plate.

Alice did not wish to offend the Dormouse again, so she began very cautiously: 'But I don't understand. Where did they draw the treacle from?'

'You can draw water out of a water-well,' said the Hatter; 'so I should think you could draw treacle out of a treacle-well--eh, stupid?'

'But they were in the well,' Alice said to the Dormouse, not choosing to notice this last remark.

'Of course they were', said the Dormouse; '--well in.'

This answer so confused poor Alice, that she let the Dormouse go on for some time without interrupting it.

'They were learning to draw,' the Dormouse went on, yawning and rubbing its eyes, for it was getting very sleepy; 'and they drew all manner of things--everything that begins with an M--'

'Why with an M?' said Alice.

'Why not?' said the March Hare.

Alice was silent.

The Dormouse had closed its eyes by this time, and was going off into a doze; but, on being pinched by the Hatter, it woke up again with a little shriek, and went on: '--that begins with an M, such as mouse-traps, and the moon, and memory, and muchness-- you know you say things are "much of a muchness"--did you ever see such a thing as a drawing of a muchness?'

'Really, now you ask me,' said Alice, very much confused, 'I don't think--'

'Then you shouldn't talk,' said the Hatter.

This piece of rudeness was more than Alice could bear: she got up in great disgust, and walked off; the Dormouse fell asleep instantly, and neither of the others took the least notice of her going, though she looked back once or twice, half hoping that they would call after her: the last time she saw them, they were trying to put the Dormouse into the teapot.

'At any rate I'll never go there again!' said Alice as she picked her way through the wood. 'It's the stupidest tea-party I ever was at in all my life!'

Just as she said this, she noticed that one of the trees had a door leading right into it. 'That's very curious!' she thought. 'But everything's curious today. I think I may as well go in at once.' And in she went.

Once more she found herself in the long hall, and close to the little glass table. 'Now, I'll manage better this time,' she said to herself, and began by taking the little golden key, and unlocking the door that led into the garden. Then she went to work nibbling at the mushroom (she had kept a piece of it in her pocket) till she was about a foot high: then she walked down the little passage: and then--she found herself at last in the beautiful garden, among the bright flower-beds and the cool fountains.


CHAPTER VIII. The Queen's Croquet-Ground

CHAPTER VIII

The Queen's Croquet-Ground

A large rose-tree stood near the entrance of the garden: the roses growing on it were white, but there were three gardeners at it, busily painting them red. Alice thought this a very curious thing, and she went nearer to watch them, and just as she came up to them she heard one of them say, 'Look out now, Five! Don't go splashing paint over me like that!'

'I couldn't help it,' said Five, in a sulky tone; 'Seven jogged my elbow.'

On which Seven looked up and said, 'That's right, Five! Always lay the blame on others!'

You'd better not talk!' said Five. 'I heard the Queen say only yesterday you deserved to be beheaded!'

'What for?' said the one who had spoken first.

'That's none of your business, Two!' said Seven.

'Yes, it is his business!' said Five, 'and I'll tell him--it was for bringing the cook tulip-roots instead of onions.'

Seven flung down his brush, and had just begun 'Well, of all the unjust things--' when his eye chanced to fall upon Alice, as she stood watching them, and he checked himself suddenly: the others looked round also, and all of them bowed low.

'Would you tell me,' said Alice, a little timidly, 'why you are painting those roses?'

Five and Seven said nothing, but looked at Two. Two began in a low voice, 'Why the fact is, you see, Miss, this here ought to have been a red rose-tree, and we put a white one in by mistake; and if the Queen was to find it out, we should all have our heads cut off, you know. So you see, Miss, we're doing our best, afore she comes, to--' At this moment Five, who had been anxiously looking across the garden, called out 'The Queen! The Queen!' and the three gardeners instantly threw themselves flat upon their faces. There was a sound of many footsteps, and Alice looked round, eager to see the Queen.

First came ten soldiers carrying clubs; these were all shaped like the three gardeners, oblong and flat, with their hands and feet at the corners: next the ten courtiers; these were ornamented all over with diamonds, and walked two and two, as the soldiers did. After these came the royal children; there were ten of them, and the little dears came jumping merrily along hand in hand, in couples: they were all ornamented with hearts. Next came the guests, mostly Kings and Queens, and among them Alice recognised the White Rabbit: it was talking in a hurried nervous manner, smiling at everything that was said, and went by without noticing her. Then followed the Knave of Hearts, carrying the King's crown on a crimson velvet cushion; and, last of all this grand procession, came THE KING AND QUEEN OF HEARTS.

Alice was rather doubtful whether she ought not to lie down on her face like the three gardeners, but she could not remember ever having heard of such a rule at processions; 'and besides, what would be the use of a procession,' thought she, 'if people had all to lie down upon their faces, so that they couldn't see it?' So she stood still where she was, and waited.

When the procession came opposite to Alice, they all stopped and looked at her, and the Queen said severely 'Who is this?' She said it to the Knave of Hearts, who only bowed and smiled in reply.

'Idiot!' said the Queen, tossing her head impatiently; and, turning to Alice, she went on, 'What's your name, child?'

'My name is Alice, so please your Majesty,' said Alice very politely; but she added, to herself, 'Why, they're only a pack of cards, after all. I needn't be afraid of them!'

'And who are these?' said the Queen, pointing to the three gardeners who were lying round the rosetree; for, you see, as they were lying on their faces, and the pattern on their backs was the same as the rest of the pack, she could not tell whether they were gardeners, or soldiers, or courtiers, or three of her own children.

'How should I know?' said Alice, surprised at her own courage. 'It's no business of mine.'

The Queen turned crimson with fury, and, after glaring at her for a moment like a wild beast, screamed 'Off with her head! Off--'

'Nonsense!' said Alice, very loudly and decidedly, and the Queen was silent.

The King laid his hand upon her arm, and timidly said 'Consider, my dear: she is only a child!'

The Queen turned angrily away from him, and said to the Knave 'Turn them over!'

The Knave did so, very carefully, with one foot.

'Get up!' said the Queen, in a shrill, loud voice, and the three gardeners instantly jumped up, and began bowing to the King, the Queen, the royal children, and everybody else.

'Leave off that!' screamed the Queen. 'You make me giddy.' And then, turning to the rose-tree, she went on, 'What have you been doing here?'

'May it please your Majesty,' said Two, in a very humble tone, going down on one knee as he spoke, 'we were trying--'

'I see!' said the Queen, who had meanwhile been examining the roses. 'Off with their heads!' and the procession moved on, three of the soldiers remaining behind to execute the unfortunate gardeners, who ran to Alice for protection.

'You shan't be beheaded!' said Alice, and she put them into a large flower-pot that stood near. The three soldiers wandered about for a minute or two, looking for them, and then quietly marched off after the others.

'Are their heads off?' shouted the Queen.

'Their heads are gone, if it please your Majesty!' the soldiers shouted in reply.

'That's right!' shouted the Queen. 'Can you play croquet?'

The soldiers were silent, and looked at Alice, as the question was evidently meant for her.

'Yes!' shouted Alice.

'Come on, then!' roared the Queen, and Alice joined the procession, wondering very much what would happen next.

'It's--it's a very fine day!' said a timid voice at her side. She was walking by the White Rabbit, who was peeping anxiously into her face.

'Very,' said Alice: '--where's the Duchess?'

'Hush! Hush!' said the Rabbit in a low, hurried tone. He looked anxiously over his shoulder as he spoke, and then raised himself upon tiptoe, put his mouth close to her ear, and whispered 'She's under sentence of execution.'

'What for?' said Alice.

'Did you say "What a pity!"?' the Rabbit asked.

'No, I didn't,' said Alice: 'I don't think it's at all a pity. I said "What for?"'

'She boxed the Queen's ears--' the Rabbit began. Alice gave a little scream of laughter. 'Oh, hush!' the Rabbit whispered in a frightened tone. 'The Queen will hear you! You see, she came rather late, and the Queen said--'

'Get to your places!' shouted the Queen in a voice of thunder, and people began running about in all directions, tumbling up against each other; however, they got settled down in a minute or two, and the game began. Alice thought she had never seen such a curious croquet-ground in her life; it was all ridges and furrows; the balls were live hedgehogs, the mallets live flamingoes, and the soldiers had to double themselves up and to stand on their hands and feet, to make the arches.

The chief difficulty Alice found at first was in managing her flamingo: she succeeded in getting its body tucked away, comfortably enough, under her arm, with its legs hanging down, but generally, just as she had got its neck nicely straightened out, and was going to give the hedgehog a blow with its head, it would twist itself round and look up in her face, with such a puzzled expression that she could not help bursting out laughing: and when she had got its head down, and was going to begin again, it was very provoking to find that the hedgehog had unrolled itself, and was in the act of crawling away: besides all this, there was generally a ridge or furrow in the way wherever she wanted to send the hedgehog to, and, as the doubled-up soldiers were always getting up and walking off to other parts of the ground, Alice soon came to the conclusion that it was a very difficult game indeed.

The players all played at once without waiting for turns, quarrelling all the while, and fighting for the hedgehogs; and in a very short time the Queen was in a furious passion, and went stamping about, and shouting 'Off with his head!' or 'Off with her head!' about once in a minute.

Alice began to feel very uneasy: to be sure, she had not as yet had any dispute with the Queen, but she knew that it might happen any minute, 'and then,' thought she, 'what would become of me? They're dreadfully fond of beheading people here; the great wonder is, that there's any one left alive!'

She was looking about for some way of escape, and wondering whether she could get away without being seen, when she noticed a curious appearance in the air: it puzzled her very much at first, but, after watching it a minute or two, she made it out to be a grin, and she said to herself 'It's the Cheshire Cat: now I shall have somebody to talk to.'

'How are you getting on?' said the Cat, as soon as there was mouth enough for it to speak with.

Alice waited till the eyes appeared, and then nodded. 'It's no use speaking to it,' she thought, 'till its ears have come, or at least one of them.' In another minute the whole head appeared, and then Alice put down her flamingo, and began an account of the game, feeling very glad she had someone to listen to her. The Cat seemed to think that there was enough of it now in sight, and no more of it appeared.

'I don't think they play at all fairly,' Alice began, in rather a complaining tone, 'and they all quarrel so dreadfully one can't hear oneself speak--and they don't seem to have any rules in particular; at least, if there are, nobody attends to them--and you've no idea how confusing it is all the things being alive; for instance, there's the arch I've got to go through next walking about at the other end of the ground--and I should have croqueted the Queen's hedgehog just now, only it ran away when it saw mine coming!'

'How do you like the Queen?' said the Cat in a low voice.

'Not at all,' said Alice: 'she's so extremely--' Just then she noticed that the Queen was close behind her, listening: so she went on, '--likely to win, that it's hardly worth while finishing the game.'

The Queen smiled and passed on.

'Who are you talking to?' said the King, going up to Alice, and looking at the Cat's head with great curiosity.

'It's a friend of mine--a Cheshire Cat,' said Alice: 'allow me to introduce it.'

'I don't like the look of it at all,' said the King: 'however, it may kiss my hand if it likes.'

'I'd rather not,' the Cat remarked.

'Don't be impertinent,' said the King, 'and don't look at me like that!' He got behind Alice as he spoke.

'A cat may look at a king,' said Alice. 'I've read that in some book, but I don't remember where.'

'Well, it must be removed,' said the King very decidedly, and he called the Queen, who was passing at the moment, 'My dear! I wish you would have this cat removed!'

The Queen had only one way of settling all difficulties, great or small. 'Off with his head!' she said, without even looking round.

'I'll fetch the executioner myself,' said the King eagerly, and he hurried off.

Alice thought she might as well go back, and see how the game was going on, as she heard the Queen's voice in the distance, screaming with passion. She had already heard her sentence three of the players to be executed for having missed their turns, and she did not like the look of things at all, as the game was in such confusion that she never knew whether it was her turn or not. So she went in search of her hedgehog.

The hedgehog was engaged in a fight with another hedgehog, which seemed to Alice an excellent opportunity for croqueting one of them with the other: the only difficulty was, that her flamingo was gone across to the other side of the garden, where Alice could see it trying in a helpless sort of way to fly up into a tree.

By the time she had caught the flamingo and brought it back, the fight was over, and both the hedgehogs were out of sight: 'but it doesn't matter much,' thought Alice, 'as all the arches are gone from this side of the ground.' So she tucked it away under her arm, that it might not escape again, and went back for a little more conversation with her friend.

When she got back to the Cheshire Cat, she was surprised to find quite a large crowd collected round it: there was a dispute going on between the executioner, the King, and the Queen, who were all talking at once, while all the rest were quite silent, and looked very uncomfortable.

The moment Alice appeared, she was appealed to by all three to settle the question, and they repeated their arguments to her, though, as they all spoke at once, she found it very hard indeed to make out exactly what they said.

The executioner's argument was, that you couldn't cut off a head unless there was a body to cut it off from: that he had never had to do such a thing before, and he wasn't going to begin at his time of life.

The King's argument was, that anything that had a head could be beheaded, and that you weren't to talk nonsense.

The Queen's argument was, that if something wasn't done about it in less than no time she'd have everybody executed, all round. (It was this last remark that had made the whole party look so grave and anxious.)

Alice could think of nothing else to say but 'It belongs to the Duchess: you'd better ask her about it.'

'She's in prison,' the Queen said to the executioner: 'fetch her here.' And the executioner went off like an arrow.

The Cat's head began fading away the moment he was gone, and, by the time he had come back with the Duchess, it had entirely disappeared; so the King and the executioner ran wildly up and down looking for it, while the rest of the party went back to the game.


CHAPTER IX. The Mock Turtle's Story

CHAPTER IX

The Mock Turtle's Story

'You can't think how glad I am to see you again, you dear old thing!' said the Duchess, as she tucked her arm affectionately into Alice's, and they walked off together.

Alice was very glad to find her in such a pleasant temper, and thought to herself that perhaps it was only the pepper that had made her so savage when they met in the kitchen.

'When I'm a Duchess,' she said to herself, (not in a very hopeful tone though), 'I won't have any pepper in my kitchen at all. Soup does very well without--Maybe it's always pepper that makes people hot-tempered,' she went on, very much pleased at having found out a new kind of rule, 'and vinegar that makes them sour--and camomile that makes them bitter--and--and barley-sugar and such things that make children sweet-tempered. I only wish people knew that: then they wouldn't be so stingy about it, you know--'

She had quite forgotten the Duchess by this time, and was a little startled when she heard her voice close to her ear. 'You're thinking about something, my dear, and that makes you forget to talk. I can't tell you just now what the moral of that is, but I shall remember it in a bit.'

'Perhaps it hasn't one,' Alice ventured to remark.

'Tut, tut, child!' said the Duchess. 'Everything's got a moral, if only you can find it.' And she squeezed herself up closer to Alice's side as she spoke.

Alice did not much like keeping so close to her: first, because the Duchess was very ugly; and secondly, because she was exactly the right height to rest her chin upon Alice's shoulder, and it was an uncomfortably sharp chin. However, she did not like to be rude, so she bore it as well as she could.

'The game's going on rather better now,' she said, by way of keeping up the conversation a little.

''Tis so,' said the Duchess: 'and the moral of that is--"Oh, 'tis love, 'tis love, that makes the world go round!"'

'Somebody said,' Alice whispered, 'that it's done by everybody minding their own business!'

'Ah, well! It means much the same thing,' said the Duchess, digging her sharp little chin into Alice's shoulder as she added, 'and the moral of that is--"Take care of the sense, and the sounds will take care of themselves."'

'How fond she is of finding morals in things!' Alice thought to herself.

'I dare say you're wondering why I don't put my arm round your waist,' the Duchess said after a pause: 'the reason is, that I'm doubtful about the temper of your flamingo. Shall I try the experiment?'

'He might bite,' Alice cautiously replied, not feeling at all anxious to have the experiment tried.

'Very true,' said the Duchess: 'flamingoes and mustard both bite. And the moral of that is--"Birds of a feather flock together."'

'Only mustard isn't a bird,' Alice remarked.

'Right, as usual,' said the Duchess: 'what a clear way you have of putting things!'

'It's a mineral, I think,' said Alice.

'Of course it is,' said the Duchess, who seemed ready to agree to everything that Alice said; 'there's a large mustard-mine near here. And the moral of that is--"The more there is of mine, the less there is of yours."'

'Oh, I know!' exclaimed Alice, who had not attended to this last remark, 'it's a vegetable. It doesn't look like one, but it is.'

'I quite agree with you,' said the Duchess; 'and the moral of that is--"Be what you would seem to be"--or if you'd like it put more simply--"Never imagine yourself not to be otherwise than what it might appear to others that what you were or might have been was not otherwise than what you had been would have appeared to them to be otherwise."'

'I think I should understand that better,' Alice said very politely, 'if I had it written down: but I can't quite follow it as you say it.'

'That's nothing to what I could say if I chose,' the Duchess replied, in a pleased tone.

'Pray don't trouble yourself to say it any longer than that,' said Alice.

'Oh, don't talk about trouble!' said the Duchess. 'I make you a present of everything I've said as yet.'

'A cheap sort of present!' thought Alice. 'I'm glad they don't give birthday presents like that!' But she did not venture to say it out loud.

'Thinking again?' the Duchess asked, with another dig of her sharp little chin.

'I've a right to think,' said Alice sharply, for she was beginning to feel a little worried.

'Just about as much right,' said the Duchess, 'as pigs have to fly; and the m--'

But here, to Alice's great surprise, the Duchess's voice died away, even in the middle of her favourite word 'moral,' and the arm that was linked into hers began to tremble. Alice looked up, and there stood the Queen in front of them, with her arms folded, frowning like a thunderstorm.

'A fine day, your Majesty!' the Duchess began in a low, weak voice.

'Now, I give you fair warning,' shouted the Queen, stamping on the ground as she spoke; 'either you or your head must be off, and that in about half no time! Take your choice!'

The Duchess took her choice, and was gone in a moment.

'Let's go on with the game,' the Queen said to Alice; and Alice was too much frightened to say a word, but slowly followed her back to the croquet-ground.

The other guests had taken advantage of the Queen's absence, and were resting in the shade: however, the moment they saw her, they hurried back to the game, the Queen merely remarking that a moment's delay would cost them their lives.

All the time they were playing the Queen never left off quarrelling with the other players, and shouting 'Off with his head!' or 'Off with her head!' Those whom she sentenced were taken into custody by the soldiers, who of course had to leave off being arches to do this, so that by the end of half an hour or so there were no arches left, and all the players, except the King, the Queen, and Alice, were in custody and under sentence of execution.

Then the Queen left off, quite out of breath, and said to Alice, 'Have you seen the Mock Turtle yet?'

'No,' said Alice. 'I don't even know what a Mock Turtle is.'

'It's the thing Mock Turtle Soup is made from,' said the Queen.

'I never saw one, or heard of one,' said Alice.

'Come on, then,' said the Queen, 'and he shall tell you his history,'

As they walked off together, Alice heard the King say in a low voice, to the company generally, 'You are all pardoned.' 'Come, that's a good thing!' she said to herself, for she had felt quite unhappy at the number of executions the Queen had ordered.

They very soon came upon a Gryphon, lying fast asleep in the sun. (If you don't know what a Gryphon is, look at the picture.) 'Up, lazy thing!' said the Queen, 'and take this young lady to see the Mock Turtle, and to hear his history. I must go back and see after some executions I have ordered'; and she walked off, leaving Alice alone with the Gryphon. Alice did not quite like the look of the creature, but on the whole she thought it would be quite as safe to stay with it as to go after that savage Queen: so she waited.

The Gryphon sat up and rubbed its eyes: then it watched the Queen till she was out of sight: then it chuckled. 'What fun!' said the Gryphon, half to itself, half to Alice.

'What is the fun?' said Alice.

'Why, she,' said the Gryphon. 'It's all her fancy, that: they never executes nobody, you know. Come on!'

'Everybody says "come on!" here,' thought Alice, as she went slowly after it: 'I never was so ordered about in all my life, never!'

They had not gone far before they saw the Mock Turtle in the distance, sitting sad and lonely on a little ledge of rock, and, as they came nearer, Alice could hear him sighing as if his heart would break. She pitied him deeply. 'What is his sorrow?' she asked the Gryphon, and the Gryphon answered, very nearly in the same words as before, 'It's all his fancy, that: he hasn't got no sorrow, you know. Come on!'

So they went up to the Mock Turtle, who looked at them with large eyes full of tears, but said nothing.

'This here young lady,' said the Gryphon, 'she wants for to know your history, she do.'

'I'll tell it her,' said the Mock Turtle in a deep, hollow tone: 'sit down, both of you, and don't speak a word till I've finished.'

So they sat down, and nobody spoke for some minutes. Alice thought to herself, 'I don't see how he can even finish, if he doesn't begin.' But she waited patiently.

'Once,' said the Mock Turtle at last, with a deep sigh, 'I was a real Turtle.'

These words were followed by a very long silence, broken only by an occasional exclamation of 'Hjckrrh!' from the Gryphon, and the constant heavy sobbing of the Mock Turtle. Alice was very nearly getting up and saying, 'Thank you, sir, for your interesting story,' but she could not help thinking there must be more to come, so she sat still and said nothing.

'When we were little,' the Mock Turtle went on at last, more calmly, though still sobbing a little now and then, 'we went to school in the sea. The master was an old Turtle--we used to call him Tortoise--'

'Why did you call him Tortoise, if he wasn't one?' Alice asked.

'We called him Tortoise because he taught us,' said the Mock Turtle angrily: 'really you are very dull!'

'You ought to be ashamed of yourself for asking such a simple question,' added the Gryphon; and then they both sat silent and looked at poor Alice, who felt ready to sink into the earth. At last the Gryphon said to the Mock Turtle, 'Drive on, old fellow! Don't be all day about it!' and he went on in these words:

'Yes, we went to school in the sea, though you mayn't believe it--'

'I never said I didn't!' interrupted Alice.

'You did,' said the Mock Turtle.

'Hold your tongue!' added the Gryphon, before Alice could speak again. The Mock Turtle went on.

'We had the best of educations--in fact, we went to school every day--'

'I've been to a day-school, too,' said Alice; 'you needn't be so proud as all that.'

'With extras?' asked the Mock Turtle a little anxiously.

'Yes,' said Alice, 'we learned French and music.'

'And washing?' said the Mock Turtle.

'Certainly not!' said Alice indignantly.

'Ah! then yours wasn't a really good school,' said the Mock Turtle in a tone of great relief. 'Now at ours they had at the end of the bill, "French, music, and washing--extra."'

'You couldn't have wanted it much,' said Alice; 'living at the bottom of the sea.'

'I couldn't afford to learn it.' said the Mock Turtle with a sigh. 'I only took the regular course.'

'What was that?' inquired Alice.

'Reeling and Writhing, of course, to begin with,' the Mock Turtle replied; 'and then the different branches of Arithmetic-- Ambition, Distraction, Uglification, and Derision.'

'I never heard of "Uglification,"' Alice ventured to say. 'What is it?'

The Gryphon lifted up both its paws in surprise. 'What! Never heard of uglifying!' it exclaimed. 'You know what to beautify is, I suppose?'

'Yes,' said Alice doubtfully: 'it means--to--make--anything--prettier.'

'Well, then,' the Gryphon went on, 'if you don't know what to uglify is, you are a simpleton.'

Alice did not feel encouraged to ask any more questions about it, so she turned to the Mock Turtle, and said 'What else had you to learn?'

'Well, there was Mystery,' the Mock Turtle replied, counting off the subjects on his flappers, '--Mystery, ancient and modern, with Seaography: then Drawling--the Drawling-master was an old conger-eel, that used to come once a week: He taught us Drawling, Stretching, and Fainting in Coils.'

'What was that like?' said Alice.

'Well, I can't show it you myself,' the Mock Turtle said: 'I'm too stiff. And the Gryphon never learnt it.'

'Hadn't time,' said the Gryphon: 'I went to the Classics master, though. He was an old crab, he was.'

'I never went to him,' the Mock Turtle said with a sigh: 'he taught Laughing and Grief, they used to say.'

'So he did, so he did,' said the Gryphon, sighing in his turn; and both creatures hid their faces in their paws.

'And how many hours a day did you do lessons?' said Alice, in a hurry to change the subject.

'Ten hours the first day,' said the Mock Turtle: 'nine the next, and so on.'

'What a curious plan!' exclaimed Alice.

'That's the reason they're called lessons,' the Gryphon remarked: 'because they lessen from day to day.'

This was quite a new idea to Alice, and she thought it over a little before she made her next remark. 'Then the eleventh day must have been a holiday?'

'Of course it was,' said the Mock Turtle.

'And how did you manage on the twelfth?' Alice went on eagerly.

'That's enough about lessons,' the Gryphon interrupted in a very decided tone: 'tell her something about the games now.'


CHAPTER X. The Lobster Quadrille

CHAPTER X

The Lobster Quadrille

The Mock Turtle sighed deeply, and drew the back of one flapper across his eyes. He looked at Alice, and tried to speak, but for a minute or two sobs choked his voice. 'Same as if he had a bone in his throat,' said the Gryphon: and it set to work shaking him and punching him in the back. At last the Mock Turtle recovered his voice, and, with tears running down his cheeks, he went on again:--

'You may not have lived much under the sea--' ('I haven't,' said Alice)-- 'and perhaps you were never even introduced to a lobster--' (Alice began to say 'I once tasted--' but checked herself hastily, and said 'No, never') '--so you can have no idea what a delightful thing a Lobster Quadrille is!'

'No, indeed,' said Alice. 'What sort of a dance is it?'

'Why,' said the Gryphon, 'you first form into a line along the sea-shore--'

'Two lines!' cried the Mock Turtle. 'Seals, turtles, salmon, and so on; then, when you've cleared all the jelly-fish out of the way--'

'That generally takes some time,' interrupted the Gryphon.

'--you advance twice--'

'Each with a lobster as a partner!' cried the Gryphon.

'Of course,' the Mock Turtle said: 'advance twice, set to partners--'

'--change lobsters, and retire in same order,' continued the Gryphon.

'Then, you know,' the Mock Turtle went on, 'you throw the--'

'The lobsters!' shouted the Gryphon, with a bound into the air.

'--as far out to sea as you can--'

'Swim after them!' screamed the Gryphon.

'Turn a somersault in the sea!' cried the Mock Turtle, capering wildly about.

'Change lobster's again!' yelled the Gryphon at the top of its voice.

'Back to land again, and that's all the first figure,' said the Mock Turtle, suddenly dropping his voice; and the two creatures, who had been jumping about like mad things all this time, sat down again very sadly and quietly, and looked at Alice.

'It must be a very pretty dance,' said Alice timidly.

'Would you like to see a little of it?' said the Mock Turtle.

'Very much indeed,' said Alice.

'Come, let's try the first figure!' said the Mock Turtle to the Gryphon. 'We can do without lobsters, you know. Which shall sing?'

'Oh, you sing,' said the Gryphon. 'I've forgotten the words.'

So they began solemnly dancing round and round Alice, every now and then treading on her toes when they passed too close, and waving their forepaws to mark the time, while the Mock Turtle sang this, very slowly and sadly:--

'"Will you walk a little faster?" said a whiting to a snail. "There's a porpoise close behind us, and he's treading on my tail. See how eagerly the lobsters and the turtles all advance! They are waiting on the shingle--will you come and join the dance?

Will you, won't you, will you, won't you, will you join the dance? Will you, won't you, will you, won't you, won't you join the dance?

"You can really have no notion how delightful it will be When they take us up and throw us, with the lobsters, out to sea!" But the snail replied "Too far, too far!" and gave a look askance-- Said he thanked the whiting kindly, but he would not join the dance. Would not, could not, would not, could not, would not join the dance. Would not, could not, would not, could not, could not join the dance.

'"What matters it how far we go?" his scaly friend replied. "There is another shore, you know, upon the other side. The further off from England the nearer is to France-- Then turn not pale, beloved snail, but come and join the dance.

Will you, won't you, will you, won't you, will you join the dance? Will you, won't you, will you, won't you, won't you join the dance?"'

'Thank you, it's a very interesting dance to watch,' said Alice, feeling very glad that it was over at last: 'and I do so like that curious song about the whiting!'

'Oh, as to the whiting,' said the Mock Turtle, 'they--you've seen them, of course?'

'Yes,' said Alice, 'I've often seen them at dinn--' she checked herself hastily.

'I don't know where Dinn may be,' said the Mock Turtle, 'but if you've seen them so often, of course you know what they're like.'

'I believe so,' Alice replied thoughtfully. 'They have their tails in their mouths--and they're all over crumbs.'

'You're wrong about the crumbs,' said the Mock Turtle: 'crumbs would all wash off in the sea. But they have their tails in their mouths; and the reason is--' here the Mock Turtle yawned and shut his eyes.--'Tell her about the reason and all that,' he said to the Gryphon.

'The reason is,' said the Gryphon, 'that they would go with the lobsters to the dance. So they got thrown out to sea. So they had to fall a long way. So they got their tails fast in their mouths. So they couldn't get them out again. That's all.'

'Thank you,' said Alice, 'it's very interesting. I never knew so much about a whiting before.'

'I can tell you more than that, if you like,' said the Gryphon. 'Do you know why it's called a whiting?'

'I never thought about it,' said Alice. 'Why?'

'It does the boots and shoes.' the Gryphon replied very solemnly.

Alice was thoroughly puzzled. 'Does the boots and shoes!' she repeated in a wondering tone.

'Why, what are your shoes done with?' said the Gryphon. 'I mean, what makes them so shiny?'

Alice looked down at them, and considered a little before she gave her answer. 'They're done with blacking, I believe.'

'Boots and shoes under the sea,' the Gryphon went on in a deep voice, 'are done with a whiting. Now you know.'

'And what are they made of?' Alice asked in a tone of great curiosity.

'Soles and eels, of course,' the Gryphon replied rather impatiently: 'any shrimp could have told you that.'

'If I'd been the whiting,' said Alice, whose thoughts were still running on the song, 'I'd have said to the porpoise, "Keep back, please: we don't want you with us!"'

'They were obliged to have him with them,' the Mock Turtle said: 'no wise fish would go anywhere without a porpoise.'

'Wouldn't it really?' said Alice in a tone of great surprise.

'Of course not,' said the Mock Turtle: 'why, if a fish came to me, and told me he was going a journey, I should say "With what porpoise?"'

'Don't you mean "purpose"?' said Alice.

'I mean what I say,' the Mock Turtle replied in an offended tone. And the Gryphon added 'Come, let's hear some of your adventures.'

'I could tell you my adventures--beginning from this morning,' said Alice a little timidly: 'but it's no use going back to yesterday, because I was a different person then.'

'Explain all that,' said the Mock Turtle.

'No, no! The adventures first,' said the Gryphon in an impatient tone: 'explanations take such a dreadful time.'

So Alice began telling them her adventures from the time when she first saw the White Rabbit. She was a little nervous about it just at first, the two creatures got so close to her, one on each side, and opened their eyes and mouths so very wide, but she gained courage as she went on. Her listeners were perfectly quiet till she got to the part about her repeating 'You are old, Father William,' to the Caterpillar, and the words all coming different, and then the Mock Turtle drew a long breath, and said 'That's very curious.'

'It's all about as curious as it can be,' said the Gryphon.

'It all came different!' the Mock Turtle repeated thoughtfully. 'I should like to hear her try and repeat something now. Tell her to begin.' He looked at the Gryphon as if he thought it had some kind of authority over Alice.

'Stand up and repeat "'Tis the voice of the sluggard,"' said the Gryphon.

'How the creatures order one about, and make one repeat lessons!' thought Alice; 'I might as well be at school at once.' However, she got up, and began to repeat it, but her head was so full of the Lobster Quadrille, that she hardly knew what she was saying, and the words came very queer indeed:--

''Tis the voice of the Lobster; I heard him declare, "You have baked me too brown, I must sugar my hair." As a duck with its eyelids, so he with his nose Trims his belt and his buttons, and turns out his toes.'

[later editions continued as follows When the sands are all dry, he is gay as a lark, And will talk in contemptuous tones of the Shark, But, when the tide rises and sharks are around, His voice has a timid and tremulous sound.]

'That's different from what I used to say when I was a child,' said the Gryphon.

'Well, I never heard it before,' said the Mock Turtle; 'but it sounds uncommon nonsense.'

Alice said nothing; she had sat down with her face in her hands, wondering if anything would ever happen in a natural way again.

'I should like to have it explained,' said the Mock Turtle.

'She can't explain it,' said the Gryphon hastily. 'Go on with the next verse.'

'But about his toes?' the Mock Turtle persisted. 'How could he turn them out with his nose, you know?'

'It's the first position in dancing.' Alice said; but was dreadfully puzzled by the whole thing, and longed to change the subject.

'Go on with the next verse,' the Gryphon repeated impatiently: 'it begins "I passed by his garden."'

Alice did not dare to disobey, though she felt sure it would all come wrong, and she went on in a trembling voice:--

'I passed by his garden, and marked, with one eye, How the Owl and the Panther were sharing a pie--'

[later editions continued as follows: The Panther took pie-crust, and gravy, and meat, While the Owl had the dish as its share of the treat. When the pie was all finished, the Owl, as a boon, Was kindly permitted to pocket the spoon: While the Panther received knife and fork with a growl, And concluded the banquet--]

'What is the use of repeating all that stuff,' the Mock Turtle interrupted, 'if you don't explain it as you go on? It's by far the most confusing thing I ever heard!'

'Yes, I think you'd better leave off,' said the Gryphon: and Alice was only too glad to do so.

'Shall we try another figure of the Lobster Quadrille?' the Gryphon went on. 'Or would you like the Mock Turtle to sing you a song?'

'Oh, a song, please, if the Mock Turtle would be so kind,' Alice replied, so eagerly that the Gryphon said, in a rather offended tone, 'Hm! No accounting for tastes! Sing her "Turtle Soup," will you, old fellow?'

The Mock Turtle sighed deeply, and began, in a voice sometimes choked with sobs, to sing this:--

'Beautiful Soup, so rich and green, Waiting in a hot tureen! Who for such dainties would not stoop? Soup of the evening, beautiful Soup! Soup of the evening, beautiful Soup! Beau--ootiful Soo--oop! Beau--ootiful Soo--oop! Soo--oop of the e--e--evening, Beautiful, beautiful Soup!

'Beautiful Soup! Who cares for fish, Game, or any other dish? Who would not give all else for two pennyworth only of beautiful Soup? Pennyworth only of beautiful Soup? Beau--ootiful Soo--oop! Beau--ootiful Soo--oop! Soo--oop of the e--e--evening, Beautiful, beauti--FUL SOUP!'

'Chorus again!' cried the Gryphon, and the Mock Turtle had just begun to repeat it, when a cry of 'The trial's beginning!' was heard in the distance.

'Come on!' cried the Gryphon, and, taking Alice by the hand, it hurried off, without waiting for the end of the song.

'What trial is it?' Alice panted as she ran; but the Gryphon only answered 'Come on!' and ran the faster, while more and more faintly came, carried on the breeze that followed them, the melancholy words:--

'Soo--oop of the e--e--evening, Beautiful, beautiful Soup!'


CHAPTER XI. Who Stole the Tarts?

CHAPTER XI

Who Stole the Tarts?

The King and Queen of Hearts were seated on their throne when they arrived, with a great crowd assembled about them--all sorts of little birds and beasts, as well as the whole pack of cards: the Knave was standing before them, in chains, with a soldier on each side to guard him; and near the King was the White Rabbit, with a trumpet in one hand, and a scroll of parchment in the other. In the very middle of the court was a table, with a large dish of tarts upon it: they looked so good, that it made Alice quite hungry to look at them--'I wish they'd get the trial done,' she thought, 'and hand round the refreshments!' But there seemed to be no chance of this, so she began looking at everything about her, to pass away the time.

Alice had never been in a court of justice before, but she had read about them in books, and she was quite pleased to find that she knew the name of nearly everything there. 'That's the judge,' she said to herself, 'because of his great wig.'

The judge, by the way, was the King; and as he wore his crown over the wig, (look at the frontispiece if you want to see how he did it,) he did not look at all comfortable, and it was certainly not becoming.

'And that's the jury-box,' thought Alice, 'and those twelve creatures,' (she was obliged to say 'creatures,' you see, because some of them were animals, and some were birds,) 'I suppose they are the jurors.' She said this last word two or three times over to herself, being rather proud of it: for she thought, and rightly too, that very few little girls of her age knew the meaning of it at all. However, 'jury-men' would have done just as well.

The twelve jurors were all writing very busily on slates. 'What are they doing?' Alice whispered to the Gryphon. 'They can't have anything to put down yet, before the trial's begun.'

'They're putting down their names,' the Gryphon whispered in reply, 'for fear they should forget them before the end of the trial.'

'Stupid things!' Alice began in a loud, indignant voice, but she stopped hastily, for the White Rabbit cried out, 'Silence in the court!' and the King put on his spectacles and looked anxiously round, to make out who was talking.

Alice could see, as well as if she were looking over their shoulders, that all the jurors were writing down 'stupid things!' on their slates, and she could even make out that one of them didn't know how to spell 'stupid,' and that he had to ask his neighbour to tell him. 'A nice muddle their slates'll be in before the trial's over!' thought Alice.

One of the jurors had a pencil that squeaked. This of course, Alice could not stand, and she went round the court and got behind him, and very soon found an opportunity of taking it away. She did it so quickly that the poor little juror (it was Bill, the Lizard) could not make out at all what had become of it; so, after hunting all about for it, he was obliged to write with one finger for the rest of the day; and this was of very little use, as it left no mark on the slate.

'Herald, read the accusation!' said the King.

On this the White Rabbit blew three blasts on the trumpet, and then unrolled the parchment scroll, and read as follows:--

'The Queen of Hearts, she made some tarts, All on a summer day: The Knave of Hearts, he stole those tarts, And took them quite away!'

'Consider your verdict,' the King said to the jury.

'Not yet, not yet!' the Rabbit hastily interrupted. 'There's a great deal to come before that!'

'Call the first witness,' said the King; and the White Rabbit blew three blasts on the trumpet, and called out, 'First witness!'

The first witness was the Hatter. He came in with a teacup in one hand and a piece of bread-and-butter in the other. 'I beg pardon, your Majesty,' he began, 'for bringing these in: but I hadn't quite finished my tea when I was sent for.'

'You ought to have finished,' said the King. 'When did you begin?'

The Hatter looked at the March Hare, who had followed him into the court, arm-in-arm with the Dormouse. 'Fourteenth of March, I think it was,' he said.

'Fifteenth,' said the March Hare.

'Sixteenth,' added the Dormouse.

'Write that down,' the King said to the jury, and the jury eagerly wrote down all three dates on their slates, and then added them up, and reduced the answer to shillings and pence.

'Take off your hat,' the King said to the Hatter.

'It isn't mine,' said the Hatter.

'Stolen!' the King exclaimed, turning to the jury, who instantly made a memorandum of the fact.

'I keep them to sell,' the Hatter added as an explanation; 'I've none of my own. I'm a hatter.'

Here the Queen put on her spectacles, and began staring at the Hatter, who turned pale and fidgeted.

'Give your evidence,' said the King; 'and don't be nervous, or I'll have you executed on the spot.'

This did not seem to encourage the witness at all: he kept shifting from one foot to the other, looking uneasily at the Queen, and in his confusion he bit a large piece out of his teacup instead of the bread-and-butter.

Just at this moment Alice felt a very curious sensation, which puzzled her a good deal until she made out what it was: she was beginning to grow larger again, and she thought at first she would get up and leave the court; but on second thoughts she decided to remain where she was as long as there was room for her.

'I wish you wouldn't squeeze so.' said the Dormouse, who was sitting next to her. 'I can hardly breathe.'

'I can't help it,' said Alice very meekly: 'I'm growing.'

'You've no right to grow here,' said the Dormouse.

'Don't talk nonsense,' said Alice more boldly: 'you know you're growing too.'

'Yes, but I grow at a reasonable pace,' said the Dormouse: 'not in that ridiculous fashion.' And he got up very sulkily and crossed over to the other side of the court.

All this time the Queen had never left off staring at the Hatter, and, just as the Dormouse crossed the court, she said to one of the officers of the court, 'Bring me the list of the singers in the last concert!' on which the wretched Hatter trembled so, that he shook both his shoes off.

'Give your evidence,' the King repeated angrily, 'or I'll have you executed, whether you're nervous or not.'

'I'm a poor man, your Majesty,' the Hatter began, in a trembling voice, '--and I hadn't begun my tea--not above a week or so--and what with the bread-and-butter getting so thin--and the twinkling of the tea--'

'The twinkling of the what?' said the King.

'It began with the tea,' the Hatter replied.

'Of course twinkling begins with a T!' said the King sharply. 'Do you take me for a dunce? Go on!'

'I'm a poor man,' the Hatter went on, 'and most things twinkled after that--only the March Hare said--'

'I didn't!' the March Hare interrupted in a great hurry.

'You did!' said the Hatter.

'I deny it!' said the March Hare.

'He denies it,' said the King: 'leave out that part.'

'Well, at any rate, the Dormouse said--' the Hatter went on, looking anxiously round to see if he would deny it too: but the Dormouse denied nothing, being fast asleep.

'After that,' continued the Hatter, 'I cut some more bread- and-butter--'

'But what did the Dormouse say?' one of the jury asked.

'That I can't remember,' said the Hatter.

'You must remember,' remarked the King, 'or I'll have you executed.'

The miserable Hatter dropped his teacup and bread-and-butter, and went down on one knee. 'I'm a poor man, your Majesty,' he began.

'You're a very poor speaker,' said the King.

Here one of the guinea-pigs cheered, and was immediately suppressed by the officers of the court. (As that is rather a hard word, I will just explain to you how it was done. They had a large canvas bag, which tied up at the mouth with strings: into this they slipped the guinea-pig, head first, and then sat upon it.)

'I'm glad I've seen that done,' thought Alice. 'I've so often read in the newspapers, at the end of trials, "There was some attempts at applause, which was immediately suppressed by the officers of the court," and I never understood what it meant till now.'

'If that's all you know about it, you may stand down,' continued the King.

'I can't go no lower,' said the Hatter: 'I'm on the floor, as it is.'

'Then you may sit down,' the King replied.

Here the other guinea-pig cheered, and was suppressed.

'Come, that finished the guinea-pigs!' thought Alice. 'Now we shall get on better.'

'I'd rather finish my tea,' said the Hatter, with an anxious look at the Queen, who was reading the list of singers.

'You may go,' said the King, and the Hatter hurriedly left the court, without even waiting to put his shoes on.

'--and just take his head off outside,' the Queen added to one of the officers: but the Hatter was out of sight before the officer could get to the door.

'Call the next witness!' said the King.

The next witness was the Duchess's cook. She carried the pepper-box in her hand, and Alice guessed who it was, even before she got into the court, by the way the people near the door began sneezing all at once.

'Give your evidence,' said the King.

'Shan't,' said the cook.

The King looked anxiously at the White Rabbit, who said in a low voice, 'Your Majesty must cross-examine this witness.'

'Well, if I must, I must,' the King said, with a melancholy air, and, after folding his arms and frowning at the cook till his eyes were nearly out of sight, he said in a deep voice, 'What are tarts made of?'

'Pepper, mostly,' said the cook.

'Treacle,' said a sleepy voice behind her.

'Collar that Dormouse,' the Queen shrieked out. 'Behead that Dormouse! Turn that Dormouse out of court! Suppress him! Pinch him! Off with his whiskers!'

For some minutes the whole court was in confusion, getting the Dormouse turned out, and, by the time they had settled down again, the cook had disappeared.

'Never mind!' said the King, with an air of great relief. 'Call the next witness.' And he added in an undertone to the Queen, 'Really, my dear, you must cross-examine the next witness. It quite makes my forehead ache!'

Alice watched the White Rabbit as he fumbled over the list, feeling very curious to see what the next witness would be like, '--for they haven't got much evidence yet,' she said to herself. Imagine her surprise, when the White Rabbit read out, at the top of his shrill little voice, the name 'Alice!'

CHAPTER XII

Alice's Evidence

'Here!' cried Alice, quite forgetting in the flurry of the moment how large she had grown in the last few minutes, and she jumped up in such a hurry that she tipped over the jury-box with the edge of her skirt, upsetting all the jurymen on to the heads of the crowd below, and there they lay sprawling about, reminding her very much of a globe of goldfish she had accidentally upset the week before.

'Oh, I beg your pardon!' she exclaimed in a tone of great dismay, and began picking them up again as quickly as she could, for the accident of the goldfish kept running in her head, and she had a vague sort of idea that they must be collected at once and put back into the jury-box, or they would die.

'The trial cannot proceed,' said the King in a very grave voice, 'until all the jurymen are back in their proper places-- all,' he repeated with great emphasis, looking hard at Alice as he said do.

Alice looked at the jury-box, and saw that, in her haste, she had put the Lizard in head downwards, and the poor little thing was waving its tail about in a melancholy way, being quite unable to move. She soon got it out again, and put it right; 'not that it signifies much,' she said to herself; 'I should think it would be quite as much use in the trial one way up as the other.'

As soon as the jury had a little recovered from the shock of being upset, and their slates and pencils had been found and handed back to them, they set to work very diligently to write out a history of the accident, all except the Lizard, who seemed too much overcome to do anything but sit with its mouth open, gazing up into the roof of the court.

'What do you know about this business?' the King said to Alice.

'Nothing,' said Alice.

'Nothing whatever?' persisted the King.

'Nothing whatever,' said Alice.

'That's very important,' the King said, turning to the jury. They were just beginning to write this down on their slates, when the White Rabbit interrupted: 'Unimportant, your Majesty means, of course,' he said in a very respectful tone, but frowning and making faces at him as he spoke.

'Unimportant, of course, I meant,' the King hastily said, and went on to himself in an undertone, 'important--unimportant-- unimportant--important--' as if he were trying which word sounded best.

Some of the jury wrote it down 'important,' and some 'unimportant.' Alice could see this, as she was near enough to look over their slates; 'but it doesn't matter a bit,' she thought to herself.

At this moment the King, who had been for some time busily writing in his note-book, cackled out 'Silence!' and read out from his book, 'Rule Forty-two. All persons more than a mile hight to leave the court.'

Everybody looked at Alice.

'I'm not a mile high,' said Alice.

'You are,' said the King.

'Nearly two miles high,' added the Queen.

'Well, I shan't go, at any rate,' said Alice: 'besides, that's not a regular rule: you invented it just now.'

'It's the oldest rule in the book,' said the King.

'Then it ought to be Number One,' said Alice.

The King turned pale, and shut his note-book hastily. 'Consider your verdict,' he said to the jury, in a low, trembling voice.

'There's more evidence to come yet, please your Majesty,' said the White Rabbit, jumping up in a great hurry; 'this paper has just been picked up.'

'What's in it?' said the Queen.

'I haven't opened it yet,' said the White Rabbit, 'but it seems to be a letter, written by the prisoner to--to somebody.'

'It must have been that,' said the King, 'unless it was written to nobody, which isn't usual, you know.'

'Who is it directed to?' said one of the jurymen.

'It isn't directed at all,' said the White Rabbit; 'in fact, there's nothing written on the outside.' He unfolded the paper as he spoke, and added 'It isn't a letter, after all: it's a set of verses.'

'Are they in the prisoner's handwriting?' asked another of they jurymen.

'No, they're not,' said the White Rabbit, 'and that's the queerest thing about it.' (The jury all looked puzzled.)

'He must have imitated somebody else's hand,' said the King. (The jury all brightened up again.)

'Please your Majesty,' said the Knave, 'I didn't write it, and they can't prove I did: there's no name signed at the end.'

'If you didn't sign it,' said the King, 'that only makes the matter worse. You must have meant some mischief, or else you'd have signed your name like an honest man.'

There was a general clapping of hands at this: it was the first really clever thing the King had said that day.

'That proves his guilt,' said the Queen.

'It proves nothing of the sort!' said Alice. 'Why, you don't even know what they're about!'

'Read them,' said the King.

The White Rabbit put on his spectacles. 'Where shall I begin, please your Majesty?' he asked.

'Begin at the beginning,' the King said gravely, 'and go on till you come to the end: then stop.'

These were the verses the White Rabbit read:--

'They told me you had been to her, And mentioned me to him: She gave me a good character, But said I could not swim.

He sent them word I had not gone (We know it to be true): If she should push the matter on, What would become of you?

I gave her one, they gave him two, You gave us three or more; They all returned from him to you, Though they were mine before.

If I or she should chance to be Involved in this affair, He trusts to you to set them free, Exactly as we were.

My notion was that you had been (Before she had this fit) An obstacle that came between Him, and ourselves, and it.

Don't let him know she liked them best, For this must ever be A secret, kept from all the rest, Between yourself and me.'

'That's the most important piece of evidence we've heard yet,' said the King, rubbing his hands; 'so now let the jury--'

'If any one of them can explain it,' said Alice, (she had grown so large in the last few minutes that she wasn't a bit afraid of interrupting him,) 'I'll give him sixpence. _I_ don't believe there's an atom of meaning in it.'

The jury all wrote down on their slates, 'She doesn't believe there's an atom of meaning in it,' but none of them attempted to explain the paper.

'If there's no meaning in it,' said the King, 'that saves a world of trouble, you know, as we needn't try to find any. And yet I don't know,' he went on, spreading out the verses on his knee, and looking at them with one eye; 'I seem to see some meaning in them, after all. "-said I could not swim--" you can't swim, can you?' he added, turning to the Knave.

The Knave shook his head sadly. 'Do I look like it?' he said. (Which he certainly did not, being made entirely of cardboard.)

'All right, so far,' said the King, and he went on muttering over the verses to himself: '"We know it to be true--" that's the jury, of course-- "I gave her one, they gave him two--" why, that must be what he did with the tarts, you know--'

'But, it goes on "they all returned from him to you,"' said Alice.

'Why, there they are!' said the King triumphantly, pointing to the tarts on the table. 'Nothing can be clearer than that. Then again--"before she had this fit--" you never had fits, my dear, I think?' he said to the Queen.

'Never!' said the Queen furiously, throwing an inkstand at the Lizard as she spoke. (The unfortunate little Bill had left off writing on his slate with one finger, as he found it made no mark; but he now hastily began again, using the ink, that was trickling down his face, as long as it lasted.)

'Then the words don't fit you,' said the King, looking round the court with a smile. There was a dead silence.

'It's a pun!' the King added in an offended tone, and everybody laughed, 'Let the jury consider their verdict,' the King said, for about the twentieth time that day.

'No, no!' said the Queen. 'Sentence first--verdict afterwards.'

'Stuff and nonsense!' said Alice loudly. 'The idea of having the sentence first!'

'Hold your tongue!' said the Queen, turning purple.

'I won't!' said Alice.

'Off with her head!' the Queen shouted at the top of her voice. Nobody moved.

'Who cares for you?' said Alice, (she had grown to her full size by this time.) 'You're nothing but a pack of cards!'

At this the whole pack rose up into the air, and came flying down upon her: she gave a little scream, half of fright and half of anger, and tried to beat them off, and found herself lying on the bank, with her head in the lap of her sister, who was gently brushing away some dead leaves that had fluttered down from the trees upon her face.

'Wake up, Alice dear!' said her sister; 'Why, what a long sleep you've had!'

'Oh, I've had such a curious dream!' said Alice, and she told her sister, as well as she could remember them, all these strange Adventures of hers that you have just been reading about; and when she had finished, her sister kissed her, and said, 'It was a curious dream, dear, certainly: but now run in to your tea; it's getting late.' So Alice got up and ran off, thinking while she ran, as well she might, what a wonderful dream it had been.

But her sister sat still just as she left her, leaning her head on her hand, watching the setting sun, and thinking of little Alice and all her wonderful Adventures, till she too began dreaming after a fashion, and this was her dream:--

First, she dreamed of little Alice herself, and once again the tiny hands were clasped upon her knee, and the bright eager eyes were looking up into hers--she could hear the very tones of her voice, and see that queer little toss of her head to keep back the wandering hair that would always get into her eyes--and still as she listened, or seemed to listen, the whole place around her became alive the strange creatures of her little sister's dream.

The long grass rustled at her feet as the White Rabbit hurried by--the frightened Mouse splashed his way through the neighbouring pool--she could hear the rattle of the teacups as the March Hare and his friends shared their never-ending meal, and the shrill voice of the Queen ordering off her unfortunate guests to execution--once more the pig-baby was sneezing on the Duchess's knee, while plates and dishes crashed around it--once more the shriek of the Gryphon, the squeaking of the Lizard's slate-pencil, and the choking of the suppressed guinea-pigs, filled the air, mixed up with the distant sobs of the miserable Mock Turtle.

So she sat on, with closed eyes, and half believed herself in Wonderland, though she knew she had but to open them again, and all would change to dull reality--the grass would be only rustling in the wind, and the pool rippling to the waving of the reeds--the rattling teacups would change to tinkling sheep-bells, and the Queen's shrill cries to the voice of the shepherd boy--and the sneeze of the baby, the shriek of the Gryphon, and all the other queer noises, would change (she knew) to the confused clamour of the busy farm-yard--while the lowing of the cattle in the distance would take the place of the Mock Turtle's heavy sobs.

Lastly, she pictured to herself how this same little sister of hers would, in the after-time, be herself a grown woman; and how she would keep, through all her riper years, the simple and loving heart of her childhood: and how she would gather about her other little children, and make their eyes bright and eager with many a strange tale, perhaps even with the dream of Wonderland of long ago: and how she would feel with all their simple sorrows, and find a pleasure in all their simple joys, remembering her own child-life, and the happy summer days.


ALICE'S ADVENTURES IN WONDERLAND

Lewis Carroll

THE MILLENNIUM FULCRUM EDITION 3.0

Table of Contents

I. Down the Rabbit-Hole

II. The Pool of Tears

III. A Caucus-Race and a Long Tale

IV. The Rabbit Sends in a Little Bill

V. Advice from a Caterpillar

VI. Pig and Pepper

VII. A Mad Tea-Party

VIII. The Queen's Croquet-Ground

IX. The Mock Turtle's Story

X. The Lobster Quadrille

XI. Who Stole the Tarts?


Performing Custom Painting: Examples (The Java™ Tutorials > Creating a GUI with JFC/Swing > Performing Custom Painting)

Trail: Creating a GUI with JFC/Swing
Lesson: Performing Custom Painting
Home Page > Creating a GUI with JFC/Swing > Performing Custom Painting
« Previous • Trail • Next »
Performing Custom Painting: Examples
The table that follows lists every example in the Performing Custom Painting lesson, with links to required files and to where each example is discussed. The first column of the table has links to JNLP files that let you run the examples using JavaTM Web Start.

NOTE: Release 6.0 is required to run all applets and Java Web Start examples. Most examples will run on an earlier release but you must compile and run them locally.

To run an example using Java Web Start, click the [Launch] link in the first column of the table. The first time you run an example, there will be a delay while Java Web Start downloads the JAR file containing the class files for this lesson's examples. Afterward, the examples should execute more quickly.

Compiling and Running the Examples Locally

The second column in the table below has links to zip files for each demo that you can open and run in the NetBeans IDE. Refer to Running Tutorial Examples in NetBeans IDE for more information.

You can get all of the source, image, and other files required for all these examples by downloading the Swing Tutorial Examples bundle, which contains the files in the correct hierarchy.

If you download an individual example, take care to have all the necessary files in the proper hierarchy when you compile and run it. All of the examples in the Swing tutorial are placed in a package. For example, the components examples are placed in a components package. See the following image for the complete structure. Note that any examples using images expect their image files to be in a directory named images that's in the same directory as the example's src files.

You can find out which files each example needs by consulting the following table or by looking at the comments at the beginning of each source file.

Table of Examples

Example | Source Files | Zip File (contains all files necessary for the example plus NetBeans IDE project metadata) | Image & Other Files | Where Described
SwingPaintDemo1 [Launch] | Swing Paint Demo 1 | SwingPaintDemo1.java |  | Creating the Demo Application (Step 1)
SwingPaintDemo2 [Launch] | Swing Paint Demo 2 | SwingPaintDemo2.java |  | Creating the Demo Application (Step 2)
SwingPaintDemo3 [Launch] | Swing Paint Demo 3 | SwingPaintDemo3.java |  | Creating the Demo Application (Step 3)
SwingPaintDemo4 [Launch] | Swing Paint Demo 4 | SwingPaintDemo4.java |  | Refining the Design
« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Getting Started with Swing: Examples (The Java™ Tutorials > Creating a GUI with JFC/Swing > Getting Started with Swing)

Trail: Creating a GUI with JFC/Swing
Lesson: Getting Started with Swing
Home Page > Creating a GUI with JFC/Swing > Getting Started with Swing
« Previous • Trail • Next »
Getting Started with Swing: Examples

Compiling and Running the Examples Locally

The second column in the table below has links to zip files for each demo that you can open and run in the NetBeans IDE. Refer to Running Tutorial Examples in NetBeans IDE for more information.

You can get all of the source, image, and other files required for all these examples by downloading the Swing Tutorial Examples bundle, which contains the files in the correct hierarchy.

If you download an individual example, take care to have all the necessary files in the proper hierarchy when you compile and run it. All of the examples in the Swing tutorial are placed in a package. For example, the components examples are placed in a components package. See the following image for the complete structure. Note that any examples using images expect their image files to be in a directory named images that's in the same directory as the example's src files.

Example Source Files Zip File
(contains all files necessary for the example plus NetBeans IDE project metadata) 		Image & Other Files Where Described
HelloWorldSwing Hello World Swing Project HelloWorldSwing.java Compiling and Running Swing Programs

« Previous • Trail • Next »
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page:
Next page:


Answers: Using Swing Components (The Java™ Tutorials > Creating a GUI with JFC/Swing > )

Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • TOC
Answers: Using Swing Components

Use the information in this lesson and the component how-to sections to help you complete these questions and exercises.

Questions

Question 1: Find the component that best fits each of the following needs. Write down both the component’s common name (such as “frame”) and find the component's how-to page online. [Hint: You can use A Visual Index to the Swing Components to help you answer this question.]

Question 1a: A component that lets the user pick a color.
Answer 1a: color chooser

Question 1b: A component that displays an icon, but that doesn’t react to user clicks.
Answer 1b: label

Question 1c: A component that looks like a button and that, when pressed, brings up a menu of items for the user to choose from.
Answer 1c: uneditable combo box

Question 1d: A container that looks like a frame, but that appears (usually with other, similar containers) within a real frame.
Answer 1d: internal frame

Question 1e: A container that lets the user determine how two components share a limited amount of space.
Answer 1e: split pane

Question 2: Which method do you use to add a menu bar to a top-level container such as a JFrame?
Answer 2: setJMenuBar

Question 3: Which method do you use to specify the default button for a top-level container such as a JFrame or JDialog?
Answer 3: JRootPane's setDefaultButton method. (You get the top-level container's root pane using the getRootPane method defined by the RootPaneContainer interface, which every top-level container implements.)

Question 4: Which method do you use to enable and disable components such as JButtons? What class is it defined in?
Answer 4: setEnabled, which is defined in the Component class

Question 5a: Which Swing components use ListSelectionModel? [Hint: The “Use” link at the top of the specification for each interface and class takes you to a page showing where in the API that interface or class is referenced.]
Answer 5a: JList and JTable

Question 5b: Do those components use any other models to handle other aspects of the components’ state? If so, list the other models’ types.
Answer 5b: JList also uses a ListModel, which holds the list's data. JTable uses a TableModel to hold its data and a TableColumnModel to manage the table's columns.

Question 6: Which type of model holds a text component’s content?
Answer 6: Document

Exercises

Exercise 1. Implement a program with a GUI that looks like the one shown below. Put the main method in a class named MyDemo1.

Answer 1: See MyDemo1.java (in a .java source file) . Here's the code that adds the bold, italicized text:

JLabel label = new JLabel("My Demo");
frame.getContentPane().add(BorderLayout.CENTER, label);
label.setFont(label.getFont().deriveFont(Font.ITALIC | Font.BOLD));
label.setHorizontalAlignment(JLabel.CENTER)

Exercise 2. Make a copy of MyDemo1.java named MyDemo2.java. Add a menu bar to MyDemo2.
Answer 2: See MyDemo2.java (in a .java source file) . The menu bar can be implemented with this code:

JMenu menu = new JMenu("Menu");
JMenuBar mb = new JMenuBar();
mb.add(menu);
frame.setJMenuBar(mb);

Exercise 3. Copy MyDemo1.java to MyDemo3.java. Add a button (JButton) to MyDemo3.java. Make it the default button.
Answer 3: See MyDemo3.java (in a .java source file) . Here's the code that adds the button and makes it the default button:

JButton b = new JButton("A button");
frame.getContentPane().add(BorderLayout.PAGE_END, b);
frame.getRootPane().setDefaultButton(b);

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Using Swing Components


Answers: Laying Out Components within a Container (The Java™ Tutorials > Creating a GUI with JFC/Swing > )

Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • TOC
Answers: Laying Out Components within a Container

Questions

In each of the following questions, choose the layout manager(s) most naturally suited for the described layout. Assume that the container controlled by the layout manager is a JPanel. [Hint: Two sections that might help are A Visual Index to Swing Components and Tips on Choosing a Layout Manager.]

Question 1. The container has one component that should take up as much space as possible

a. BorderLayout
b. GridLayout
c. GridBagLayout
d. a and b
e. b and c

Answer 1: d. BorderLayout and GridLayout easily deal with this situation. Although you could use GridBagLayout, it's much more complex than necessary.

Question 2. The container has a row of components that should all be displayed at the same size, filling the container’s entire area.

a. FlowLayout
b. GridLayout
c. BoxLayout
d. a and b

Answer 2: b. This type of same-size layout — whether in a row, a column, or a grid — is what GridLayout is best at.

Question 3. The container displays a number of components in a column, with any extra space going between the first two components.

a. FlowLayout
b. BoxLayout
c. GridLayout
d. BorderLayout

Answer 3: b. BoxLayout lays out components in either a column or a row. You can specify extra space using an invisible component.

Question 4. The container can display three completely different components at different times, depending perhaps on user input or program state. Even if the components’ sizes differ, switching from one component to the next shouldn’t change the amount of space devoted to the component.

a. SpringLayout
b. BoxLayout
c. CardLayout
d. GridBagLayout

Answer 4: c. CardLayout exists to allow components to share the same space. Although it's simpler to use a JTabbedPane component to control an area, CardLayout is the solution when you don't want tabs.

Exercises

Exercise 1. Implement the layout described and shown in question 1.
Answer 1: See Layout1.java (in a .java source file) . Here's the code that implements the layout:

JPanel p = new JPanel(new BorderLayout());
p.add(createComponent("Component 1"),
                      BorderLayout.CENTER);
frame.setContentPane(p);

Exercise 2. Implement the layout described and shown in question 2.
Answer 2: See Layout2.java (in a .java source file) . Here's the code that implements the layout:

JPanel p = new JPanel(new GridLayout(1,0));
p.add(createComponent("Component 1"));
p.add(createComponent("Component 2"));
p.add(createComponent("Component 3"));
p.add(createComponent("Component 4"));
frame.setContentPane(p);

Exercise 3. Implement the layout described and shown in question 3.
Answer 3: See Layout3.java (in a .java source file) . Here's the code that implements the layout:

JPanel p = new JPanel();
p.setLayout(new BoxLayout(p, BoxLayout.PAGE_AXIS));
p.add(createComponent("Component 1"));
p.add(Box.createVerticalGlue());
p.add(createComponent("Component 2"));
p.add(createComponent("Component 3"));
p.add(createComponent("Component 4"));
frame.setContentPane(p);

Exercise 4. Implement the layout described and shown in question 4.
Answer 4: See Layout4.java (in a .java source file) . Here's the code that implements the layout:

...//Where the radio buttons are set up:
for (int i= 0; i < strings.length; i++) {
    ...
    rb[i].setActionCommand(String.valueOf(i));
    ...
}

...//Where the panel to contain the shared-space components is set up:
cards = new JPanel(new CardLayout());
for (int i = 0; i < strings.length; i++) {
    cards.add(createComponent(strings[i]), String.valueOf(i));
}

...//In the action listener for the radio buttons:
public void actionPerformed(ActionEvent evt) {
    CardLayout cl = (CardLayout)(cards.getLayout());
    cl.show(cards, (String)evt.getActionCommand());
}

Exercise 5. By adding a single line of code, make the program you wrote for Exercise 2 display the components from right-to-left, instead of from left-to-right.

Answer 5: You can change the horizontal orientation using the setComponentOrientation method defined by the Component class. For example:

p.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT);
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Laying Out Components within a Container


Answers: Writing Event Listeners (The Java™ Tutorials > Creating a GUI with JFC/Swing > )

Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • TOC
Answers: Writing Event Listeners
Use this lesson’s tables, the component how-to sections and the event listeners how-to sections to complete these questions and exercises.

Questions

Question 1: What listener would you implement to be notified when a particular component has appeared on screen? What method tells you this information?
Answer 1: You would register a ComponentListener on the component. The componentShown method. This method is called when the window is first displayed or is deiconified.

Question 2: What listener would you implement to be notified when the user has finished editing a text field by pressing Enter? What listener would you implement to be notified as each character is typed into a text field? Note that you should not implement a general-purpose key listener, but a listener specific to text.
Answer 2: To be notified when the user presses Enter, you would register an ActionListener on the text field; the actionPerformed method is called when the user types Enter. Note that the Enter character is not part of the resulting string. To be notified as each character is typed, you would register a DocumentListener on the text field's Document. The insertUpdate method is then called as each character is typed. Note that this is not the correct way to implement input validation. For that behavior you should check out the Input Verification API section in How to Use the Focus Subsystem.

Question 3: What listener would you implement to be notified when a spinner’s value has changed? How would you get the spinner’s new value?
Answer 3: To be notified when the value has changed, you would register a ChangeListener on the spinner. You would get the new value through the event's source in the stateChanged method. The following code snippet shows how this could be done:

public void stateChanged(ChangeEvent e) {
    JSpinner mySpinner = (JSpinner)(e.getSource());
    SpinnerNumberModel model = (SpinnerNumberModel)(mySpinner.getModel());
    Number currentValue = model.getNumber();
    ...
}

Question 4: The default behavior for the focus subsystem is to consume the focus traversal keys, such as Tab and Shift Tab. Say you want to prevent this behavior in one of your application’s components. How would you accomplish this?
Answer 4: You call setFocusTraversalKeysEnabled(false) on that particular component. Note that you must then handle focus traversal manually. See How to Write a Key Listener and How to Use the Focus Subsystem for more information.

Exercises

Exercise 1. Take the Beeper.java (in a .java source file) example and add a text field. Implement it so that when the user has finishing entering data, the system beeps.
Answer 1: See Beeper1.java (in a .java source file)

Exercise 2. Take the Beeper.java (in a .java source file) example and add a selectable component that allows the user to enter a number from 1 to 10. For example, you can use a combo box, a set of radio buttons, or a spinner. Implement it so that when the user has selected the number, the system beeps that many times.
Answer 2: See Beeper2.java (in a .java source file)

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Writing Event Listeners


Questions

Question 1. What method defined by JComponent paints the inside of a component?
Answer 1: As described in How Swing Components Are Displayed, the paintComponent method paints a component's innards (with the exception of any children it contains).

Question 2. Which of the following code snippets paint a rectangle (filled or not) that is 100x100 pixels?

a. g.fillRect(x, y, 100, 100)
b. g.fillRect(x, y, 99, 99)
c. g.drawRect(x, y, 100, 100)
d. b and c
e. a and c

Answer 2: a. As noted in Introduction to Painting Concepts, drawRect methods paint lines just below the specified rectangle. So to get a 100x100 rectangle, you need to specify a width and height of 99, 99 to drawRect. For fillXxx methods, on the other hand, you specify exactly the desired width and height, so g.fillRect(x, y, 100, 100) results in a 100x100 rectangle.

Question 3. What code would you use to make a component perform the next painting operation using the background color at 50% transparency?
Answer 3: You can find the answer by looking at the faded rocketship code in Implementing a Custom Component and then modifying the specified amount of fading. Here's the result:

g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.5f));

Exercises

Exercise 1. Using a standard border and custom component painting, implement a component that has a preferred size of 250x100, is opaque by default, has a 5-pixel black border, and paints an “X” (using 5-pixel-thick lines) in the foreground color, as shown in the following figure.

Answer 1: See XMarksTheSpot.java, which you can run using ComponentDisplayer.java.

Here's the code that sets the border of the XMarksTheSpot component:

setBorder(BorderFactory.createMatteBorder(5,5,5,5, Color.BLACK));

Here's the X-drawing code from the paintComponent method of XMarksTheSpot:

Graphics2D g2 = (Graphics2D)g;
Insets insets = getInsets();
g2.setStroke(new BasicStroke(5.0f));
g2.draw(new Line2D.Double(insets.left,
                          insets.top,
                          getWidth() - insets.right,
                          getHeight() - insets.bottom));
g2.draw(new Line2D.Double(insets.left,
                          getHeight() - insets.bottom,
                          getWidth() - insets.right,
                          insets.top));

Exercise 2. Implement an icon that’s 10x10 pixels and paints a solid rectangle that fills the 10x10 area. If the icon’s component is enabled, the rectangle should be red; if disabled, gray. Make a copy of ButtonDemo.java that uses your custom Icon for the middle button, instead of displaying middle.gif. The following pictures show what the icon should look like.

Answer 2: See SquareIcon.java, which you can run using this modified ButtonDemo.java.

Here's the code that sets the icon:

Icon middleButtonIcon = new SquareIcon();
...
b2 = new JButton("Middle button", middleButtonIcon);

Here is SquareIcon's implementation of the three methods required by the Icon interface:

public void paintIcon(Component c, Graphics g, int x, int y) { if (c.isEnabled()) { g.setColor(Color.RED); } else { g.setColor(Color.GRAY); } g.fillRect(x, y, SIZE, SIZE); } public int getIconWidth() { return SIZE; } public int getIconHeight() { return SIZE; }

Exercise 3. Implement a border that paints a red 15-pixel-tall stripe all the way across the top of its component. Test this border by substituting it for the border on the component you created in exercise 1. The result should look like the following figure.

Answer 3: See StripeBorder.java, which you can run using ComponentDisplayer.java and XMarksTheSpot.java (be sure to uncomment the line that sets the border to StripeBorder). Here is StripeBorder's implementation of the three methods required by the Border interface: public void paintBorder(Component c, Graphics g, int x, int y, int width, int height) { g.setColor(Color.RED); g.fillRect(x, y, c.getWidth(), HEIGHT); } public Insets getBorderInsets(Component c) { return new Insets(HEIGHT, 0, 0, 0); } public boolean isBorderOpaque() { return true; }


Answers: Concurrency in Swing (The Java™ Tutorials > Creating a GUI with JFC/Swing > )

Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • TOC
Answers: Concurrency in Swing

Questions

Question 1: For each of the following tasks, specify which thread it should be executed in and why.
Answer 1:
  • Initializing the GUI. The event dispatch thread; most interactions with the GUI framework must occur on this thread.
  • Loading a large file. A worker thread. Executing this task on the event dispatch thread would prevent GUI events from being processed, "freezing" the GUI until the task is finished. Executing this task on an initial thread would cause a delay in creating the GUI.
  • Invoking javax.swing.JComponent.setFont to change the font of a component. The event dispatch thread. As with most Swing methods, it is not safe to invoke setFont from any other thread.
  • Invoking javax.swing.text.JTextComponent.setText to change the text of a component. This method is documented as thread-safe, so it can be invoked from any thread.

Question 2: One thread is not the preferred thread for any of the tasks mentioned in the previous question. Name this thread and explain why its applications are so limited.
Answer 2: The initial threads launch the first GUI task on the event dispatch thread. After that, a Swing program is primarily driven by GUI events, which trigger tasks on the event dispatch thread and the worker thread. Usually, the initial threads are left with nothing to do.

Question 3: SwingWorker has two type parameters. Explain how these type parameters are used, and why it often doesn't matter what they are.
Answer 3: The type parameters specify the type of the final result (also the return type of the doInBackground method) and the type of interim results (also the argument types for publish and process). Many background tasks do not provide final or interim results.

Exercises

Question 1: Modify the Flipper example so that it pauses 5 seconds between "coin flips." If the user clicks the "Cancel", the coin-flipping loop terminates immediately.
Answer 1: See the source code for Flipper2. The modified program adds a delay in the central doInBackground loop:
protected Object doInBackground() {
    long heads = 0;
    long total = 0;
    Random random = new Random();
    while (!isCancelled()) {
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            //Cancelled!
            return null;
        }
        total++;
        if (random.nextBoolean()) {
            heads++;
        }
        publish(new FlipPair(heads, total));
    }
    return null;
}
The try ... catch causes doInBackground to return if an interrupt is received while the thread is sleeping. Invoking cancel with an argument of true ensures that an interrupt is sent when the task is cancelled.
« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Previous page: Questions and Exercises: Concurrency in Swing


Answers: Learning Swing with the NetBeans IDE (The Java™ Tutorials > Creating a GUI with JFC/Swing > )

Trail: Creating a GUI with JFC/Swing
Home Page > Creating a GUI with JFC/Swing
« Previous • TOC
Answers: Learning Swing with the NetBeans IDE

Questions

Question 1: When creating this new project, we left the "Create Main Class" checkbox deselected. Why?
Answer 1: We left this checkbox deselected because the CelsiusConverterGUI is the application's main entry point.

Question 2: The _____ contains all of the components offered by the Swing API.
Answer 2: Palette

Question 3: What is the purpose of the Design Area?
Answer 3: The Design Area is where you visually arrange the various components of the application's GUI. It cuts development time because all of the application's layout code is auto-generated.

Question 4: Explain the difference between the Source and Design tabs.
Answer 4: These tabs provide two different views of the same application. The Design tab shows what the application actually looks like, and the Source tab shows its source code. Some portions of the source tab are auto-generated and not directly editable by the user.

Question 5: Name some advantages to editing an object with the Property Editor (as opposed to editing it directly in the source code.)
Answer 5: Using the property editor elimates typing errors, accidental modification of the wrong code, and provides a listing of all properties exposed by a particular object.

Question 6:This lesson used Swing objects of three different types. What were they?
Answer 6: JLabel, JButton, and JTextField

Question 7:In the Design Area, describe the process for setting two components to the same width.
Answer 7: Shift-click the two target components; this will highlight each showing that they are selected. Right-click (control-click for mac users) Same Size -> Same Width. The components will now be the same width.

Exercises

  1. Use the property editor to change the appearance of this application. Experiment by changing some values and seeing what effect your changes have. This is a quick and easy way to explore the properties of the various Swing components.
Below we've modified the application to use DialogInput font, and have changed the cursor to a hand cursor.

Figure showing a modified CelsiusConverter application.

A modified CelsiusConverter Application.

« Previous • TOC
Problems with the examples? Try Compiling and Running the Examples: FAQs.
Complaints? Compliments? Suggestions? Give us your feedback.

Your use of this page (http://java.sun.com/docs/books/tutorial (Last Updated 2/14/2008)) and all the material on pages under "The Java Tutorials" banner is subject to the Terms of Use. Additionally, (i) any example code contained in any of these Java Tutorials pages is also licensed under the Code Sample License, and (ii) the entire Java Tutorials content is available for download under the Java Tutorials Limited Non-Commercial License for limited, non-commercial individual and/or research and instructional use at Sun Download Center.

 About Sun | About This Site | Terms of Use | Trademarks A Sun Developer Network Site
Copyright 1995-2008 Sun Microsystems, Inc.
Previous page: Questions and Exercises: Learning Swing with the NetBeans IDE


Questions

1. What method defined by JComponent paints the inside of a component?

2. Which of the following code snippets paint a rectangle (filled or not) that is 100x100 pixels?

a. g.fillRect(x, y, 100, 100)
b. g.fillRect(x, y, 99, 99)
c. g.drawRect(x, y, 100, 100)
d. b and c
e. a and c

3. What code would you use to make a component perform the next painting operation using the background color at 50% transparency?

Exercises

1. Using a standard border and custom component painting, implement a component that has a preferred size of 250x100, is opaque by default, has a 5-pixel black border, and paints an “X” (using 5-pixel-thick lines) in the foreground color, as shown in the following figure.

2. Implement an icon that’s 10x10 pixels and paints a solid rectangle that fills the 10x10 area. If the icon’s component is enabled, the rectangle should be red; if disabled, gray. Make a copy of ButtonDemo.java that uses your custom Icon for the middle button, instead of displaying middle.gif. The following pictures show what the icon should look like.

3. Implement a border that paints a red 15-pixel-tall stripe all the way across the top of its component. Test this border by substituting it for the border on the component you created in exercise 1. The result should look like the following figure.