2013-05-24 22 views
9

Mam prostą klasę podobną do poniższej, ale mam pytanie dotyczące używania generycznych, aby zwrócić wartość.Jak zwrócić liczbę używając generycznych w Javie?

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 musi dostać 0 (lub 0,0 - to zależy od wartości T) kiedy < list.size() nie jest zerowy. Jak mogę to poprawnie zakodować, aby to zrobić?

+2

Zamiast tego zwracamy 'null', 0 nie jest obiektem. –

+2

Problem polega na tym, że chociaż napisałeś "return 0", java musi zwrócić instancję klasy T, która nie jest znana podczas kompilacji. –

Odpowiedz

9

Jeśli naprawdę chcą powrócić domyślnie 0, można zrobić coś takiego:

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

wtedy implementację dla każdego podtypu numer, który ma na celu wspieranie, np

public class IntegerBox extends Box<Integer> { 

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

i

public class DoubleBox extends Box<Double> { 

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

itp

Przyjemną cechą tego jest to, że może zwracać wartość domyślną, a nie tylko zero ... i ta sama zasada zadziałałaby dla dowolnego typu obiektu, a nie tylko dla liczb.

+1

Chociaż może to być * dobre * rozwiązanie, musisz zaimplementować dziecko dla każdej klasy, która rozszerza 'Number':' Byte', 'Short',' Integer', 'Long',' Float', 'Double',' BigInteger', 'BigDecimal',' AtomicInteger' (i na ...). Jest więcej kodu na ten temat niż obsługa wyniku 'null' lub obsługa' wyjątku'. –

+2

Tak, jest więcej kodu ... ale to daje oryginalnemu pytającemu, o co prosił! –

+0

IMO wysiłek zrobienia * dobrego * projektu nie jest wart tego w tym konkretnym przypadku. –

2

0 to int, a generyczne działa tylko z odniesieniami do obiektów (nie jako typy pierwotne). Sposób na naprawienie kodu powróciłby zamiast tego do wersji null.

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

I musi sobie 0 (lub 0,0 - zależy to od T) kiedy < list.size() nie null

Weź pod uwagę, że prezentacja tematów jako show 0 to user musi być obsługiwane przez klasy/metody, które pokazują dane, a nie za pomocą tych metod. Oznacza to, że nie ma możliwości zwrócenia 0, gdy musisz zwrócić obiekt o numerze referencyjnym.

9

Jeśli naprawdę potrzebujesz swoją Box zwrócić wartość zero lub domyślny, że gdy get nie znajdzie dopasowanie, można mieć parametr konstruktora do zera lub domyślnego typu T.

zwrócą ją domyślną wartość w metodzie get.

Przykład:

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

Nie można tego zrobić bez tworzenia podklasy dla wszystkich typów i bez parametryzacji i wyraźnie sprawdzania typu. I jest to normalne: mogę utworzyć typ

public StrictlyPositiveInteger implements Number 

że nawet nie miała wartość 0, a następnie wykonaj

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

Innymi słowy: chcesz specyficzne zachowanie określonych typów, więc nie możesz tego zrobić w sposób ogólny.

+0

Solidne wyjaśnienie i przykład. – jahroy

Powiązane problemy