2013-05-24 7 views
9

Ho una classe semplice come quella seguente, ma ho una domanda sull'utilizzo di generici per restituire un valore.Come restituire un numero utilizzando i generici in Java?

import java.util.ArrayList; 
public class Box<T extends Number> { 
    private ArrayList<T> list; 
    public Box(){ 
     list = new ArrayList<T>(); 
    } 
    public T get(int i){ 
     if(i <list.size()) 
      return list.get(i); 
     else 
      return 0; // Problem 
    } 
} 

I devo ottengo 0 (o 0,0 - dipende dal valore di T) quando i < list.size() non è nullo . Come posso codificarlo correttamente per farlo?

+2

Restituisce 'null' invece, 0 non è un oggetto. –

+2

Il problema è che sebbene tu abbia scritto "return 0", java deve restituire un'istanza di classe T, che non è nota al momento della compilazione. –

risposta

9

Se davvero desidera restituire 0 per impostazione predefinita, si potrebbe fare qualcosa di simile:

public abstract class Box<T extends Number> { 
    private List<T> list; 

    public Box(){ 
     list = new ArrayList<T>(); 
    } 

    public T get(int i){ 
     if(i <list.size()) 
      return list.get(i); 
     else 
      return getDefault(); 
    } 

    protected abstract T getDefault(); 
} 

poi avere un'implementazione per ogni sottotipo numero che si desidera supportare, ad esempio,

public class IntegerBox extends Box<Integer> { 

    @Override 
    protected Integer getDefault() { 
     return 0; 
    } 
} 

e

public class DoubleBox extends Box<Double> { 

    @Override 
    protected Double getDefault() { 
     return 0D; 
    } 
} 

ecc.

Una buona caratteristica di questo è che può restituire qualsiasi valore predefinito, non solo zero ... e lo stesso principio funzionerebbe per qualsiasi tipo di oggetto, non solo per i numeri.

+1

Anche se questa può essere una * buona * soluzione, è necessario implementare un figlio per ogni classe che estende 'Numero':' Byte', 'Breve',' Intero', 'Lungo',' Fluttuante', 'Doppio',' BigInteger', 'BigDecimal',' AtomicInteger' (e su ...). C'è più codice che fa questo piuttosto che gestire un risultato 'null' o gestire un' Exception'. –

+2

Sì, c'è più codice ... ma sta dando al richiedente originale quello che ha chiesto! –

+0

IMO lo sforzo per fare il * buon * design non vale la pena per questo caso specifico. –

2

0 è un int e generici funziona solo con riferimenti oggetto (non tipi primitivi). Un modo per correggere il codice restituirebbe invece null.

public T get(int i){ 
    if(i <list.size()) { 
     return list.get(i); 
    } 
    return null; // Problem solved 
} 

ho devo ottenere 0 (o 0.0 - dipende da T) quando ho < list.size() non null

tener conto che i temi di presentazione come mostra 0 all'utente deve essere gestito dalle classi/metodi che mostrano i dati, non da questi metodi. Ciò significa che, , non è possibile restituire 0 quando è necessario restituire un riferimento oggetto.

9

Se davvero bisogno del vostro Box per restituire un valore pari a zero o di default che, quando il vostro get non trova una corrispondenza, si può avere un parametro del costruttore per lo zero o di default di tipo T.

Poi ritorno che di default valore nel tuo metodo get.

Esempio:

public class Box<T extends Number> { 
    private ArrayList<T> list; 
    private T defaultValue; 
    public Box(T defaultValue){ 
     list = new ArrayList<T>(); 
     this.defaultValue = defaultValue; 
    } 
    public T get(int i){ 
     if(i <list.size()) 
      return list.get(i); 
     else 
      return defaultValue; 
    } 
} 
2

Non si può fare questo senza creare sottoclassi per tutti i tipi e senza parametrizzare e controllare in modo esplicito il tipo. E questo è normale: ho potuto creare un tipo

public StrictlyPositiveInteger implements Number 

che non ha nemmeno il valore 0, e poi fare

Box<StrictlyPositiveInteger> box = new Box<>(); 

In altre parole: si vuole un comportamento specifico per tipi specifici, in modo da non puoi farlo in un modo generico.

+0

Spiegazione e esempio solidi. – jahroy