2009-07-15 12 views

risposta

335

generici volte Java semplicemente non consentono di fare ciò che si vuole, e avete bisogno di raccontare in modo efficace al compilatore che quello che stai facendo veramente sarà essere legale in fase di esecuzione.

Di solito trovo questo un problema quando sto prendendo in giro un'interfaccia generica, ma ci sono anche altri esempi. Di solito vale la pena tentare di evitare un avvertimento piuttosto che sopprimerlo (lo Java Generics FAQ aiuta qui) ma a volte anche se è possibile , il codice si piega così tanto che la soppressione dell'avviso è più netta. Aggiungi sempre un commento esplicativo in quel caso!

Le stesse FAQ generiche hanno diverse sezioni su questo argomento, a partire da "What is an "unchecked" warning?" - vale la pena leggerlo.

+8

In alcuni casi, è possibile evitarlo utilizzando YourClazz.class.cast(). Funziona per singoli contenitori di elementi generici ma non per raccolte. – akarnokd

+0

O preferibilmente usare generici con caratteri jolly '(YourClazz )' - Java non avverte mai su tali tipi di cast quanto sono sicuri. Tuttavia, ciò non funzionerà sempre (consultare le Domande frequenti sui generici per i dettagli). – xfix

39

È un'annotazione per sopprimere gli avvisi di compilazione relativi alle operazioni generiche non controllate (non alle eccezioni), ad esempio le conversioni. Significa essenzialmente che il programmatore non desiderava essere informato di ciò di cui è già a conoscenza durante la compilazione di un particolare bit di codice.

Si può leggere di più su questo specifica annotazione qui:

SuppressWarnings

Inoltre, Oracle fornisce una certa documentazione tutorial su l'uso di annotazioni qui:

come dicono loro,

"L'avvertimento 'incontrollata' può accadere quando ci si interfaccia con il codice legacy scritto prima dell'avvento dei generici (discusso nella lezione intitolata Generics)."

9

L'annotazione SuppressWarning viene utilizzata per sopprimere gli avvisi del compilatore per l'elemento annotato. In particolare, la categoria unchecked consente la soppressione degli avvisi del compilatore generati come risultato di cast di tipi non controllati.

+0

Il tuo link SupressWarning è morto; ecco un'alternativa: http://docs.oracle.com/javase/specs/jls/se6/html/interfaces.html#9.6.1.5 –

3

Per quanto ne so, per ora ha a che fare con la soppressione degli avvertimenti sui generici; i generici sono un nuovo costrutto di programmazione non supportato nelle versioni JDK precedenti a JDK 5, quindi qualsiasi mix dei vecchi costrutti con quelli nuovi potrebbe portare a risultati inattesi.

Il compilatore avverte il programmatore a riguardo, ma se il programmatore sa già, può disattivare quegli avvisi temuti usando SuppressWarnings.

+1

JDK5 è nuovo? Ha completato la maggior parte del periodo di fine vita del servizio. –

+0

So che JDK 5 è piuttosto obsoleto, intendevo dire che è nuovo, nel senso che ha introdotto nuove funzionalità in Java, in precedenza non offerte in JDK 4. Si noti anche che ci sono ancora quelli in attesa di JDK 7 prima di lasciare JDK 5 dietro per abbracciare JDK 6, non riesco a capire perché! – BakerTheHacker

17

Potrebbe anche significare che l'attuale versione del sistema di tipo Java non è sufficiente per il tuo caso. Ci sono stati diversi JSR propositions/hack per risolvere questo problema: digitare i token, Super Type Tokens, Class.cast().

Se hai davvero bisogno di questa supressione, restringila il più possibile (ad esempio non metterla sulla classe stessa o su un metodo lungo). Un esempio:

public List<String> getALegacyListReversed() { 
    @SuppressWarnings("unchecked") List<String> list = 
     (List<String>)legacyLibrary.getStringList(); 

    Collections.reverse(list); 
    return list; 
} 
5

È possibile sopprimere gli avvisi del compilatore e comunicare ai generici che il codice che è stato scritto è legale in base ad esso.

Esempio:

@SuppressWarnings("unchecked") 
public List<ReservationMealPlan> retreiveMealPlan() { 
    List<ReservationMealPlan> list=new ArrayList<ReservationMealPlan>(); 
    TestMenuService testMenuService=new TestMenuService(em, this.selectedInstance); 
    list = testMenuService.getMeal(reservationMealPlan); 
    return list; 
} 
5

Un trucco è quello di creare un'interfaccia che si estende un'interfaccia di base generico ...

public interface LoadFutures extends Map<UUID, Future<LoadResult>> {} 

Quindi è possibile controllare con instanceof prima che il cast ...

Object obj = context.getAttribute(FUTURES); 
if (!(obj instanceof LoadFutures)) { 
    String format = "Servlet context attribute \"%s\" is not of type " 
      + "LoadFutures. Its type is %s."; 
    String msg = String.format(format, FUTURES, obj.getClass()); 
    throw new RuntimeException(msg); 
} 
return (LoadFutures) obj; 
7

Semplicemente: è un avviso mediante il quale il compilatore indica che non è possibile garantire la sicurezza del tipo.

metodo di servizio APP per esempio:

@SuppressWarnings("unchecked") 
public List<User> findAllUsers(){ 
    Query query = entitymanager.createQuery("SELECT u FROM User u"); 
    return (List<User>)query.getResultList(); 
} 

Se didn'n anotate le @SuppressWarnings ("incontrollato") qui, sarebbe un problema con la linea, dove voglio restituire il mio risultante.

In shortcut type-safety significa: Un programma è considerato sicuro dal tipo di carattere se viene compilato senza errori e avvisi e non genera inaspettate ClassCastException in fase di esecuzione.

costruisco su http://www.angelikalanger.com/GenericsFAQ/FAQSections/Fundamentals.html

+2

Questo è un buon esempio per la situazione in cui è necessario utilizzare SuppressWarnings. – Jimmy

0

In Java, i generici sono implementati per mezzo di tipo cancellazione. Ad esempio, il seguente codice.

List<String> hello = List.of("a", "b"); 
String example = hello.get(0); 

Viene compilato di seguito.

List hello = List.of("a", "b"); 
String example = (String) hello.get(0); 

E List.of è definito come.

static <E> List<E> of(E e1, E e2); 

Quale dopo la cancellazione del tipo diventa.

static List of(Object e1, Object e2); 

Il compilatore non ha idea di che cosa sono i tipi generici in fase di runtime, quindi se si scrive qualcosa di simile.

Object list = List.of("a", "b"); 
List<Integer> actualList = (List<Integer>) list; 

Java Virtual Machine non ha idea di quali tipi generici sono durante l'esecuzione di un programma, quindi questo viene compilato ed eseguito, per quanto riguarda Java Virtual Machine, questo è un cast di List tipo (questa è l'unica cosa che può verificare , quindi verifica solo quello).

Ma ora aggiungere questa linea.

Integer hello = actualList.get(0); 

E JVM getterà un inaspettato ClassCastException, come compilatore Java inserito un cast implicito.

java.lang.ClassCastException: java.base/java.lang.String cannot be cast to java.base/java.lang.Integer 

Un unchecked avvertimento dice che un programmatore un cast può causare un programma per generare un'eccezione da qualche altra parte. Sopprimendo l'avviso con @SuppressWarnings("unchecked") si dice al compilatore che il programmatore crede che il codice sia sicuro e non causerà eccezioni impreviste.

Perché vuoi farlo? Il sistema di tipo Java non è abbastanza buono da rappresentare tutti i possibili schemi di utilizzo del tipo. A volte potresti sapere che un cast è sicuro, ma Java non fornisce un modo per dirlo - per nascondere avvertimenti come questo, è possibile utilizzare @SupressWarnings("unchecked"), in modo che un programmatore possa concentrarsi sugli avvisi reali. Ad esempio, Optional.empty() restituisce un singleton per evitare l'allocazione di opzioni vuote che non memorizzano un valore.

private static final Optional<?> EMPTY = new Optional<>(); 
@SuppressWarnings("unchecked") 
public static <T> Optional<T> empty() { 
    return (Optional<T>) EMPTY; 
} 

Questo cast è sicuro, in quanto il valore memorizzato in un optional vuoto non può essere recuperata in modo non v'è alcun rischio di inaspettate eccezioni di classe del cast.

Problemi correlati