Software Engineering for Smart Data Analytics & Smart Data Analytics for Software Engineering
“This code is casting the result of calling toArray() on a collection to a type more specific than Object[], as in:
<code Java> String[] getAsArray(Collection<String> c) {
return (String[]) c.toArray();
} </Code>
This will usually fail by throwing a ClassCastException. The toArray() of almost all collections return an Object[]. They can't really do anything else, since the Collection object has no reference to the declared generic type of the collection.
The correct way to do get an array of a specific type from a collection is to use c.toArray(new String[]); or c.toArray(new String[c.size()]); (the latter is slightly more efficient).
There is one common/known exception exception to this. The toArray() method of lists returned by Arrays.asList(…) will return a covariantly typed array. For example, Arrays.asArray(new String[] { “a” }).toArray() will return a String []. FindBugs attempts to detect and suppress such cases, but may miss some.” – 2013-10-13
The List class of the Java util package contains the toArray() method, which returns an array containing all the elements of the list. However, the returned array is of type Object[] (since the List collection is capable of storing objects of any class) and upon any attempt to cast this value to an array of a more specific type, a ClassCastException will be thrown.
The former limitation is quite inconvenient, as prior to operating on any of the elements of the array it would have to be cast independently. That could have a negative impact on performance, as an unboxing operation would be executed for each element of the array. Moreover, it is very likely to cause errors that may go undetected during development to arise upon execution.
Therefore, the parameterless version of the toArray method should be avoided in favor of its parameterized overload: toArray(T[] a). This version returns an array of the same type as that of the provided parameter.
<code Java> public class DowncastArray {
public static void main(String[] args) { List<Integer> lst = new ArrayList<Integer>(); Integer[] arr = (Integer[])lst.toArray(); }
} </Code>
Be aware that Lists created by means of the Arrays utility class are able to produce arrays of the specific type they contain. Therefore, the following code works perfectly and would correspond to a false positive if reported as error:
<code Java> public class ValidDowncastArray {
public static void main(String[] args) { List<Integer> lst = Arrays.asList(new Integer[] {3, 4, 5, 5}); Integer[] arr = (Integer[])lst.toArray(); }
} </Code>
<code Java> public class DowncastArray {
public static void main(String[] args) { List<Integer> lst = new ArrayList<Integer>(); Integer[] arr = (Integer[])lst.toArray(new Integer[3]); }
} </Code>
Benchmark project | Precision | Recall | ||||
---|---|---|---|---|---|---|
FB | JT | Delta | FB | JT | Delta | |
Project … | …% | …% | …% | …% | …% | …% |
Project … | …% | …% | …% | …% | …% | …% |
FB = FindBugs, JT = JTransformer, Delta = JTransformer - FindBugs