Skip to main content

Varargs Puzzler

Posted by rbair on August 10, 2006 at 2:28 PM PDT

This probably isn't up to Click 'n' Hack's standards, but here's a fun little Java 5 puzzler for a Thursday afternoon.

NOTE: For those in the dark, Click and Hack are really Neal Gafter and Joshua Bloch. They have a little skit they do at conferences where they present java code puzzlers.

Alright, we've had Java 5 for a while now and have had a good chance to get up to date with our new language features. In this puzzler I've written a method that takes a vararg of Objects, counts them up, and returns how many elements there were. Here's the code:

   private static int elementCount(Object... elements) {
     return elements == null ? 0 : elements.length;
   }

   public static void main(String... args) {
     System.out.println("null length array: " + elementCount(null));
     System.out.println("[a,b,c] length array: " + elementCount("a", "b", "c"));
   }

Pretty straight to the point. I have a method called elementCount, and it simply returns the length of the elements array, or 0 if the param is null. So what's wrong with it?

  a) Nothing at all! It works as expected!
  b) There is a compiler warning
  c) It fails to compile
  d) Both (a) and (b)

Ok, I'll give you a few minutes to look it over, read the Java Language Specification, try it out in your favorite IDE, etc. Done?

And the answer is..... d! In fact, there is a compiler warning on this line:

    //line of code
    System.out.println("null length array: " + elementCount(null));

    //compiler warning
    warning: non-varargs call of varargs method with inexact argument type for last parameter;

Besides this warning, though, the code executes properly. But since I don't really like compiler warnings, I go ahead and make the change. Here's the new code.

   private static int elementCount(Object... elements) {
     return elements == null ? 0 : elements.length;
   }

   public static void main(String... args) {
     System.out.println("null length array: " + elementCount((Object)null));
     System.out.println("[a,b,c] length array: " + elementCount("a", "b", "c"));
   }

Alright, that took care of the warning! So what's wrong with it? Anything? Come on, no cheating, think about it!

  a) It runs, but prints out "[a,b,c] length array: 0"
  b) There is a compiler warning
  c) Perfecto!
  d) It runs, but prints out "null length array: 1"

Alright, you've had your chance. What is it?






That's right, "d" again. It turns out the problem is this statement: elementCount((Object)null). The problem is that (Object)null tells the compiler to include a one element Object array where the first element is null. Instead, what we wanted to do was this (Object[])null! This is why we get the compiler warning, the compiler doesn't know if we want null to be an element in the vararg array or whether we want it to be the vararg array itself.

Tripped me up for a few minutes today, hope you enjoyed it.

Note: Updated to refer to "Click and Hack" instead of "Click and Clack" -- also fixed a typo in the description. Thanks for pointing these things out!

Related Topics >>

Comments

I had recently blogged on how the varargs are handled by JDK ...

I had recently blogged on how the varargs are handled by JDK by showing the decompiled code for java variable arguments