java - into - pass arraylist to array
Comportamiento genérico impar de List.toArray(T[]) (5)
Encontré algo muy básico pero extremadamente desconcertante hoy. Necesitaba convertir una lista a una matriz. La lista contenía instancias de String
. Ejemplo perfecto de usar List.toArray(T[])
, ya que quería una instancia de String[]
. Sin embargo, no funcionaría sin lanzar explícitamente el resultado a String[]
.
Como escenario de prueba, utilicé el siguiente código:
import java.util.Arrays;
import java.util.List;
public class MainClass {
public static void main(String args[]) {
List l = Arrays.asList("a", "b", "c");
String stuff[] = l.toArray(new String[0]);
System.err.println(Arrays.asList(stuff));
}
}
que no se compila. Es casi una copia exacta del ejemplo en el javadoc , sin embargo, el compilador dice lo siguiente:
MainClass.java:7: incompatible types
found : java.lang.Object[]
required: java.lang.String[]
String stuff[] = l.toArray(new String[0]);
^
Si agrego un molde a String[]
, se compilará Y se ejecutará perfectamente. Pero eso no es lo que esperaba cuando miré la firma del método toArray:
<T> T[] toArray(T[] a)
Esto me dice que no debería tener que lanzar. Que esta pasando?
Editar:
Curiosamente, si cambio la declaración de la lista a:
List<?> l = Arrays.asList("a", "b", "c");
tambien funciona O List<Object>
. Por lo tanto, no tiene que ser una List<String>
como se sugirió. Estoy empezando a pensar que usar el tipo de List
procesar también cambia la forma en que funcionan los métodos genéricos dentro de esa clase.
Segunda edición:
Creo que lo entiendo ahora. Lo que Tom Hawtin escribió en un comentario a continuación parece ser la mejor explicación. Si utiliza un tipo genérico de forma bruta, el compilador borrará toda la información genérica de esa instancia.
Eso es porque su lista contiene objetos, no cadenas. Si hubiera declarado su lista como List<String>
, el compilador estaría contento.
o hacer
List<?> l = Arrays.asList("a", "b", "c");
todavía extraño
olvidó especificar el parámetro de tipo para su Lista:
List<String> l = Arrays.asList("a", "b", "c");
En este caso puedes escribir seguridad:
String[] a = l.toArray(new String[0]);
sin ningún elenco.
List
sin un tipo declarado se establecerá de manera predeterminada en "Lista de objetos", mientras que List<?>
Significa "Lista de desconocidos". En el mundo de los tipos genéricos, es un hecho que "Lista de objetos" es diferente de "Lista de cadenas" pero el compilador no puede decir lo mismo para "Lista de desconocidos". Si lo has declarado como desconocido, entonces, por lo que el compilador puede decir, está bien.
¿El punto principal es que declarar algo como el comodín? Es diferente de declararlo como Objeto. Lea más sobre comodines here
List<String> l = Arrays.asList("a", "b", "c");
esto lo hará compilar, estás usando genéricos para decir "esta es una lista de cadenas", por lo que el método toArray sabe qué tipo de matriz devolver.