Welcome to the Core Java 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). This issue covers:
These tips were developed using Java 2 SDK, Standard Edition, v 1.4. This issue of the Core Java Technologies Tech Tips is written by Glen McCluskey. USING VARIABLE-LENGTH ARGUMENT LISTSIf you've done much C or C++ programming, you might have encountered some code that looks similar to this:
The The output of this C program is:
count = 1: 1
count = 3: 1 2 3
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:
dumpList(3, 1, 2, 3.4);
the result is something like this:
count = 1: 1
count = 3: 1 2 858993459
The demo program assumes that an int argument has been passed, when in fact a double (3.4) is passed. 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.
The first approach you might think of is to overload the
The idea is that you have a variable number of object references to be passed as arguments, and 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.
A second approach to handling variable argument lists is to use an
This approach works quite well. One example of its use is the
This class is a rough equivalent to the When you run this program, the result is:
msg = Error at line 37 of file abc.java: missing (
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 A final approach uses the collections framework, like this:
This approach solves the problem of modifying the passed-in argument list. If you uncomment the "
Using the collections framework has other advantages. For example, notice that the top of the 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 "The Java Programming Language Third Edition" by Arnold, Gosling, and Holmes. SOME THINGS YOU SHOULD KNOW ABOUT FLOATING-POINT ARITHMETICSuppose 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:
Everyone knows that:
0.1 + 0.1 + 0.1 == 0.3
at least in mathematical terms. But when you run the
d != val2
d - val2 = 5.551115123125783E-17
This result seems to indicate that 0.1 + 0.1 + 0.1 differs from 0.3 by about 5.55e-17. 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:
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.
There are several ways to fix the equality testing problem illustrated above. You could check that Here's another example where floating-point works differently from what you'd expect when applying math rules:
The result of the
val1 + val2 == val1
In mathematical terms, if:
a > 0 && b > 0
then:
a + b != a
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:
1.2345e+4 + 1e-16
Because the precision of double values is not sufficient to represent the result of this addition, the 1e-16 is effectively ignored. Here's another example that illustrates how the laws of math are violated:
If
1.6E308
Infinity
The initial multiplication
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
When you run this program, the output is:
-Infinity
Infinity
NaN
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. 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.
What about the third division, Negative and positive zeros and NaN have some odd properties. Let's look at another example to help clarify this:
If you run the
The Let's look at a final example that illustrates the ordering of some of the odd floating-point values discussed so far:
The result of running the program is:
The list presents -0.0 before +0.0. As already mentioned, whether -0.0 really comes before +0.0 depends on your perspective.
Note that 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. For more information about floating-point arithmetic, see section 4.2.3, Floating-Point Types, Formats, and Values, in "The Java Language Specification Second Edition" by Gosling, Joy, Steele, and Bracha. Also see the following IEEE-754 documents: Storage Layout and Ranges of Floating-Point Numbers and IEEE-754 Floating-Point Conversion IMPORTANT: Please read our Terms of Use, Privacy, and Licensing policies: http://www.sun.com/share/text/termsofuse.html http://www.sun.com/privacy/ http://developer.java.sun.com/berkeley_license.html Comments? Send your feedback on the Core Java Technologies Tech Tips to: jdc-webmaster@sun.com Subscribe to other Java developer Tech Tips: - 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). - Wireless Developer Tech Tips. Get tips on using wireless Java technologies and APIs, such as those in the Java 2 Platform, Micro Edition (J2ME). To subscribe to these and other JDC publications: - Go to the JDC Newsletters and Publications page, choose the newsletters you want to subscribe to and click "Update". - To unsubscribe, go to the subscriptions page, uncheck the appropriate checkbox, and click "Update". ARCHIVES: You'll find the Core Java Technologies Tech Tips archives at: http://java.sun.com/jdc/TechTips/index.html Copyright 2003 Sun Microsystems, Inc. All rights reserved. 901 San Antonio Road, Palo Alto, California 94303 USA. This document is protected by copyright. For more information, see: http://java.sun.com/jdc/copyright.html 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. | ||||||||||||||||||||||||||
|
| ||||||||||||