Return-Path: <env_37792749-1992895016@hermes.sun.com>
Received: from po10.mit.edu (po10.mit.edu [18.7.21.66]) (authenticated user=env_37792749-1992895016@hermes.sun.com bits=0)
	by po10.mit.edu (Cyrus v2.1.5) with LMTP; Tue, 15 Jul 2003 15:06:49 -0400
X-Sieve: CMU Sieve 2.2
Received: from po10.mit.edu by po10.mit.edu (8.12.4/4.7) id h6FJ6nNP005815; Tue, 15 Jul 2003 15:06:49 -0400 (EDT)
Received: (from mdefang@localhost)
	by po10.mit.edu (8.12.4/8.12.4/Submit) id h6FJ6m0U005809
	for <alexp+Spamscreen@PO10.LOCAL>; Tue, 15 Jul 2003 15:06:48 -0400 (EDT)
Received: from hermes.sun.com (hermes.sun.com [64.124.140.169])
	by pacific-carrier-annex.mit.edu (8.12.4/8.9.2) with SMTP id h6FJ6j6G019750
	for <alexp@mit.edu>; Tue, 15 Jul 2003 15:06:45 -0400 (EDT)
Date: 15 Jul 2003 10:20:17 -0800
From: "SDN - Core Java Technologies Tech Tips" <sunmail@hermes.sun.com>
To: alexp@mit.edu
Message-Id: <37792749-1992895016@hermes.sun.com>
Subject: Core Java Technologies Tech Tips, July 15, 2003 (Preferences API, Interfaces and Constants)
Mime-Version: 1.0
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-Mailer: SunMail 1.0
X-Spam-Score: 2.6
X-Spam-Level: ** (2.6)
X-Spam-Flag: YES
X-Scanned-By: MIMEDefang 2.28 (www . roaringpenguin . com / mimedefang)

<!DOCtype HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<html>
<head>
<title>Core Java Technologies Technical Tips</title>

<style type="text/css">

code {color: #333333; font-family: verdana, courier, monospace; font-size: 10pt}
pre {color: #333333; font-family: verdana, courier, monospace; font-size: 10pt}
body, div, span {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
td, th {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
tr {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
table {font-family: arial, helvetica, sans-serif; font-size: 10pt}
p {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
li {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
br {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
div {color: #666699; font-family: arial, helvetica, sans-serif; font-size: 10pt}
sup {font-family: arial, helvetica, sans-serif; font-size: 5pt}
h3 {color: #666699; font-family: arial, helvetica, sans-serif; font-size: 11pt}
h4, b {color: #666699; font-family: arial, helvetica, sans-serif; font-size: 10pt}
blockquote, input, select {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
ul, ol {color: #333333; font-family: arial, helvetica, sans-serif; font-size: 10pt}
a:link {font-size: 10pt; font-family: arial, helvetica, sans-serif; color:#666699 }
span.purple {font-weight: bold; color: #666699; font-family: arial, helvetica, sans-serif; font-size: 10pt}
span.small {font-size: 8pt; font-family: arial, helvetica, sans-serif; color:#333333 }
span.link {font-size: 8pt; font-family: arial, helvetica, sans-serif; color:#666699 }
</style>

</head>

<body bgcolor="#ffffff">
<a name="top"></a>
<table border="0" cellpadding="0" cellspacing="0" width="611">
<tr>
<td colspan="3" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>

<tr>
<td bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>

<td>
<table border="0" cellpadding="0" cellspacing="0" width="611">
<tr>
<td colspan="2"><a href="http://bulkmail2.sun.com/CTServlet?id=37792749-1992895016:1058289293190"><img src="http://developer.java.sun.com/images/headers/core_ttips_hdr.jpg" width="611" height="160" alt="Core Java Technologies Technical Tips" border="0"></a></td>
</tr>

<tr>
<td colspan="2" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>

<!-- ================== -->
<!-- Start Main Content -->
<!-- ================== -->

<tr>
<td height="20">&nbsp;&nbsp;&nbsp;<a href="http://bulkmail2.sun.com/CTServlet?id=37792749-1992895016:1058289293209" style="text-decoration:none;">View this issue as simple text</a></td>
<td align="right" height="20"><span class="purple">July 15, 2003</span>&nbsp;&nbsp;&nbsp;&nbsp;</td>
</tr>

<tr><td colspan="2">

<table border="0" cellpadding="10" cellspacing="0" width="100%">
<tr>
<td>
     
<form method="get" action="http://search.java.sun.com/search/java/">   
<table border="0" cellpadding="3" cellspacing="0" width="100%">
<tr> 
<td align="left" valign="middle" width="20%"><h3>In this Issue</h3></td>
              
<td valign="middle" align="right" width="70%">
<font size="2">
<input type="text" size="15" maxlength="128" name="qt"></font></td>
            
<td valign="middle" width="55">
<input type="image" src="http://developer.java.sun.com/images/v4a_search.gif" alt="Search" value="search" border="0" width="55"></td>
</tr>
</table>
</form>

<p>
Welcome to the Core Java Technologies Tech Tips, July 15, 2003. Here you'll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE).
</p>

<p>
This issue covers:
</p>

<p>
<a href="#1"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt=".">Using the <code>Preferences</code> API</a><br>    
<a href="#2"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt=".">Interfaces and Constants</a>
</p>

<p>
These tips were developed using Java 2 SDK, Standard Edition, v 1.4. 
</p>

<p>
This issue of the Core Java Technologies Tech Tips is written by Daniel Steinberg, Director of Java Offerings for Dim Sum Thinking, Inc, and editor-in-chief for <a href="http://bulkmail2.sun.com/CTServlet?id=37792749-1992895016:1058289293102">java.net</a>.
</p>

<p>
See the Subscribe/Unsubscribe note at the end of this newsletter to subscribe to Tech Tips that focus on technologies and products in other Java platforms.
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<a name="1"></a>

<h3>USING THE PREFERENCES API</h3>

<p>
There are many times when you need to persist configuration 
information for an application. In the past, you might have used 
<code>java.util.Properties</code> to save details about the preferred date 
format for an application, the preferred window size or location, 
or the previous time that a user logged into an application. The 
<code>Properties</code> class required you to write to and read from streams. 
This, in turn, meant that you had to manage where the properties 
files were stored in your file system. In other words, much of 
your effort was spent managing details that had little to do with 
the information being managed.
</p>

<p>
The <code>Preferences</code> API introduced in J2SE 1.4 provides a convenient 
framework for storing and recalling data about user-specific 
preferences or system-wide preferences. In this tip, you'll learn
how to use the <code>Preferences</code> API to store and recall user-specific 
preferences. 
</p>

<p>
First, here's a little background about how preferences data is 
organized. Data about user and system preferences is organized 
into hierarchical collections called nodes. Multiple nodes exist 
in a tree. There are two types of trees: one for user preferences 
and one for system preferences. There is a separate preference 
tree for each user. But there is only one system preference tree
for the entire system. Note that even though data about 
user-specific preferences and system-wide preferences are in 
different trees, the techniques for storing and recalling system 
preferences are the same as those shown in this tip.
</p>

<p>
This first step in using the <code>Preferences</code> API is to get a handle 
to a <code>Preferences</code> object for this class. To do this, pass the 
factory method <code>useNodeForPackage()</code> an object of type <code>Class</code>.
</p>

<pre>
   import java.util.prefs.Preferences;
   import java.awt.Dimension;

   public class UserPreferences {
      private Preferences userPrefs;

      public UserPreferences(){
        userPrefs = Preferences.userNodeForPackage(
                                UserPreferences.class);
   }
}
</pre>

<p>
This gives you an instance of a <code>Preferences</code> object that you can 
use to read from and write to the stored data. For this tip, 
let's use the <code>Preferences</code> instance to store and retrieve the 
dimensions of a <code>JFrame</code>. This is shown in the following code:
</p>

<pre>
   import java.util.prefs.Preferences;
   import java.awt.Dimension;
   import javax.swing.JFrame;

   public class UserPreferences extends JFrame{
      private Preferences userPrefs;

      public UserPreferences(){
        userPrefs = Preferences.userNodeForPackage(
                               UserPreferences.class);
        setToPreferredSize();
      }
 
      public void setToPreferredSize(){
        int width = userPrefs.getInt(&quot;width&quot;, 100);
        int height = userPrefs.getInt(&quot;height&quot;, 200);
        setSize(width, height);
      }

      public Dimension getDimensions(){
        int width = userPrefs.getInt(&quot;width&quot;, 100);
        int height = userPrefs.getInt(&quot;height&quot;, 200);
        return new Dimension(width, height);
      }

      public void putDimensions( Dimension dimension){
        userPrefs.putInt(
                   &quot;width&quot;, (int)dimension.getWidth());
        userPrefs.putInt(
                 &quot;height&quot;, (int)dimension.getHeight());
      }

   }

</pre>

<p>
In this class, the <code>setToPreferredSize()</code> method is used to 
retrieve the height and width, and set the <code>JFrame</code>'s size to these dimensions. The <code>putDimensions()</code> method is used to persist <code>int</code> values for the height and width. These methods, in turn, call the <code>getInt()</code> and <code>putInt()</code> methods of the <code>Preferences</code> class.
</p>

<p>
The <code>getInt()</code> method in the <code>Preferences</code> class takes two arguments. The first is a <code>String</code> that acts as the key for the property being stored. The second argument is an <code>int</code> that is used as the default value. If the property has not yet been set, then the default value is used. Similarly the <code>putInt()</code> method takes two arguments. 
The first is the key, and the second is the value of the property 
being set.
</p>

<p>
Now let's exercise the code. The following program creates a 
<code>JFrame</code>, setting the size based on data read from the <code>Preferences</code> object. The dimensions in the <code>Preferences</code> object are initially 
width 100 and height 200. In the program, they're reset to width 
200 and height 300. A print statement and a call to <code>setVisible()</code> have been added so you can see the effects.
</p>

<pre>
   import java.util.prefs.Preferences;
   import java.awt.Dimension;
   import javax.swing.JFrame;

   public class UserPreferences extends JFrame{
      private Preferences userPrefs;

      public UserPreferences(){
        userPrefs = Preferences.userNodeForPackage(
                               UserPreferences.class);
        setToPreferredSize();
        setVisible(true);
      }
 
      public void setToPreferredSize(){
        int width = userPrefs.getInt(&quot;width&quot;, 100);
        int height = userPrefs.getInt(&quot;height&quot;, 200);
        setSize(width, height);
        System.out.println(&quot;Width = &quot;+ getWidth() +
                         &quot; Height = &quot; + getHeight());
      }

      public Dimension getDimensions(){
        int width = userPrefs.getInt(&quot;width&quot;, 100);
        int height = userPrefs.getInt(&quot;height&quot;, 200);
        return new Dimension(width, height);
      }

      public void putDimensions( Dimension dimension){
        userPrefs.putInt(
                   &quot;width&quot;, (int)dimension.getWidth());
        userPrefs.putInt(
                 &quot;height&quot;, (int)dimension.getHeight());
      }

      public static void main(String[] args){
        new UserPreferences().putDimensions(
                               new Dimension(200,300));
      }
   }

</pre>

<p>
Run this program, and you should get the following results:
</p>

<pre>
   Width = 100 Height = 200
</pre>

<p>
Run the program a second time, and you should get the following 
results:
</p>

<pre>
   Width = 200 Height = 300
</pre>

<p>
The width and height have been successfully saved, and so the 
values are saved between runs of the program. 
</p>

<p>
If you want to add the ability to clear the values from memory, 
add the following method to <code>UserPreferences.java</code>.
</p>

<pre>
   public void clearPreferences(){
      try {
        userPrefs.clear();
      } catch (BackingStoreException e) {
        e.printStackTrace();
      }
  }
</pre>

<p>
Also add the <code>import</code> statement for <code>BackingStoreException</code>. A call to the <code>clearPreferences()</code> method will result in the use of the default values when you call the <code>setToPreferredSize()</code> method.  
</p>

<p>
You can also implement a listener, specifically 
<code>PreferenceChangeListener</code>, for changes in preferences. For 
example, let's set up the <code>JFrame</code> to implement 
<code>PreferenceChangeListener</code>, and so respond to changes in the 
preferences. In addition to extending <code>JFrame</code>, <code>UserPreferences</code> can also implement <code>PreferenceChangeListener</code>. The only requirement is that you implement <code>PreferenceChangeListener</code>'s one method: <code>preferenceChange()</code>. When a change to the preferred 
dimensions is discovered, the appropriate action is to change the 
dimensions of the <code>JFrame</code> by calling <code>setToPreferredSize()</code>.
</p>

<pre>
  public void preferenceChange(PreferenceChangeEvent e){
      setToPreferredSize();
  }
</pre>

<p>
Other changes you can make to the code include adding methods to 
select and set the random <code>int</code>s that are stored as preferences, 
and adding a call to the <code>resetManyTimes()</code> method in <code>main()</code>. The revised code looks like this.  
</p>

<pre>
   import javax.swing.JFrame;
   import java.util.prefs.Preferences;
   import java.util.prefs.PreferenceChangeListener;
   import java.util.prefs.PreferenceChangeEvent;

   public class UserPreferences extends JFrame 
                implements PreferenceChangeListener{
     private Preferences userPrefs;

     public UserPreferences(){
       userPrefs = Preferences.userNodeForPackage(
                              UserPreferences.class);
       userPrefs.addPreferenceChangeListener(this);
       setToPreferredSize();
       setVisible(true);
     }

     public void setToPreferredSize(){
       int width = userPrefs.getInt(&quot;width&quot;, 100);
       int height = userPrefs.getInt(&quot;height&quot;, 200);
       setSize(width, height);
       System.out.println(&quot;Width = &quot;+ getWidth() +
           &quot; Height = &quot;+ getHeight());
     }

       public void resetDimensionsManyTimes(){
       for (int i = 0; i&lt;10;i++){
         putRandomDimensions();
         try {
           Thread.sleep(1000);
         } catch (InterruptedException e) {
           e.printStackTrace();
         }
       }
     }

     private void putRandomDimensions(){
       userPrefs.putInt(&quot;width&quot;, getRandomInt());
       userPrefs.putInt(&quot;height&quot;, getRandomInt());
     }

     private int getRandomInt(){
       return (int)(Math.random()*300+100);
     }

     public void preferenceChange(PreferenceChangeEvent e){
         setToPreferredSize();
     }

     public static void main(String[] args){
       new UserPreferences().resetDimensionsManyTimes();
     }

   }
</pre>

<p>
Run the application and you should see the <code>JFrame</code> change size ten times.
</p>

<p>
For more information on the <code>Preferences</code> APIs, see the its 
description in the <a href="http://bulkmail2.sun.com/CTServlet?id=37792749-1992895016:1058289293142">J2SE 1.4.1 documentation</a>.
</p>


<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">
<tr>
<td>
<div align="right">
<a href="#top">back to top<img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt="image"></a>
</div>
</td>
</tr>

<tr>
<td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<a name="2"></a>

<h3>INTERFACES AND CONSTANTS</h3>

<p>
When you want to use global constants in an application, it is 
often tempting to define the constants in an interface and then 
implement the interface in the class using the constants. For 
example, suppose you have the following interface that contains 
approximations for the numbers pi and e.
</p>

<pre>
   public interface TranscendentalConstants {
      public static final double PI = 3.14159;
      public static final double E = 2.71828;
   }
</pre>

<p>
Suppose too that you have a second collection of constants that 
contains approximations for the square roots of two and three.
</p>

<pre>
   public interface IrrationalConstants {
      public static final double SQRT_TWO = 1.414;
      public static final double SQRT_THREE = 1.732;
   }
</pre>

<p>
A common strategy for using these constants is to create a class 
like the following.
</p>

<pre>
   public class BadUseOfConstants implements 
        TranscendentalConstants, IrrationalConstants {

      public double sinPiOverFour(){
        return SQRT_TWO / 2;
      }

      public double sinPiOverThree(){
        return SQRT_THREE / 2;
      }

      private void outputResults() {
        System.out.println(&quot;Pi is approximately &quot; + PI);
        System.out.println(
                   &quot;The sin of Pi/4 is approximately &quot; + 
                   sinPiOverFour());
        System.out.println(
                   &quot;The sin of Pi/3 is approximately &quot; + 
                   sinPiOverThree());
      }

      public static void main(String[] args) {
        new BadUseOfConstants().outputResults();
      }
  }
</pre>

<p>
Even though this code runs, it is an improper use of interfaces. 
That's because <code>BadUseOfConstants</code> is not an extension of the type 
<code>TranscendentalConstants</code>. Instead, <code>BadUseOfConstants</code> is a consumer 
of <code>TranscendentalConstants</code>. There are two reasons why using 
interfaces in this way is so attractive. First, you can easily 
use constants defined in two different interfaces. If the 
constants were used in different classes instead, multiple 
inheritance would be required to perform the same task. Second, 
by implementing the interfaces, you can refer to the constants
without qualifying them as <code>SQRT_TWO</code> instead of as 
<code>IrrationalConstants.SQRT_TWO</code>.
</p>

<p>
You can address this second problem of having to qualify constants
by caching the variables locally like this.
</p>

<pre>
   public class OKUseOfConstants {

     private double PI = TranscendentalConstants.PI;
     private double SQRT_TWO = 
                          IrrationalConstants.SQRT_TWO;
     private double SQRT_THREE = 
                        IrrationalConstants.SQRT_THREE;

     public double sinPiOverFour() {
       return SQRT_TWO / 2;
     }

     public double sinPiOverThree() {
       return SQRT_THREE / 2;
     }

     public void outputResults() {
       System.out.println(&quot;Pi is approximately &quot; + PI);
       System.out.println(
           &quot;The sin of Pi/4 is approximately &quot; +
           sinPiOverFour());
       System.out.println(
           &quot;The sin of Pi/3 is approximately &quot; +
           sinPiOverThree());
     }

     public static void main(String[] args) {
       new OKUseOfConstants().outputResults();
     }
   }
</pre>

<p>
When J2SE 1.5 is released, a new mechanism for importing specific 
constants will be introduced that will address both of these 
issues. In the meantime, you might want to introduce an inner 
class or a different class that collects all of the interfaces
containing the constants you want to use. Here's an example. In 
the <code>BetterUseOfConstants</code> program that follows, the inner class 
<code>ConstantCollector</code> is used to collect the constants declared in 
<code>TranscendentalConstants</code> and <code>IrrationalConstants</code>.
</p>

<pre>
   public class BetterUseOfConstants {

      private ConstantCollector constants = 
                               new ConstantCollector();

      public double sinPiOverFour(){
        return constants.SQRT_TWO / 2;
      }

      public double sinPiOverThree(){
        return constants.SQRT_THREE / 2;
      }
      
      private void outputResults() {
        System.out.println(
                               &quot;Pi is approximately &quot; + 
                               constants.PI);
        System.out.println(
                  &quot;The sin of Pi/4 is approximately &quot; + 
                  sinPiOverFour());
        System.out.println(
                  &quot;The sin of Pi/3 is approximately &quot; + 
                  sinPiOverThree());
      }

      public static void main(String[] args) {
        new BetterUseOfConstants().outputResults();
      }
      
      private class ConstantCollector implements 
       TranscendentalConstants, IrrationalConstants{}
      }
</pre>

<p>      
Running this code should produce the following results:
</p>

<pre>
   Pi is approximately 3.14159
   The sin of Pi/4 is approximately 0.707
   The sin of Pi/3 is approximately 0.866      
</pre>

<p>
In this case <code>ConstantCollector</code> is a type extension of the two 
interfaces.
</p>

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">

<tr>
<td>
<div align="right">
<a href="#top">back to top<img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt="image"></a>
</div>
</td></tr>

<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td></tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<form method="POST" action="http://developer.java.sun.com/servlet/jdc.survey.TabulationServlet">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td></tr>

<tr><td>
<h3>Reader Feedback</h3> 

<input type="hidden" name="survey_id" value="2600">
<input type="hidden" name="anonymous" value="True">
<input type="hidden" name="answer_count" value="3">
<input type="hidden" name="answer1" value="MayCore_tt062003">
<input name="answer2" type="radio" value="2">&nbsp; Very worth reading&nbsp; 
<input name="answer2" type="radio" value="1">&nbsp; Worth reading&nbsp; 
<input name="answer2" type="radio" value="0">&nbsp; Not worth reading&nbsp; 
 
<p>
If you have other comments or ideas for future technical tips, please type them  here: 
</p>
 
<p>
<textarea name="answer3" rows="6" cols="50"></textarea> 
</p>
 
<p>
<input type="Submit" value="Submit"> &nbsp; <input type="Reset"> 
</p>

<p> 
Have a question about Java programming? Use  
<a href="http://bulkmail2.sun.com/CTServlet?id=37792749-1992895016:1058289293221">Java Online Support.</a> 
</p>

</td></tr></table>
</form> 

<table width="100%" border="0" cellspacing="0" cellpadding="0" align="center">
<tr>
<td>
<div align="right">
<a href="#top">back to top<img src="http://developer.java.sun.com/images/back_to_top.gif" border="0" alt="image"></a>
</div>
</td></tr>

<tr><td bgcolor="#ffffff" height="2"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td></tr>

<!-- Grey Horizontal Line Begins Here -->

<tr>
<td bgcolor="#cccccc" height="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" alt="." border="0"></td>
</tr>
</table> 

<!-- Grey Horizontal Line ends Here -->

<br>

<span class="small">IMPORTANT: Please read our Terms of Use, Privacy, and Licensing policies:<br>
<a href="http://www.sun.com/share/text/termsofuse.html"><span class="link">http://www.sun.com/share/text/termsofuse.html</span></a><br>
<a href="http://www.sun.com/privacy/"><span class="link">http://www.sun.com/privacy/</span></a><br> 
<a href="http://developer.java.sun.com/berkeley_license.html"><span class="link">http://developer.java.sun.com/berkeley_license.html</span></a>
</span><br><br>


<span class="small">
Comments? Send your feedback on the Core Java Technologies Tech Tips to: <a href="http://bulkmail2.sun.com/CTServlet?id=37792749-1992895016:1058289293154"><span class="link">http://developers.sun.com/contact/feedback.jsp?category=sdn</span></a>
</span><br><br>

<span class="small">
Subscribe to other Java developer Tech Tips:
</span><br><br>

<span class="small">
- Enterprise Java Technologies Tech Tips. Get tips on using enterprise Java technologies and APIs, such as those in the Java 2 Platform, Enterprise Edition (J2EE).<br>
- Wireless Developer Tech Tips. Get tips on using wireless Java technologies and APIs, such as those in the Java 2 Platform, Micro Edition (J2ME).<br><br>
</span>
   
<span class="small">
To subscribe to these and other JDC publications:<br>
- Go to the JDC Newsletters and Publications page, choose the newsletters you want to <a href="http://bulkmail2.sun.com/CTServlet?id=37792749-1992895016:1058289293167"><span class="link">subscribe</span></a> to and click &quot;Update&quot;.<br>
  - To unsubscribe, go to the <a href="http://bulkmail2.sun.com/CTServlet?id=37792749-1992895016:1058289293167"><span class="link">subscriptions page</span></a>, uncheck the appropriate checkbox, and click &quot;Update&quot;.
</span><br><br>

<span class="small">ARCHIVES: You'll find the Core Java Technologies Tech Tips archives at:<br>
<a href="http://bulkmail2.sun.com/CTServlet?id=37792749-1992895016:1058289293238"><span class="link">http://java.sun.com/jdc/TechTips/index.html</span></a>
</span><br><br>

<span class="small">Copyright 2003 <a href="http://bulkmail2.sun.com/CTServlet?id=37792749-1992895016:1058289293250"><span class="link">Sun Microsystems, Inc.</span></a> All rights reserved.
<br>4150 Network Circle, Santa Clara, CA 95054 USA.
</span><br><br>

<span class="small">This document is protected by copyright. For more information, see:
<br><a href="http://java.sun.com/jdc/copyright.html"><span class="link">http://java.sun.com/jdc/copyright.html</span></a>
</span><br><br>

<span class="small">Java, J2SE, J2EE, J2ME, and all Java-based marks are trademarks or registered trademarks (<a href="http://www.sun.com/suntrademarks/"><span class="link">http://www.sun.com/suntrademarks/</span></a>) of Sun Microsystems, Inc. in the United States and other countries.</span>
<br><br>

<!-- ================ -->
<!-- End Main Content -->
<!-- ================ -->

<center>
<a href="http://bulkmail2.sun.com/CTServlet?id=37792749-1992895016:1058289293250"><img src="http://developer.java.sun.com/images/lgsun.gif" border="0" alt="Sun Microsystems, Inc."></a>
</center>

</td>
</tr>
</table>

</td></tr>
</table>
</td>

<td bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>
<tr>
<td colspan="3" bgcolor="#cccccc" width="1"><img src="http://developer.java.sun.com/images/pixel.gif" width="1" height="1" border="0" alt="."></td>
</tr>
</table>

<br><br><table bgcolor = "#efefef"><tr><td><a href="http://subscriptions.sun.com/unsubscribe?37792749-1992895016">Please unsubscribe me from this newsletter.</a></td></tr></table><br><br><img src="http://bulkmail2.sun.com/OTServlet?id=37792749-1992895016" width=1 height=1></body>
</html>


