2012-06-16 16 views
12

Teniendo en cuenta este código:¿Existe alguna manera clara de asignar la clase de un tipo genérico a una variable?

List<Integer> ints = new ArrayList<Integer>(); 

// Type mismatch: 
// cannot convert from Class<capture#1-of ? extends List> to Class<List<Integer>>  
Class<List<Integer>> typeTry1 = ints.getClass(); 

// Type safety: 
// Unchecked cast from Class<capture#2-of ? extends List> to Class<List<Integer>> 
Class<List<Integer>> typeTry2 = (Class<List<Integer>>) ints.getClass(); 

// List is a raw type. References to generic type List<E> should be parameterized 
Class<? extends List> typeTry3 = ints.getClass(); 

¿Hay una manera de conseguir la Class de un List<Integer> sin un error o una advertencia? Puedo suprimir las advertencias con la suficiente facilidad, pero si Java requiere que suprima una advertencia para este código válido, soy muy disappoint.

Por otro lado, si la supresión de advertencia es la única manera, ¿cuál es el más seguro para suprimir?

+0

Aparentemente, no hay advertencia de forma gratuita debido a la eliminación. http://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens – user845279

+0

No tiene sentido utilizar un tipo genérico concreto para la referencia de objeto de clase, porque esa información no es allí en el objeto que se hace referencia, por lo que en mi opinión 'Clase 'o' Class > 'son los mejores tipos para la variable. Sin embargo, me sorprendió que no pudiera encontrar un lanzamiento sin advertencia para el tipo de objetivo comodín ...Sin embargo, como los objetos de clase se usan principalmente para la reflexión de todos modos, puede estar bien usando 'Clase ', que funciona sin advertencias –

Respuesta

5

Este es un verdadero Catch-22 en Java.

El compilador le avisa si no se agrega un tipo genérico de List:

// WARN: List is not typed 
Class<? extends List> typeTry3 = ints.getClass(); 

Eso es porque, en la mayoría de los casos, es realmente la mejor manera de escribir sus listas.

Sin embargo, debido a la supresión de tipo, no hay forma de que Java averigüe el tipo genérico de List en tiempo de ejecución, y el compilador lo sabe. Por lo tanto, no existe un método en el que se Class vuelto un objeto escrito:

// ERROR: ints.getClass() doesn't return a Class<List<Integer>>, it returns a Class<List> 
Class<? extends List<? extends Integer>> var = ints.getClass(); 

Así que hay que fundido a una lista de tipos. Sin embargo, como es sabido, ya que no hay verificación de tipos en tiempo de ejecución, Java le avisará de cualquier moldes a una variable de tipo:

// WARN: Casting to typed List 
Class<List<Integer>> typeTry2 = (Class<List<Integer>>) ints.getClass(); 

Cualquier intento de evitar esto es esencialmente un medio de confundir el compilador, y que inevitablemente ser intrincado

Su mejor apuesta es, entonces, para ir con la opción B:

Por otro lado, si la supresión de advertencia es la única manera, lo que es el más seguro para suprimir?

La manera más segura de suprimir esta advertencia es hacer que su anotación @SuppressWarnings("unchecked") sea lo más localizada posible. Ponlos encima de cada elenco sin marcar individual. De esa forma, está absolutamente claro quién está causando la advertencia.

3

Una forma de hacerlo sería crear su own class. No estoy seguro si esto satisfaría sus necesidades.

No estoy seguro de lo que está tratando de lograr. Entonces quizás wildcards es la respuesta.

import java.util.*; 

class Main 
{ 
     public static void main(String[] args) 
     { 
      List<Integer> list = new ArrayList<Integer>(); 
      Class<?> clazz = list.getClass(); 
      System.out.println(clazz) ; 
     } 
} 
+0

+1 sin advertencias o errores, pero todavía bastante hacky :) – cqcallaw

+0

Me parece una solución faire decirle al compilador: "Sé que obtendré una clase de _algo_, por favor dámelo sin quejas, aunque _usted_ (el compilador) no pueda inferir/mantenga el tipo de este _algo_". –

Cuestiones relacionadas