Return-Path: <env_263585151282598993@hermes.sun.com>
Received: from fort-point-station.mit.edu by po10.mit.edu (8.9.2/4.7) id SAA27734; Tue, 3 Dec 2002 18:39:42 -0500 (EST)
Received: from hermes.sun.com (hermes.sun.com [64.124.140.169])
	by fort-point-station.mit.edu (8.9.2/8.9.2) with SMTP id SAA15936
	for <alexp@mit.edu>; Tue, 3 Dec 2002 18:39:42 -0500 (EST)
Date: 3 Dec 2002 13:57:12 -0800
From: "JDC Tech Tips" <JDC_Tech_Tips@hermes.sun.com>
To: alexp@mit.edu
Message-Id: <263585151282598993@hermes.sun.com>
Subject: Core Java Technologies Tech Tips, Dec. 3, 2002 (BitSet, JSpinner)
Mime-Version: 1.0
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit
X-Mailer: SunMail 1.0

<!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="image"></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="image"></td>

<td>
<table border="0" cellpadding="0" cellspacing="0" width="611">
<tr>
<td colspan="2"><a href="http://developer.java.sun.com" target="_blank"><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="image"></td>
</tr>

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

<tr>
<td height="20">&nbsp;&nbsp;&nbsp;<a href="http://developer.java.sun.com/developer/TechTips/txtarchive/2002/Dec02_GlenM.txt?s=06&w=49" target="_blank" style="text-decoration:none;" target="_blank">View this issue as simple text</a></td>
<td align="right" height="20"><span class="purple">December 3, 2002</span>&nbsp;&nbsp;&nbsp;&nbsp;</td>
</tr>

<tr><td colspan="2">

<FORM METHOD="GET" ACTION="http://search.java.sun.com/search/java/" target="_blank">
<table border="0" cellpadding="10" cellspacing="0" width="100%">
<tr>
<td>
        
<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<sup>TM</sup> Technologies Tech Tips, December 3, 2002. Here you'll get tips on using core Java technologies and APIs, such as those in Java 2 Platform, Standard Edition (J2SE<sup>TM</sup>).
</p>

<p>
This issue covers:
</p>

<a href="#1"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt="">Using the BitSet Class</a>
<br>    
<a href="#2"><img src="http://developer.java.sun.com/images/anchor.gif" border="0" alt="">Using JSpinner to Choose From an Ordered List</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 Glen McCluskey.</a> 
</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="Pixel" border="0"></td>
</tr>
</table> 

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

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

<h3>USING THE BITSET CLASS</h3>

<p>
<code>BitSet</code> is a class you use to represent vectors of bits or true/false values. You can represent bitmaps and similar kinds of structures with <code>BitSet</code> objects. <code>BitSets</code> grow dynamically as new bits are set.
</p>

<p>
To start the discussion of <code>BitSet</code>, let's look at an example:
</p>

<pre>
    import java.util.BitSet;
    
    public class BitSet1 {
        public static void main(String args[]) {
    
            // create a BitSet
    
            BitSet bitset = new BitSet();
    
            // set the 0th and 1000th bits
    
            bitset.set(0);
            bitset.set(1000);
    
            // display the size, length, 
            // and cardinality
    
            System.out.println(
                &quot;size = &quot; + bitset.size());
            System.out.println(
                &quot;length = &quot; + bitset.length());
            System.out.println(&quot;cardinality = &quot; +
                bitset.cardinality());
    
            // list the bits that are set, 
            // using toString()
    
            System.out.println(&quot;list #1 = &quot; + bitset);
    
            // list the bits that are set, 
            // using a loop
    
            System.out.print(&quot;list #2 = &quot;);
            for (int i = 0, len = bitset.length(); 
                i &lt; len; i++) {
                    if (bitset.get(i)) {
                        System.out.print(i + &quot; &quot;);
                    }
            }
            System.out.println();
    
            // list the bits that are set, 
            // using an iterator
    
            System.out.print(&quot;list #3 = &quot;);
            for (int i = bitset.nextSetBit(0); i &gt;= 0;
            i = bitset.nextSetBit(i + 1)) {
                System.out.print(i + &quot; &quot;);
            }
            System.out.println();
        }
    }
</pre>

<p>
The <code>BitSet1</code> program creates a <code>BitSet</code> and sets the 0th and 1000th bits to true. Other bits between 0 and 1000 have false values. <code>BitSet</code> allocates enough memory internally to represent the highest set bit. Bits beyond the highest set bit are considered to be false.
</p>

<p>
One way of thinking about a <code>BitSet</code> is that it's a vector of <code>2^31</code> true or false bits, with all of the bits initially set to false. The bits have indices from <code>0</code> to <code>Integer.MAX_VALUE</code>, or <code>2^31 - 1</code>. As bits are set to true, memory is allocated to represent them.
</p>

<p>
The program prints the size, length, and cardinality of the <code>BitSet</code>. The size is the the actual number of bits used by the <code>BitSet</code>. The length is the index of the highest set bit plus one. The cardinality is the number of bits currently set to true in the <code>BitSet</code>.
</p>

<p>
The program also illustrates three ways of retrieving a list of the set bits in the <code>BitSet</code>. The first way uses the <code>BitSet.toString</code> method. The second way uses a loop and the <code>get</code> method to check each index in the <code>BitSet</code>. The third way makes use of the <code>BitSet.nextSetBit</code> method to iterate across all the set bits.
</p>

<p>
When you run the program, the output is:
</p>

<pre>
    size = 1024
    length = 1001
    cardinality = 2
    list #1 = {0, 1000}
    list #2 = 0 1000 
    list #3 = 0 1000 
</pre>

<p>
This example also illustrates the idea that internal space to store the bits is dynamically allocated as needed. For example, if the 1000th bit is set, then the <code>BitSet</code> must grow to about 125 bytes.
</p>

<p>
Here's another example that illustrates this point: 
</p>

<pre>
    import java.util.BitSet;
    
    public class BitSet2 {
        public static void main(String args[]) {
            BitSet bitset = new BitSet();
            bitset.set(1000000);
            System.out.println(
                &quot;number of bytes required = &quot; +
                bitset.size() / 8);
        }
    }
</pre>

<p>
This <code>BitSet2</code> program sets the millionth bit in a <code>BitSet</code>. The output of the program is:
</p>

<pre>
    number of bytes required = 125008
</pre>

<p>
This particular <code>BitSet</code> object must grow to about 125,000 bytes to represent the millionth bit. Note that you can specify the size of the <code>BitSet</code> to the constructor, that is, if you know in advance how big the <code>BitSet</code> is likely to get. Doing this will save time and space reallocation as well as copying. <code>BitSet</code> as currently implemented uses a particular internal data structure (64-bit longs) to represent bits. This representation is not part of the external <code>BitSet</code> interface, however this tip assumes a particular model of memory allocation. This model is based on an array of longs, which represent all bits, true or false, so as to include the highest set bit. However, there are other possible ways to represent sets of bits. Note that the results from the size method might not make much sense if some other type of internal structure is used.
</p>

<p>
Let's look at another example. This one shows how you can perform common logical operations on a pair of <code>BitSets</code>:
</p>

<pre>
    import java.util.BitSet;
    
    public class BitSet3 {
        public static void main(String args[]) {
    
            // create two sets of bits
    
            BitSet bitset1 = new BitSet();
            bitset1.set(1);
            bitset1.set(5);
            bitset1.set(8);
    
            BitSet bitset2 = new BitSet();
            bitset2.set(2);
            bitset2.set(5);
            bitset2.set(7);
            bitset2.set(11);
    
            // make a copy of the first one and XOR 
            // with the second
    
            BitSet result = (BitSet)bitset1.clone();
            result.xor(bitset2);
    
            System.out.println(bitset1 + &quot; XOR &quot; + 
                bitset2 + &quot; = &quot; + result);
        }
    }
</pre>

<p>
Normally, when you have two <code>BitSets</code> and you do a logical operation like this:
</p>

<pre>
    bitset1.xor(bitset2);
</pre>

<p>
The result of the operation (exclusive-OR) is left in <code>bitset1</code>. But the idea in this example is to leave <code>bitset1</code> unchanged. So the program makes a copy of <code>bitset1</code> using the clone method.
</p>

<p>
When you run this example, the result is:
</p>

<pre>
    {1, 5, 8} XOR {2, 5, 7, 11} = {1, 2, 7, 8, 11} 
</pre>

<p>
A bit is set in the result <code>BitSet</code> if it is set in one, but not both, of the operand <code>BitSets</code>. The <code>BitSet</code> class offers similar methods for computing <code>AND</code>, <code>OR</code>, and <code>ANDNOT</code>. The <code>ANDNOT</code> method, which performs the operation a &amp; ~b, is used to mask out bits in a <code>BitSet</code>. 
</p>

<p>
A final example illustrates how you use <code>BitSet</code> features to operate on a range or group of bits:
</p>

<pre>
    import java.util.BitSet;
    
    public class BitSet4 {
        public static void main(String args[]) {
            BitSet bitset1 = new BitSet();
    
            // set bits from 0 (inclusive) 
            // to 99 (exclusive)
    
            bitset1.set(0, 99);
    
            // get bits from 0 (inclusive) 
            // to 9 (exclusive)
    
            BitSet bitset2 = bitset1.get(0, 9);
    
            System.out.println(bitset2);
        }
    }
</pre>

<p>
The <code>BitSet4</code> program creates a <code>BitSet</code>, and then sets bits 0-98 to true. Then bits 0-8 of this <code>BitSet</code> are copied into a new <code>BitSet</code>. The output is:
</p>

<pre>
    {0, 1, 2, 3, 4, 5, 6, 7, 8}
</pre>

<p>
<code>BitSet</code> is an efficient way to represent and manipulate a large number of true/false values.
</p>

<p>
For more information about <code>BitSet</code>, see section 17.1, <code>BitSet</code>, in &quot;<a href="http://java.sun.com/docs/books/javaprog/thirdedition/?s=06&w=49" target="_blank">The Java<sup>TM</sup> Programming Language Third Edition</a>&quot; by Arnold, Gosling, and Holmes.
</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="Pixel" 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="Pixel" border="0"></td>
</tr>
</table> 

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

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

<h3>USING JSPINNER TO CHOOSE FROM AN ORDERED LIST</h3>

<p>
<code>JSpinner</code> is a <code>Swing</code> class you use to display an ordered sequence of items, such as numbers or strings or calendar dates. A user can make a selection from the displayed sequence, or explicitly enter a value. <code>JSpinner</code> is similar to <code>JComboBox</code>, but instead of using a drop-down list to display the items, it employs a couple of tiny arrow keys that allow a user to sequence through a series of values. 
</p>

<p>
Let's look at an example that compares and contrasts <code>JSpinner</code> and <code>JComboBox</code>:
</p>

<pre>
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.event.*;
    
    public class SpinDemo1 {
        public static void main(String args[]) {
    
            // create a JFrame
    
            JFrame frame = new JFrame(&quot;SpinDemo1&quot;);
            frame.setDefaultCloseOperation(
                JFrame.EXIT_ON_CLOSE);
    
            // create a JSpinner with a range of 
            // values 1-5 and starting value 1 
            // and increment 1
    
            final SpinnerModel sm =
                new SpinnerNumberModel(new Integer(1),
                new Integer(1), new Integer(5), 
                    new Integer(1));
            JSpinner jsp = new JSpinner(sm);
    
            // add a change listener
    
            jsp.addChangeListener(
                new ChangeListener() {
                    public void stateChanged(
                        ChangeEvent e) {
                            System.out.println(
                                &quot;changed: &quot; +
                                sm.getValue());
                    }
                });
    
            // create a JComboBox
    
            Object list[] = {new Integer(1), 
                new Integer(2), new Integer(3), 
                new Integer(4), new Integer(5)};
            JComboBox jcb = new JComboBox(list);
            jcb.setEditable(true);
    
            // create a JPanel
    
            JPanel panel = new JPanel();
            panel.setPreferredSize(
                new Dimension(300, 300));
            panel.add(jsp);
            panel.add(jcb);
            frame.getContentPane().add(panel);
    
            // display the frame
    
            frame.pack();
            frame.setVisible(true);
        }
    }
</pre>

<p>
This <code>SpinDemo1</code> program sets up a <code>JPanel</code> containing a <code>JSpinner</code> and a <code>JComboBox</code>. Both of these display the Integer wrapper values 1-5. Both <code>JSpinner</code> and <code>JComboBox</code> also allow you to enter your own value. But the <code>JComboBox</code> pull-down list uses a lot more window space when it displays its list of values. If there is another GUI item such as a label or input area just below the <code>JComboBox</code>, it will be temporarily obscured when the list of values is displayed. So <code>JSpinner</code> has an advantage in operating within a more constrained area of the window.
</p>

<p>
The example highlights another difference between <code>JSpinner</code> and <code>JComboBox</code>. A <code>JSpinner</code> uses an ordered set of values called the model. In the <code>SpinDemo1</code> program the model is represented by a <code>SpinnerNumberModel</code> object. Minimum and maximum values as well as a starting value and an increment/decrement are set for the model. The <code>JSpinner</code> uses the model to validate its input. For example, if you enter &quot;7&quot; for the example above, it will not be accepted. You can literally type &quot;7&quot; in the <code>JSpinner</code> input field, but it will not be treated as a legal value. You can tell this by the change listener that is called when the value changes.
</p>

<p>
By contrast, <code>JComboBox</code> lets you type in any value you want, whether or not it's in the list specified to the <code>JComboBox</code> constructor. This functionality might be just what you need -- it all depends on your particular application.
</p>

<p>
Here's another example, one that uses <code>JSpinner</code> with a list of strings:
</p>

<pre>
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.event.*;
    
    public class SpinDemo2 {
        public static void main(String args[]) {
    
            // create a JFrame
    
            JFrame frame = new JFrame(&quot;SpinDemo2&quot;);
            frame.setDefaultCloseOperation(
                JFrame.EXIT_ON_CLOSE);
    
            // create a JSpinner 
            // based on a list of strings
    
            Object list[] = {&quot;string1&quot;, &quot;string2&quot;, 
                &quot;string3&quot;};
            SpinnerModel sm = 
                new SpinnerListModel(list);
            JSpinner jsp = new JSpinner(sm);
    
            // create a JPanel
    
            JPanel panel = new JPanel();
            panel.setPreferredSize(
                new Dimension(300, 300));
            panel.add(jsp);
            frame.getContentPane().add(panel);
    
            // display the frame
    
            frame.pack();
            frame.setVisible(true);
        }
    }
</pre>

<p>
As with the previous example, any input typed by the user is validated against the specified list of strings.
</p>

<p>
Let's look at a slightly more complicated example, one where you specify a starting calendar date and then step through dates in one-minute intervals:
</p>

<pre>
    import java.util.*;
    import java.awt.*;
    import javax.swing.*;
    import javax.swing.event.*;
   
    public class SpinDemo3 {
        public static void main(String args[]) {
   
            // create a JFrame
   
            JFrame frame = new JFrame(&quot;SpinDemo3&quot;);
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
   
            // create a JSpinner set to the current
            // date, with increment/decrement
            // set to minutes
   
            final SpinnerModel sm =
                new SpinnerDateModel(new Date(),
                null, null, Calendar.MINUTE);
            JSpinner jsp = new JSpinner(sm);
   
            // add a change listener for the JSpinner
   
            jsp.addChangeListener(
                new ChangeListener() {
                    public void stateChanged(
                        ChangeEvent e) {
                            Date d = (Date)sm.getValue();
                            System.out.println(
                                "new date: &quot; + d);
                }
            });
   
            // create a JPanel
   
            JPanel panel = new JPanel();
            panel.setPreferredSize(
                new Dimension(300, 300));
            panel.add(jsp);
            frame.getContentPane().add(panel);
   
            // display the frame
   
            frame.pack();
            frame.setVisible(true);
        }
    }
</pre>

<p>
In the first example, <code>SpinDemo1</code>, the program specified a range of values 1-5, a starting value of 1, and an increment/decrement of 1. In the <code>SpinDemo3</code> example, the program starts with the current date, sets no minimum or maximum date values, and sets the increment/decrement to one minute. A user presented with the display can step through calendar dates in one-minute increments, or enter a date as desired. The change listener shows how to retrieve the current <code>Date</code> value from the underlying model used by the <code>JSpinner</code> object.
</p>

<p>
You may notice that the change listener is called twice the first time you increment or decrement the date in the <code>JSpinner</code> field. This behavior occurs because the displayed calendar date does not represent the full precision of the date stored internally, and rounding of the internal date will occur to match the displayed date. The first call to the change listener happens because of this rounding.
</p>

<p>
<code>JSpinner</code> is useful in situations where you'd like to let the user choose from an ordered sequence of values, and have input validation. <code>JSpinner</code> is also useful in situations where you want to economize on the use of window space.
</p>

<p>
For more information about <code>JSpinner</code>, see &quot;<a href="http://java.sun.com/j2se/1.4/docs/guide/swing/1.4/spinner.html?s=06&w=49" target="_blank">JSpinner - A Simple Sequence Container</a>&quot;.
</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="Pixel" 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="Pixel" border="0"></td>
</tr>
</table> 

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


<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="Pixel" border="0"></td></tr>

<h3>Reader Feedback</h3> 
<FORM METHOD="POST" ACTION="http://developer.java.sun.com/servlet/jdc.survey.TabulationServlet">
<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="DecCore_tt1203"> 
<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<font size="-2"><sup>TM</sup></font> programming? Use  
<a href="http://developer.java.sun.com/developer/support/?s=06&w=49">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="Pixel" 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="Pixel" 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?s=06&w=49" target="_blank"><span class="link">http://www.sun.com/share/text/termsofuse.html</span></a><br>
<a href="http://www.sun.com/privacy/?s=06&w=49" target="_blank"><span class="link">http://www.sun.com/privacy/</span></a><br> 
<a href="http://developer.java.sun.com/berkeley_license.html?s=06&w=49" target="_blank"><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<sup>TM</sup> Technologies Tech Tips to: <a href="mailto:jdc-webmaster@sun.com"><span class="link">jdc-webmaster@sun.com</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<sup>TM</sup>).<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<sup>TM</sup>).<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://developer.java.sun.com/subscription/?s=06&w=49" target="_blank"><span class="link">subscribe</span></a> to and click &quot;Update&quot;.<br>
  - To unsubscribe, go to the <a href="http://developer.java.sun.com/subscription/?s=06&w=49" target="_blank"><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://java.sun.com/jdc/TechTips/?s=06&w=49" target="_blank"><span class="link">http://java.sun.com/jdc/TechTips/index.html</span></a>
</span><br><br>

<span class="small">Copyright 2002 <a href="http://www.sun.com" target="_blank"><span class="link">Sun Microsystems, Inc.</span></a> All rights reserved.
<br>901 San Antonio Road, Palo Alto, California 94303 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?s=06&w=49" target="_blank"><span class="link">http://java.sun.com/jdc/copyright.html</span></a>
</span><br><br>

<span class="small">Sun, Sun Microsystems, Java, Java Developer Connection, J2SE, J2EE, and J2ME are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.</span><br><br>


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

<center>
<a href="http://www.sun.com" target="_blank"><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>

<table bgcolor = "#efefef"><tr><td><a href="http://bulkmail.sun.com/servlet/PreferenceServlet?action=change&pref_name=content-type&pref_value=text&id=263585151282598993">Please send me newsletters in text.</a><br><a href="http://bulkmail.sun.com/unsubscribe?263585151282598993">Please unsubscribe me from this newsletter.</a><img src="http://bulkmail2.sun.com/OTServlet?id=263585151282598993" width=1 height=1></td></tr></table></body>
</html>

