I just went to post that... can anybody explain to me what exactly is going on? I'm not familiar with Groovy, and I try to forget Java when I can, but this just plain doesn't make any sense.
I remember discovering this and deciding to eliminate it as part of an effort to compress the groovy jar file a bit more (long story, but basically I was running some Groovy in an applet, every byte counts).
I thought I'd found a jackpot and that killing this class would surely eliminate a nice chunk of byte code. To my amazement it makes almost no difference. With pack200 the redundancy of all these methods is totally stripped out. It took me an hour or so of work and I think it made less than 200 bytes difference in the end.
public static Object[] createArray(Object... objects) {
...
}
but doing it statically, hard-coded like this is faster. You leave it to the compiler to determine the length of the arguments, rather than having to count them at run-time.
well, java has variable length arguments now so the whole file could be simply
public static Object[] createArray() {
return EMPTY;
}
public static Object[] createArray(Object... args) {
return args;
}
My guess is they probably had this before java supported such a syntax so that you could create arrays easily. once you auto-generate the file, you just do it up to 255.
I do not have a good explanation of why this is better than the normal array initializer though, apart from the fact that once you standardize on this you may have some minimal advantage in not allocating empty arrays around.
>My guess is they probably had this before java supported such a syntax so that you could create arrays easily
varargs came in Java 1.5, September 30, 2004
Groovy 1.0, January 2, 2007
Definitely could be for compiler optimizations or backwards compatibility, just providing some context for any possible historical reasons like the one you stated.
Calling new Object[]{} directly is going to call the constructor for Object anyway, so there's no really difference in the number of method calls for either.
Also, in terms of optimization: calling new Object[]{...} makes it so that the size of the array isn't known until runtime when the initialization parameters can be evaluated. Because array length is immutable the JVM must wait until execution to create an array of the proper size.
With the overloaded static createArray() methods used in ArrayUtils the size of the array can be determined and memory allocated (based on the number of parameters at the callsite and hence which variation of the method should be called) at the JRE's convenience/when optimal.
All of this is probably micro-optimization to the who-really-cares level, and might even be irrelevant due to javac/JIT magic, just wanted to show that the existence of the new Object[] syntax doesn't preclude there being performance gains from using something like ArrayUtil.createArray().
In any case, you can easily generate an ant script or whatever build groovy uses to either generate the vararg code or the insaneo source code as we see here. The point being that this should only happen when compiling groovy for java 1.4.
>In any case, you can easily generate an ant script or whatever build groovy uses to either generate the vararg code or the insaneo source code as we see here.
Yeah, I don't think anyone is implying this is handwritten. Generating a text file is trivial in any modern language/build system.
>The point being that this should only happen when compiling groovy for java 1.4.
This is a part of the pre-compiled Groovy runtime library, it's used regardless of what JDK version you're targeting for your Groovy application/script.
I can't be sure, but in the Clojure case it appears to be done for performance reasons. The final definition of invoke uses varargs for everything after 20, so it's not an issue of compatibility.
For the late-comers (like me!), Javadoc comments were added since the parent comment was posted:
$ svn log -r {2010-11-30}:HEAD http://svn.codehaus.org/groovy/trunk/groovy/groovy-core/src/main/org/codehaus/groovy/runtime/ArrayUtil.java
------------------------------------------------------------------------
r21150 | hamletdrc | 2010-11-30 19:32:11 +0100 (Tue, 30 Nov 2010) | 3 lines
updated javadoc on arrayutil
------------------------------------------------------------------------
r21152 | hamletdrc | 2010-11-30 21:31:24 +0100 (Tue, 30 Nov 2010) | 1 line
Updated ArrayUtil javadoc one more time so that people quite wondering what it is used for.
As I said, I'm sure that it's legitimate, but it's definitely not good code, and I'd rather not have it lurking in my codebase for years on end. If you don't know the original motivation behind writing something like that, you can't really remove it for fear of the original bug cropping up again without you noticing.
(I guess, then this is also what test cases are for...)
I'm curious: Why don't people just use `new Object[]{arg1, arg2...}` ?
It's one letter longer than `createArray(arg1, arg1...)`, doesn't require you to include that chunk of code, is infinite in length, and allows you to statically-type it in your type of choice. Heck, it's the same code, just removing a layer of indirection.
edit: noticed it's one character longer, not the same length. Maybe that's why?
I suspect this is code meant to be called by generated bytecode, and generating the bytecode to call said function is easier than generating the bytecode to make a new object[]?
It's been a while since I generated JVM bytecode (oh my, five years), but I don't recall there being array initializer instructions. In other words, the new Object[] {...} statement probably translates to a whole bunch of array-write operations on the caller side whereas with a method call you just push them all on the stack and invoke the utility method.
If it's not a case here, how could this be a good example? This is an example of generating code to work around a limitation. You can approve or disapprove of the whole situation, but it does have technical merit.