5.5 Avoiding Automatic Array Conversion
Tiger adds all sorts of automatic
conversions and conveniences, which is
pretty cool...about 99% of the time. Unfortunately, there are times when
all those helps turn into hindrances. The conversion of Object... to
Object[] in a varargs method can be one of those cases, and you'll find
that in rare cases, you need to work around Java.
5.5.1 How do I do that?
Before getting into the details of getting
around this issue, be sure you
understand the problem. Take Java's new printf( ) method, a real convenience:
If you look at the Javadoc for printf( ), you'll see its a varargs method, with two parameters: a String for the formatting string, and then
System.out.printf("The balance of %s's account is $%(,6.2f\n",
account.getOwner().getFullName( ), account.getBalance( ));
Object... for all the arguments passed in for use in that formatting
string:
NOTEprintf( ), along with the other new Tiger formatting methods, are detailed in
PrintStream printf(String format, Object... args)
Chapter 9.By now, you can mentally convert this to the following:
All good, right? Well, most of the time. Consider the following code:
PrintStream printf(String format, Object[] args)
NOTEI realize this isn't the most common scenario. Then again, if all I covered were
Object[] objectArray = getObjectArrayFromSomewhereElse( );
out.printf("Description of object array: %s\n", obj);
common scenarios, we'd all be debugging right now, wouldn't we?This might seem a bit
far-fetchedhowever, consider this as normal fare
for introspective code. That's a ten-cent word for code that investigates
other code. If you are writing a code analysis tool, or an IDE, or anything
else that might use reflection or a similar API to figure out what objects
an application uses, this suddenly becomes a normal usecase. Here,
you're not really interested in the contents of the object array as much as
you are with the array itself. What type is it? What's its memory address?
What is its String representation? Keep in mind that all these questions
apply to the array itself, and not to the contents of the array. For example, let's say the array is something like this:
In that case, you might write some code like this to begin to answer
public Object[] getObjectArrayFromSomewhereElse( ) {
return new String[] {"Hello", "to", "all", "of", "you"};
}
some questions about this array:
However, the output isn't what you expect:
out.printf("Description of object array: %s\n", obj);
What in the world? This is hardly what you'd expect to seehowever,
run-ch05:
[echo] Running Chapter 5 examples from Java Tiger: A Developer's
Notebook
[echo] Running VarargsTester...
[java] Hello
the compiler did just what it always didit converted Object... in the
printf( ) method to Object[]. When it read your method invocation, it saw an argument that was, in fact, Object[]! So instead of treating the array as an object itself, it broke it up into its various parts. The first
argument became the String "Hello", which was passed to the format
string (%s), and the result was "Hello" being printed out.To get around this, you need to tell the compiler that you want the entire
object array, obj, treated as a single object, and not as a grouping of arguments. Here's the magic bullet:
Alternatively, here's an even shorter approach:
out.printf("Description of object array: %s\n", new Object[] { obj });
In both cases, the compiler no longer sees an array of objects, it simply
out.printf("Description of object array: %s\n", (Object)obj);
sees a single Object (which just happens to be an array of objects). The
result is what you should want (at least in this rather odd scenario):
While this may look like gibberish to you, it's probably what reflection-based
run-ch05:
[echo] Running Chapter 5 examples from Java Tiger: A Developer's
Notebook
[echo] Running VarargsTester...
[java] [Ljava.lang.String;@c44b88
or other introspective code wants to take a look at.