2012-02-29 7 views
13

In qualche modo la mia vecchia domanda è stata chiusa, in modo da aprire una nuova:Come evitare gli avvertimenti del cast non controllati con Java Generics

Sto usando Java Generics per implementare un generico bidirezionale Hash Mappa di una query SQL. Dovrebbe essere in grado di mappare qualsiasi combinazione di coppie String, Integer avanti e indietro. Dovrebbe essere usato in questo modo:

String sql = "SELECT string_val, int_val FROM map_table"; 
PickMap<String, Integer> pm1 = new PickMap<String, Integer>(sql); 

String key1 = "seven"; 
Integer value1 = pm1.getLeft2Right(key1); 

Integer key2 = 7; 
String value2 = pm1.getRightToLeft(key2); 

Naturalmente dovrebbe essere possibile creare un pm (intero, intero) e così via ...

mia implementazione di Pick Mappa assomiglia a questo (senza il getter ...):

public class PickMap<L, R> { 

    private final HashMap<L, R> left2Right = new HashMap<L, R>(); 
    private final HashMap<R, L> right2Left = new HashMap<R, L>(); 

    public PickMap(String sql) throws OException { 
     DTable d = new DTable(sql); 
     int colTypeL = d.t.getColType(1); 
     int colTypeR = d.t.getColType(2); 
     Extractor<L> extLeft = (Extractor<L>) getInstance(colTypeL); 
     Extractor<R> extRight = (Extractor<R>) getInstance(colTypeR);  
     int numRows = d.t.getNumRows(); 
     for(int i=1;i<=numRows;i++) { 
      L leftVal = extLeft.extract(d, i); 
      R rightVal = extRight.extract(d, i); 
      this.left2Right.put(leftVal, rightVal); 
      this.right2Left.put(rightVal, leftVal); 
     } 
    } 

    private Extractor<?> getInstance(int type) { 
     if(type == 1) 
      return new IntExtractor(); 
     else 
      return new StringExtractor(); 
    } 
} 

interface Extractor<E> { 
    E extract(DTable source, int row); 
} 

class IntExtractor implements Extractor<Integer> { 

    @Override 
    public Integer extract(DTable source, int row) { 
     int value = 5; 
     return new Integer(value); 
    } 
} 

class StringExtractor implements Extractor<String> { 

    @Override 
    public String extract(DTable source, int row) { 
     String retVal = "hello"; 
     return retVal; 
    } 
} 

non ho errori di compilazione e sono abbastanza sicuro, che funzionerà in questo modo. MA sto ricevendo avvisi cast non selezionati sui metodi "getInstance" Dove lancio Extractor (E) su Extractor (L) ...

Come devo trasmettere correttamente? O cosa mi sto perdendo? O dovrei semplicemente sopprimere questi avvertimenti?

risposta

24

Stai ricevendo avvertimenti perché quello che stai facendo non può essere provato per essere sicuro. Sei assumendo che getInstance(colTypeL) restituirà un Extractor<L> - ma che non può essere verificato in fase di compilazione o tempo di esecuzione.

È possibile utilizzare @SuppressWarnings("unchecked") come già detto da altri, ma proverei a ripensare un po 'il progetto.

+0

Sì, ho capito il tuo punto. Vorrei usare il tipo generico L per installare il mio estrattore. Quindi, invece di dare "colType" nel metodo getInstance, mi piacerebbe fare qualcosa come getInstance (L) e getInstance (R) ... È possibile? Odio sopprimere gli avvertimenti! – Sauer

+1

@Sauer: Dovresti conoscere 'L' e' R' al momento dell'esecuzione, che normalmente significa avere parametri di costruzione di tipo 'Classe ' e 'Classe ' o qualcosa di simile. –

+8

Una possibilità è che il costruttore prenda gli estrattori necessari: 'PickMap (String sql, Extractor leftExtractor, Extractor rightExtractor>)'. Questo non solo rende sicura la compilation, ma consente anche a qualcun altro di venire a decidere che vogliono un 'PickMap ' senza dover cambiare il codice 'PickMap' (assumendo che' Extractor' sia un'interfaccia o una classe a cui hanno accesso a). – yshavit

5

È possibile utilizzare la seguente annotazione per rendere il compilatore non emette questi avvertimenti:

@SuppressWarnings("unchecked") 

Vai a questa related question che affronta lo stesso problema. La risposta ci spiegherà tutto ciò che devi sapere.