No se pueden mezclar genéricos y matrices así. Los genéricos tienen verificación en tiempo de compilación, las matrices tienen verificación en tiempo de ejecución, y esos enfoques son en su mayoría incompatibles. Al principio lo sugerí:
@SuppressWarnings("unchecked")
public <T> T[] ConvertToArray(List<T> list)
{
Object[] result = new Object[list.size()];
result = list.toArray(result);
return (T[])result;
}
Esto está mal de un modo sigiloso, como al menos una otra persona aquí pensaron que iba a funcionar! Sin embargo, cuando lo ejecuta, obtiene un error de tipo incompatible, porque no puede convertir un Objeto [] en un Entero []. ¿Por qué no podemos obtener T.class y crear una matriz del tipo correcto? O ¿new T[]
?
Los genéricos usan tipo borrado para conservar la compatibilidad con versiones anteriores. Se controlan en tiempo de compilación, pero se eliminan del tiempo de ejecución, por lo que el bytecode es compatible con las JVM pregenéricas. Esto significa que no puede tener conocimiento de clase de una variable genérica en tiempo de ejecución.
Así, mientras que usted puede garantizar que habrá T[] result
del tipo Integer [] antes de tiempo, el código list.toArray(result);
(o new T[]
o Array.newInstance(T.class, list.size());
) realizarán siempre en tiempo de ejecución, y no se puede saber qué es T!
Aquí hay una versión que hace trabajo, como recompensa por la lectura de esa conferencia:
public static <T> T[] convertToArray(List<?> list, Class<T> c) {
@SuppressWarnings("unchecked")
T[] result = (T[]) Array.newInstance(c, list.size());
result = list.toArray(result);
return (T[]) result;
}
en cuenta que tenemos un segundo parámetro para proporcionar la clase en tiempo de ejecución (así como en tiempo de compilación a través de los genéricos) Se podría utilizar este modo:
Integer[] arrayOfIntegers = convertToArray(listOfIntegers, Integer.class);
¿Vale la pena la molestia? Todavía tenemos que suprimir una advertencia, ¿entonces definitivamente es seguro?
Mi respuesta es sí. La advertencia generada allí es solo un "No estoy seguro" del compilador. Al recorrerlo, podemos confirmar que el lanzamiento siempre tendrá éxito, incluso si coloca la clase incorrecta como el segundo parámetro, se lanza una advertencia en tiempo de compilación.
La principal ventaja de hacer esto es que hemos centralizado la advertencia en un solo lugar. Solo necesitamos probar este lugar correcto, y sabemos que el código siempre tendrá éxito. Para citar la documentación de Java:
el lenguaje está diseñado para garantizar que si toda su aplicación se ha compilado sin advertencias sin marcar usando javac -source 1.5, que es un tipo seguro [1]
Así que ahora en lugar de tener estas advertencias en todo su código, es solo en un lugar, y puede usar esto sin tener que preocuparse, existe un riesgo enormemente reducido de que se equivoque al usarlo.
Es posible que también desee consultar this SO answer que explica el problema con más profundidad, y this answer que fue mi hoja de cuna al escribir esto. Además del already cited Java documentation, otra referencia útil que utilicé fue this blog post por Neal Gafter, ex ingeniero de personal de Sun Microsystems y co-diseñador de las características del lenguaje 1.4 y 5.0.
Y, por supuesto, ¡gracias a ShaneC que acertadamente señaló que mi primera respuesta falló en el tiempo de ejecución!
Gracias por arreglar mi ToArray S.P .. ¿puedes decir que soy un desarrollador natural de C#? : D –