A recent issue in the issue tracker on the new iOS VM reminded me of a serious pet peeve and big design mistake in the Java Collections API, something that is just unfixable and wrong yet appears often in code from developers trying to be clever.
If you have a collection and you want to convert it to an array you can do something like:
Object myArray = c.toArray();
Unfortunately, this will always be an array of objects and not of your desired type... So if the collection is one of String you would really want to do something like:
String array = new String[c.size()];
This works great but takes two lines... Which is why you can also do something like this:
String array = (String)c.toArray(new String[c.size()]);
So far so good... The problem is that this also works:
String array = (String)c.toArray(new String);
It will produce an array response that is equal to the size of c and is of type String and not Object. This will fail on the new iOS VM and should really never be used...
Java usually takes the approach of "fail fast", which means that if code fails it should do so ASAP and not "try to recover" which might cause bugs to remain hidden. This isn't such a case.
If the array past to the toArray method is too small, the code has a fallback. The problem is that the fallback is REALLY bad!
It uses reflection to detect the array type and allocate a whole new array. This is really slow and that essentially means the original allocated array is just completely redundant garbage. And all this just saves a single boilerplate method call:
String array = (String)c.toArray(new String[ c.size() ]);
Don't do that, on Java SE/EE either. It has reflection and a better optimizer but even the best optimizer can't eliminate something this bad...
Notice: This post was automatically converted using a script from an older blogging system. Some elements might not have come out as intended.... If that is the case please let us know via the comments section below.