2012-06-16 9 views
12

Dato questo codice:Esiste un modo pulito per assegnare la classe di un tipo generico a una variabile?

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(); 

C'è un modo per ottenere il Class di un List<Integer> senza un errore o un avvertimento? Posso sopprimere gli avvertimenti abbastanza facilmente, ma se Java mi richiede di sopprimere un avviso per questo codice valido, sono molto disappoint.

D'altra parte, se la soppressione degli avvisi è l'unico modo, qual è il più sicuro da sopprimere?

+0

Apparentemente non vi è alcun modo libero di avvertimento a causa della cancellazione. http://stackoverflow.com/questions/339699/java-generics-type-erasure-when-and-what-happens – user845279

+0

Non c'è davvero alcun senso nell'utilizzare un tipo generico concreto per il riferimento all'oggetto Class, poiché tale informazione non è lì nell'oggetto a cui si fa riferimento, quindi nelle mie opinioni 'Classe 'o' Classe > 'sono i migliori tipi per la variabile. Sono rimasto sorpreso però che non sono riuscito a trovare un cast privo di avvisi per il tipo di target con caratteri jolly ...Tuttavia, poiché gli oggetti di classe sono per lo più utilizzati per la riflessione, si potrebbe andare bene usando 'Classe ', che funziona senza avvisi –

risposta

5

Questo è un vero Catch-22 in Java.

Il compilatore avverte se non si aggiunge un tipo generico di List:

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

Questo perché, nella maggior parte dei casi, è davvero meglio di digitare le vostre liste.

Tuttavia, a causa della cancellazione dei tipi, Java non è in grado di calcolare il tipo generico di List in fase di esecuzione e il compilatore lo sa. Pertanto, non v'è alcun metodo su Class che restituito un oggetto tipizzato:

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

Così si deve cast a un elenco digitato. Tuttavia, come si sa, dal momento che non v'è alcun tipo di runtime controllo, Java avvisa di eventuali calchi a una variabile digitato:

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

Qualsiasi tentativo per aggirare questo è essenzialmente un mezzo di confondere il compilatore, e inevitabilmente essere contorto.

La cosa migliore quindi è di andare con Opzione B:

D'altra parte, se la soppressione di avviso è l'unico modo, quello che è il più sicuro di sopprimere?

Il modo più sicuro per eliminare questo avviso è rendere l'annotazione @SuppressWarnings("unchecked") il più possibile localizzata. Mettili sopra ogni singolo cast non controllato. In questo modo è assolutamente chiaro chi sta causando l'avvertimento.

3

Un modo per farlo sarebbe creare il tuo own class. Non sono sicuro che questo soddisferà le tue esigenze.

Non sono proprio sicuro di cosa stai cercando di ottenere. Quindi forse wildcards è la risposta.

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 per nessun avviso o errore, ma comunque abbastanza hacky :) – cqcallaw

+0

Mi sembra una soluzione faire per dire al compilatore: "So che otterrò una classe di _qualcosa_, per favore dammelo senza lamentarmi, anche se _you_ (il compilatore) potrebbe non essere in grado di dedurre/mantenere il tipo di questo _qualcosa_". –

Problemi correlati