Return-Path: <cyrus@po10.mit.edu>
Received: from po10.mit.edu ([unix socket])
	by po10.mit.edu (Cyrus v2.1.5) with LMTP; Tue, 04 Feb 2003 13:27:03 -0500
X-Sieve: CMU Sieve 2.2
Return-Path: <env_296271702004187913@hermes.sun.com>
Received: from pacific-carrier-annex.mit.edu by po10.mit.edu (8.12.4/4.7) id h14IR280023047; Tue, 4 Feb 2003 13:27:02 -0500 (EST)
Received: from hermes.sun.com (hermes.sun.com [64.124.140.169])
	by pacific-carrier-annex.mit.edu (8.9.2/8.9.2) with SMTP id NAA08763
	for <alexp@mit.edu>; Tue, 4 Feb 2003 13:27:01 -0500 (EST)
Date: 4 Feb 2003 08:47:18 -0800
From: "JDC Tech Tips" <sunmail@hermes.sun.com>
To: alexp@mit.edu
Message-Id: <296271702004187913@hermes.sun.com>
Subject: Core Java Technologies Tech Tips, Feb. 4, 2003 (Variable Argument Lists, Floating-Point Arithmetic)
Mime-Version: 1.0
Content-Type: text/html; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit
X-Mailer: SunMail 1.0
X-Spam-Flag: NO
X-Spam-Score: 1.2, Required 7.5
X-Spam-Level: * (1.2)
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="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://bulkmail2.sun.com/CTServlet?id=1044376692377"><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://bulkmail2.sun.com/CTServlet?id=1044376692390
Feb03_GlenM.txt" style="text-decoration:none;">View this issue as 
simple text</a></td>
<td align="right" height="20"><span class="purple">February 4, 
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<font size="-2"><sup>TM</sup></font> 
Technologies Tech Tips, February 4, 2003. Here you'll get tips on using 
core Java technologies and APIs, such as those in Java 2 Platform, 
Standard Edition (J2SE<font size="-2"><sup>TM</sup></font>).
</p>

<p>
This issue covers:
</p>

<p>
<a href="#1"><img src="http://developer.java.sun.com/images/anchor.gif" 
border="0" alt="">Using Variable Argument Lists</a>
<br>    
<a href="#2"><img src="http://developer.java.sun.com/images/anchor.gif" 
border="0" alt="">Some Things You Should Know About Floating-Point 
Arithmetic</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.
</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> 

<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 VARIABLE-LENGTH ARGUMENT LISTS</h3>

<p>
If you've done much C or C++ programming, you might have encountered 
some code that looks similar to this:
</p>

<pre>
    #include &lt;stdarg.h&gt;
    #include &lt;stdio.h&gt;
    
    void dumpList(int n, ...) {
        va_list ap;
    
        va_start(ap, n);
    
        printf(&quot;count = %d: &quot;, n);
        while (n-- &gt; 0) {
            int i = va_arg(ap, int);
            printf(&quot;%d &quot;, i);
        }
        printf(&quot;\n&quot;);
    
        va_end(ap); 
    }
    
    int main() {
        dumpList(1, 1);
    
        dumpList(3, 1, 2, 3);
    
        return 0;
    }
</pre>

<p>
The <code>dumpList</code> function declares a single parameter (n), 
followed by an ellipsis (...). The ellipsis specifies that a variable 
number of additional parameters are present. This means that a caller 
of <code>dumpList</code> can pass an arbitrary number of arguments in 
addition to the first int argument. The various <code>va_x</code> types 
and functions are used to extract the parameter values in the 
<code>dumpList</code> function.
</p>

<p>
The output of this C program is:
</p>

<pre>
    count = 1: 1 
    count = 3: 1 2 3 
</pre>

<p>
The C/C++ variable argument mechanism is quite useful in certain 
contexts. But the mechanism is error-prone, because it defeats type 
checking. For example, if the second dumpList call is changed to:
</p>

<pre>
    dumpList(3, 1, 2, 3.4);
</pre>

<p>
the result is something like this:
</p>

<pre>
    count = 1: 1 
    count = 3: 1 2 858993459
</pre>

<p>
The demo program assumes that an int argument has been passed, when in 
fact a double (3.4) is passed.
</p>

<p>
The Java language has no direct equivalent to this feature. However, 
it's still sometimes useful to be able to pass a variable number of 
arguments to a method. This tip looks at several ways of doing that.
</p>

<p>
The first approach you might think of is to overload the 
<code>dumpList</code> method, like this:
</p>

<pre>
    public class VarDemo1 {
        static void dumpList(Object obj1) {
            System.out.println(obj1);
        }
    
        static void dumpList(Object obj1, Object obj2) {
            System.out.println(obj1 + &quot; &quot; + obj2);
        }
    
        static void dumpList(Object obj1, Object obj2,
        Object obj3) {
            System.out.println(
               obj1 + &quot; &quot; + obj2 + &quot; &quot; + obj3);
        }
    
        public static void main(String[] args) {
            Object obj1 = new Integer(1);
            Object obj2 = new Integer(2);
            Object obj3 = new Integer(3);
    
            dumpList(obj1);
            dumpList(obj1, obj2, obj3);
        }
    }
</pre>

<p>
The idea is that you have a variable number of object references to be 
passed as arguments, and <code>dumpList</code> methods are defined for 
each case. This approach will certainly work, but has some serious 
problems. One problem is that the approach is not general. The 
<code>VarDemo1</code> program defines <code>dumpList</code> methods to 
handle one, two, or three arguments. But what if you have ten arguments 
that you want to pass? Do you keep adding new <code>dumpList</code> 
methods?
</p>

<p>
Another problem is that there can be a lot of code duplication between 
the various overloaded methods. This duplication implies a long-term 
maintenance headache.
</p>

<p>
A second approach to handling variable argument lists is to use an 
<code>Object[]</code> array, like this:
</p>

<pre>
    public class VarDemo2 {
        static void dumpList(Object[] list) {
            for (int i = 0; i &lt; list.length; i++) {
                System.out.print(list[i] + &quot; &quot;);
            }
            System.out.println();
    
            //list[0] = new Integer(4);
        }
    
        public static void main(String[] args) {
            Object[] veclist1 = {new Integer(1)};
            Object[] veclist2 = {new Integer(1),
                new Integer(2), new Integer(3)};
    
            dumpList(veclist1);
            dumpList(veclist2);
        }
    }
</pre>

<p>
This approach works quite well. One example of its use is the 
<code>java.text.MessageFormat</code> class:
</p>

<pre>
    import java.text.*;
    
    public class VarDemo3 {
        public static void main(String[] args) {
            String fmt = 
               &quot;Error at line {0} of file {1}: {2}&quot;;
    
            Object[] arglist = {new Integer(37),
                &quot;abc.java&quot;, &quot;missing (&quot;};
    
            String msg = 
               MessageFormat.format(fmt, arglist);
    
            System.out.println(&quot;msg = &quot; + msg);
        }
    }
</pre>

<p>
This class is a rough equivalent to the <code>printf</code> function 
illustrated in the first demo above. The embedded &quot;{0}&quot; and 
so on in the format string are references to the arguments passed to 
the format method in the <code>Object[]</code> array.
</p>

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

<pre>
    msg = Error at line 37 of file abc.java: missing (
</pre>

<p>
The array approach works fairly well, but one drawback is that the 
called method can modify the array contents. The commented line of code 
in the <code>VarDemo2</code> program illustrates this point. In 
general, such modification is undesirable.
</p>

<p>
A final approach uses the collections framework, like this:
</p>

<pre>
    import java.util.*;
    
    public class VarDemo4 {
        static void dumpList(List list) {
            System.out.println(list);
    
            //list.set(0, new Integer(4));
        }
    
        public static void main(String[] args) {
            List list = new ArrayList();
    
            list.add(new Integer(1));
            list.add(new Integer(2));
            list.add(new Integer(3));
    
            list = Collections.unmodifiableList(list);
    
            dumpList(list);
        }
    }
</pre>

<p>   
This approach solves the problem of modifying the passed-in argument 
list. If you uncomment the &quot;<code>list.set</code>&quot; line, and 
run the program, it will give an exception. The exception is triggered 
because the list has been wrapped in an unmodifiable view, using 
<code>Collections.unmodifiableList</code>.
</p>

<p>
Using the collections framework has other advantages. For example, 
notice that the top of the <code>dumpList</code> method prints the 
whole list using a single statement, rather than using a loop. In 
general, by using collection features it's easier to operate on lists 
as lists, rather than an element at a time. Note that the collections 
framework has features for treating <code>Object[]</code> arrays as 
lists (<code>Arrays.asList</code>) and converting lists to arrays 
(<code>ArrayList.toArray</code>).
</p>

<p>
For more information about using variable argument lists, see section 
16.6, List, 16.8.2, The Unmodifiable Wrappers, and 16.9, The Arrays 
Utility Class, in &quot;<a 
href="http://bulkmail2.sun.com/CTServlet?id=1044376692322">The 
Java<font size="-2"><sup>TM</sup></font> 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>SOME THINGS YOU SHOULD KNOW ABOUT FLOATING-POINT ARITHMETIC</h3>

<p>
Suppose that you are doing some Java programming involving 
floating-point calculations. Suppose too that your code takes the value 
0.1 and adds it to itself a couple of times, like this:
</p>

<pre>
    public class Fp1 {
        public static void main(String[] args) {
            double val1 = 0.1;
            double val2 = 0.3;
    
            double d = val1 + val1 + val1;
    
            if (d != val2) {
                System.out.println(&quot;d != val2&quot;);
            }
    
            System.out.println(
               &quot;d - val2 = &quot; + (d - val2));
        }
    }
</pre>

<p>
Everyone knows that: 
</p>

<pre>
    0.1 + 0.1 + 0.1 == 0.3
</pre>

<p>
at least in mathematical terms. But when you run the <code>Fp1</code> 
program, you discover that this equality no longer holds. The program 
output looks like this:
</p>

<pre>
    d != val2
    d - val2 = 5.551115123125783E-17
</pre>

<p>
This result seems to indicate that 0.1 + 0.1 + 0.1 differs from 0.3 by 
about 5.55e-17.
</p>

<p>
What is wrong here? The problem is that IEEE 754 floating-point 
arithmetic, as found in the Java language, doesn't use decimals to 
represent numbers. Instead it uses binary fractions and exponents. To 
understand what this means in practice, consider trying to write 
various decimal fractions as the sum of a series of powers of two:
</p>

<pre>
    0.5 = 1/2

    0.75 = 1/2 + 1/4

    0.875 = 1/2 + 1/4 + 1/8

    0.1 = 1/16 + 1/32 + 1/256 + 1/512 + 1/4096 + 1/8192 + ...
</pre>

<p>
The last series is infinite, which means that 0.1 is not exactly 
representable in floating-point format. The infinite series must be cut 
off at some point, rounded, and so on, in order to be represented in a 
64-bit double value. This process results in some amount of error.
</p>

<p>
There are several ways to fix the equality testing problem illustrated 
above. You could check that <code>d</code> and <code>val2</code> are 
close in value rather than exactly equal. Or you could use the 
<code>BigDecimal</code> class, and opt out of floating-point arithmetic 
entirely.
</p>

<p>
Here's another example where floating-point works differently from what 
you'd expect when applying math rules:
</p>

<pre>
    public class Fp2 {
        public static void main(String[] args) {
            double val1 = 12345.0;
            double val2 = 1e-16;
    
            if (val1 + val2 == val1) {
                System.out.println(
                   &quot;val1 + val2 == val1&quot;);
            }
        }
    }
</pre>  

<p> 
The result of the <code>Fp2</code> program is:   
</p>

<pre>
    val1 + val2 == val1
</pre>

<p>
In mathematical terms, if:
</p>

<pre>
    a &gt; 0 &amp;&amp; b &gt; 0
</pre>

<p>
then:
</p>

<pre>
    a + b != a
</pre>

<p>
But this program demonstrates behavior that violates this rule. The 
problem is with the precision of floating-point values. The precision 
is the actual number of bits used to represent the value (the binary 
fraction), and is distinct from the range of values that can be 
expressed using floating-point. For Java double values, there are 53 
bits of precision, or about 16 decimal digits. The example above 
implies a precision of approximately 20 digits, since the addition can 
be rewritten as:
</p>

<pre>
    1.2345e+4 + 1e-16
</pre>

<p>
Because the precision of double values is not sufficient to represent 
the result of this addition, the 1e-16 is effectively ignored.
</p>

<p>
Here's another example that illustrates how the laws of math are 
violated:
</p>

<pre>
    public class Fp3 {
        public static void main(String[] args) {
            double d1 = 1.6e308;
            double d2 = d1 * 2.0 / 2.0;
    
            System.out.println(d1);
            System.out.println(d2);
        }
    }
</pre>

<p>
If <code>d1</code> is multiplied and then divided by 2.0, the result 
should be <code>d1</code>, right? Unfortunately not. The result is 
actually this:
</p>

<pre>
    1.6E308
    Infinity
</pre>

<p>
The initial multiplication <code>d1</code> * 2.0 overflows, and the 
division by 2.0 comes too late to do any good. The maximum double value 
is approximately 1.8e308. Multiplying 1.6e308 by 2.0 results in 
3.2e308, which becomes positive infinity.
</p>

<p>
Let's look at another facet of floating-point arithmetic. If you've 
used integer arithmetic much, you know that division by zero triggers 
an <code>ArithmeticException</code>. But what about similar usage with 
floating-point? Here's an example:
</p>

<pre>
    public class Fp4 {
        public static void main(String[] args) {
            System.out.println(1.0 / -0.0);
            System.out.println(1.0 / 0.0);
    
            System.out.println(0.0 / 0.0);
        }
    }
</pre>

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

<pre>
    -Infinity
    Infinity
    NaN
</pre>

<p>
The program throws no exceptions for floating-point division by 
zero. When a positive or negative value is divided by zero, the 
result is an infinity.
</p>

<p>
This example shows that there is, in fact, more than one zero 
value. There are negative and positive zeros. The sign of the 
zero is taken into account in deciding whether the result of the 
division is negative or positive infinity.
</p>

<p>
What about the third division, <code>0.0 / 0.0</code>? The result of 
this operation is the value NaN (not a number).
</p>

<p>
Negative and positive zeros and NaN have some odd properties. Let's 
look at another example to help clarify this:
</p>

<pre>
    public class Fp5 {
        public static void main(String[] args) {
            double d1 = -0.0;
            double d2 = +0.0;
            if (d1 &lt; d2) {
                System.out.println(&quot;-0.0 &lt; +0.0&quot;);
            }
    
            double d3 = 0.0 / 0.0;
            if (d3 == d3) {
                System.out.println(&quot;d3 == d3&quot;);
            }
        }
    } 
</pre>

<p>
If you run the <code>Fp5</code> program, you'll see that it prints 
nothing. As you saw in the previous example, the sign of a zero is 
propagated, for example 1.0 / -0.0 == -Infinity and 1.0 / +0.0 == 
+Infinity. But that's not the same as saying that -0.0 &lt; +0.0, as 
the example above demonstrates (d1 is not less than d2, and so nothing 
is printed). Whether -0.0 comes &quot;before&quot; +0.0 depends on your 
perspective.
</p>

<p>
The <code>Fp5</code> program also illustrates the point that NaN values 
are unordered, so that d3 is not equal to itself. This is the way that 
you write a method to tell whether a value is <code>NaN</code>. If the 
value is not equal to itself, then it is <code>NaN</code>. Such methods 
actually already exist -- see the <code>Float.isNan</code> and 
<code>Double.isNaN</code> methods.
</p>

<p>
Let's look at a final example that illustrates the ordering of some of 
the odd floating-point values discussed so far:
</p>

<pre>
    public class Fp6 {
        static double[] list = {
            Double.NEGATIVE_INFINITY,
            -0.0,
            +0.0,
            Double.MIN_VALUE,
            Double.MAX_VALUE,
            Double.POSITIVE_INFINITY
        };
    
        public static void main(String[] args) {
            for (int i = 0; i &lt; list.length; i++) {
                System.out.println(list[i]);
            }
        }
    }
</pre>

<p>
The result of running the program is:
</p>

<pre>
    -Infinity
    -0.0
    0.0
    4.9E-324
    1.7976931348623157E308
    Infinity
</pre>

<p>
The list presents -0.0 before +0.0. As already mentioned, whether -0.0 
really comes before +0.0 depends on your perspective.
</p>

<p>
<code>NaN</code> is not on the list because it is not ordered with 
respect to other values.
</p>

<p>
Note that <code>Double.MAX_VALUE</code> and 
<code>Double.POSITIVE_INFINITY</code> are distinct values.
</p>

<p>
This tip looked at a few of the properties of floating-point 
arithmetic. It pays to be careful when using floating-point because it 
behaves differently than you might expect if you simply apply the laws 
of mathematics.
</p>

<p>
For more information about floating-point arithmetic, see section 
4.2.3, Floating-Point Types, Formats, and Values, in &quot;<a 
href="http://bulkmail2.sun.com/CTServlet?id=1044376692334">The Java<font 
size="-2"><sup>TM</sup></font> Language Specification Second 
Edition</a>&quot; by Gosling, Joy, Steele, and Bracha. Also see the 
following IEEE-754 documents: <a 
href="http://babbage.cs.qc.edu/courses/cs341/IEEE-754references.html#ke
vin_chart">Storage Layout and Ranges of Floating-Point Numbers</a> and 
<a href="http://babbage.cs.qc.edu/courses/cs341/IEEE-754.html">IEEE-754 
Floating-Point Conversion</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="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 -->

<FORM METHOD="POST" 
ACTION="http://developer.java.sun.com/servlet/jdc.survey.TabulationServ
let">
<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>

<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="FebCore_tt0204"> 
<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://bulkmail2.sun.com/CTServlet?id=1044376692405">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"><span 
class="link">http://www.sun.com/share/text/termsofuse.html</span></a><b
r>
<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<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://bulkmail2.sun.com/CTServlet?id=1044376692354"><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=1044376692354"><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=1044376692419"><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=1044376692441"><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"><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://bulkmail2.sun.com/CTServlet?id=1044376692441"><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/unsubscribe?296271702004187913">Please unsubscribe me from this newsletter.</a><img src="http://bulkmail2.sun.com/OTServlet?id=296271702004187913" width=1 height=1></td></tr></table></body>
</html>


