¿Por qué no puedo pasar explícitamente el argumento de tipo a un método Java genérico?

StackOverflow https://stackoverflow.com/questions/24991

  •  09-06-2019
  •  | 
  •  

Pregunta

He definido una función Java:

static <T> List<T> createEmptyList() {
    return new ArrayList<T>();
}

Una forma de llamarlo es así:

List<Integer> myList = createEmptyList(); // Compiles

¿Por qué no puedo llamarlo pasando explícitamente el argumento de tipo genérico? :

Object myObject = createEmtpyList<Integer>(); // Doesn't compile. Why?

Recibo el error Illegal start of expression del compilador.

¿Fue útil?

Solución

Cuando el compilador de Java no puede inferir el tipo de parámetro por sí mismo para un método estático, siempre puede pasarlo usando el nombre completo del método calificado: Clase. < Escriba & Gt; método ();

Object list = Collections.<String> emptyList();

Otros consejos

Puede, si pasa el tipo como parámetro de método.

static <T> List<T> createEmptyList( Class<T> type ) {
  return new ArrayList<T>();
}

@Test
public void createStringList() {
  List<String> stringList = createEmptyList( String.class );
}

Los métodos no pueden ser generizados de la misma manera que un tipo, por lo que la única opción para un método con un tipo de retorno genérico de tipo dinámico, es decir, un bocado :-), es pasar el tipo como un argumento.

Para obtener una excelente Preguntas frecuentes sobre genéricos de Java, consulte las Preguntas frecuentes sobre genéricos de Angelika Langer .

.
.

Seguir-: <

No tendría sentido en este contexto utilizar el argumento de matriz como en Collection.toArray( T[] ). La única razón por la que se usa una matriz es porque la misma matriz (preasignada) se usa para contener los resultados (si la matriz es lo suficientemente grande como para que quepan todos). Esto ahorra en la asignación de una nueva matriz en tiempo de ejecución todo el tiempo.

Sin embargo, a los fines de la educación, si desea utilizar el tipo de matriz, la sintaxis es muy similar:

static <T> List<T> createEmptyList( T[] array ) {
  return new ArrayList<T>();
}

@Test
public void testThing() {
  List<Integer> integerList = createEmptyList( new Integer[ 1 ] );
}

Hacía bastante tiempo que no buscaba en esas partes de Java, pero ...

¿Por qué no puede hacerlo? Probablemente fue una elección de diseño por parte de los desarrolladores del lenguaje. Aún así, debido a la tipo de borrado empleado por Java , la información genérica se descarta en el momento de la compilación de todos modos, por lo que, en su ejemplo, crearía exactamente el mismo código de byte si tenía el parámetro de tipo o no.

@pauldoo Sí, tienes toda la razón. Es una de las debilidades con los genéricos java imho.

Respondo a Cheekysoft. Me gustaría proponer que también mire cómo lo hacen las personas Java, como T [] AbstractCollection # toArray (T [] a). Creo que la versión de Cheekysofts es superior, pero la de Java tiene la ventaja de la familiaridad.

Editar: Enlace agregado. Reeditar: se encontró un error en SO :)


Seguimiento en Cheekysoft: Bueno, como es una lista de algún tipo que debería devolverse, el ejemplo correspondiente debería verse así:

static <T> List<T> createEmptyList( List<T> a ) {
  return new ArrayList<T>();
}

Pero sí, pasar el objeto de clase es claramente el mejor. Mi único argumento es el de familiaridad, y en este caso exacto no vale mucho (de hecho es malo).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top