Skip to main content

Java 5's Varags Clean Up Reflection Code

Posted by tball on September 24, 2005 at 11:09 AM PDT

Java 5 has a lot of major improvements to the platform, to the point where some of the smaller features can get overlooked. Like many developers (including Calvin Austin his J2SE in a Nutshell article), I thought it great that varargs methods were added so printf() could be implemented, but didn't see much other use for the feature.

Yesterday I was updating a Factory class which uses a ClassLoader and Java's reflection facility to separate a public interface (JackpotEngine) from its implementation (Engine), and got an unexpected compiler warning about vararg misuse calling Class.getConstructor(). Say what? I wasn't anywhere near a printf()! Here was the code:


    public static JackpotEngine createEngine(String jarPath, AppContext appContext) throws Exception {
        ClassLoader loader = new JackpotClassLoader(jarPath);
        Class c = Class.forName("org.netbeans.jackpot.Engine", true, loader); // NOI18N
        Class[] argTypes = new Class[] { AppContext.class };
        Constructor con = c.getConstructor(argTypes);
        Object[] args = new Object[] { appContext };
        return (JackpotEngine)con.newInstance(args);
    }

Normal, ugly reflection code with a one-use array definition for each call, right? Bringing up the source for getConstructor() showed the issue: this method, along with all the other reflection methods that used to take arrays, are now varargs methods. That made sense, so I converted my code:


    public static JackpotEngine createEngine(String jarPath, AppContext appContext) throws Exception {
        ClassLoader loader = new JackpotClassLoader(jarPath);
        Class c = Class.forName("org.netbeans.jackpot.Engine", true, loader); // NOI18N
        Constructor con = c.getConstructor(AppContext.class);
        return instance = (JackpotEngine)con.newInstance(appContext);
    }

That is easier to read, and made the compiler happy. Later, when I needed to also pass the Engine constructor the jarPath; varargs again made this edit easier than dealing with array declarations:


    public static JackpotEngine createEngine(String jarPath, AppContext appContext) throws Exception {
        ClassLoader loader = new JackpotClassLoader(jarPath);
        Class c = Class.forName("org.netbeans.jackpot.Engine", true, loader); // NOI18N
        Constructor con = c.getConstructor(AppContext.class, String.class);
        return instance = (JackpotEngine)con.newInstance(appContext, jarPath);
    }

Think how much easier learning Java reflection would have been if varargs support had been in Java 1.1!

Related Topics >>