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!