2010-02-06 10 views
6

Jestem nowicjuszem w Javie. Piszę klasę, w której konstruktor musi sprawdzić parametr ceny i upewnić się, że nie jest liczbą ujemną. A jeśli jest ujemny, musi ustawić cenę na zero. Dostaję błąd stackoverflow, kiedy sprawdzam cenę. Czy mogę uzyskać pomoc dotyczącą tego, co zrobiłem źle?Błąd stackoverflow w java

public class Book 
{ 
    private String title; 
    private String author; 
    private String isbn; 
    private int pages; 
    private boolean pback; 
    private double price; 

    /** 
    * Constructor for objects of class Book 
    */ 
    public Book(String bookTitle, String bookAuthor, String bookCode, int bookPages, boolean paperback, double bookRetail) 
    { 
     title = bookTitle; 
     author = bookAuthor; 
     isbn = bookCode; 
     pages = bookPages; 
     pback = paperback; 
     price = bookRetail; 
    } 

    /** 
    * @returns title 
    */ 

    public String gettitle() 
    { 
     return title; 
    } 

    /** 
    * @returns author 
    */ 

    public String getauthor() 
    { 
     return author; 
    } 

    /** 
    * @returns ISBN# 
    */ 

    public String getisbn() 
    { 
     return isbn; 
    } 

    /** 
    * @return number of pages 
    */ 

    public int getpages() 
    { 
     return pages; 
    } 

    /** 
    * @return is book paperback 
    */ 

    public boolean getpback() 
    { 
     return pback; 
    } 

    /** 
    * @return retail price 
    */ 

    public double getprice() 
    { 
     if(getprice() < 0) 
     { 
      return 0; 
     } 
     else 
     { 
      return price; 
     } 

    } 
} 
+4

+1 za samodostępne stackoverflow na stackoverflow! – trashgod

+0

teraz niektórzy mogą zrozumieć, co oznacza nazwa witryny ... –

+0

Tak meta! Zastanawiam się, czy przyszedł tutaj, szukając hasła "stackoverflow".:-) – ibz

Odpowiedz

14

Twoja metoda getprice() nazywa się zamiast sprawdzania price. Prowadzi to do nieskończonej rekurencji w tym przypadku.

+1

+1, i skomentuj odpowiedź Ignacio: nowoczesne IDE zauważą nieskończoną rekursję i ostrzeżą cię o tym w czasie rzeczywistym (używam IntelliJ i ostrzega Cię o takich błędach, jestem pewien, że inne IDE robią to samo). – SyntaxT3rr0r

+1

można również przepisać to tak: if (cena <0) {return 0; } cena powrotu; Reszta nie jest potrzebna. – Woot4Moo

+3

Jeśli chcesz uzyskać * NAPRAWDĘ * wybredny, możesz napisać to jako 'return Math.max (price, 0);'. –

1

Ignacio wyjaśnił przyczynę i rozwiązanie:

zmienić linię

if(getprice() < 0) 

do tego:

if(price < 0) 
1

Twój uzyskanie nieskończonej rekurencji, ponieważ stan if sprawdza getprice() metoda, a nie zmienna price.

Wiele współczesnych kompilatorów ostrzega, gdy zakoduje się coś, co powoduje nieskończoną rekurencję.

Nadal czasami napotykam ten błąd, szczególnie w przypadku IDE, które mają intellisense.

Powodzenia w nauce Java! :)

1

Podczas pisania fasoli generalnie chcesz sprawdzić, czy ustalana cena to < 0, zamiast wykonywać te obliczenia za każdym razem, gdy próbujesz uzyskać zmienną.

+1

Osoba początkująca może mieć trudności ze zrozumieniem koncepcji "fasoli";) –

1

Nie jest to utwardzanie dla problemu rekursji, ale należy również rozważyć sprawdzenie ceny w czasie budowy.
Czasami (większość razy?) Lepiej jest, jeśli konstruktor zawiedzie z wyjątkiem, zamiast pozwolić na konstrukcję niespójnego obiektu. W ten sposób łatwiej jest zlokalizować taki błąd.
Przykład:

public Book(String bookTitle, String bookAuthor, String bookCode, int bookPages, boolean paperback, double bookRetail) 
{ 
    if (bookRetail < 0.0) 
     throw new IllegalArgumentException("negative bookRetail: " + bookRetail); 
    ... 
} 

Istnieje ryzyko, że aplikacja może zawieść, gdy w środowisku produkcyjnym, które mogą być bałagan. Aby tego uniknąć, możesz użyć numeru assert lub przynajmniej podać lub zarejestrować błąd i użyć innej opcji. Kontrola assert musi być włączona do programowania i może być wyłączona podczas produkcji. O szczegóły patrz Programming With Assertions

public Book(String bookTitle, String bookAuthor, String bookCode, int bookPages, boolean paperback, double bookRetail) 
{ 
    assert bookRetail >= 0.0 : bookRetail; 
    ... 
} 

lub

public Book(String bookTitle, String bookAuthor, String bookCode, int bookPages, boolean paperback, double bookRetail) 
{ 
    if (bookRetail >= 0.0) { 
     price = bookRetail; 
    } else { 
     price = 0.0; 
     // display or log the "illegal argument" 
     Exception ex = new IllegalArgumentException("negative bookRetail: " + bookRetail); 
     ex.printStackTrace(); 
    } 
    ... 
} 
+0

Wystarczy się upewnić, że podczas wdrażania wzorca IDisposable/Finalizer, może on obsługiwać częściowo zbudowany obiekt. – TToni

+0

@TToni; dlaczego częściowo zbudowany obiekt? Zastanawiam się tylko nad sprawdzeniem wartości w czasie budowy, a nie przy dostępie do pola. Obiekt zostanie w pełni skonstruowany lub w ogóle nie będzie obiektu (w przypadku rzucania wyjątku). –

+0

Wyobraź sobie na przykład obiekt, który otwiera dwa pliki uchwytów w swoim konstruktorze. Wyjątek w konstruktorze może pozostawić brak, jeden lub dwa pliki otwarte. Więc jeśli wystąpi wyjątek konstruktora, środowisko wykonawcze wywoła twój finalizator (jeśli taki posiadasz), który musi sobie poradzić z tą sytuacją. – TToni

0

Twój getprice powinien po prostu być zapisany jako:

return price < 0 ? 0 : price; 

Btw, miło zobaczyć, że to błąd stackoverflow jest rozwiązany przez stackoverflow.com

+1

'reurn' nie jest prawidłowym słowem kluczowym Java ... –

+0

Poprawione, dziękuję. – fastcodejava