2010-10-01 53 views
3

假設我在書架上有一個方法getBook()。如果書架不是空的,該方法應該只返回一個Book對象。但是,Java需要該方法在任何情況下都返回一個Book對象。我可以有一個方法isShelfEmpty()這是第一次調用,但似乎尷尬有揭示書架給調用者的執行。最乾淨的方法是什麼?在Java中有條件地返回對象(沒有迭代器)

Iterator會使這個更簡單,但這是一個類項目,我們還沒有覆蓋類中的迭代器。

編輯:

我曾想過返回null,但出於某種原因,似乎有點醜陋的我。這是最好的選擇,還是有另一種?

+1

好吧,如果你不返回NULL,你可以返回一個代表書架缺少書本的「虛擬」書,也可能包含一個叫做isDummyBookBecauseShelfIsEmptyAndIDontWantToReturnNull的指示器,所以你知道這本書是你得到的真的不是一本書......但是你*有*返回*某物* ...我想你在試圖從它那裏拿一本書之前檢查貨架是不是空的,但那只是我。 – FrustratedWithFormsDesigner 2010-10-01 17:52:32

+0

當你不習慣使用null時,返回null看起來很難看。空有效意味着「沒有」,因此,在您適應返回null之後,您會意識到,當調用getBook(...)時,空的書架應該不會返回任何內容。 – 2010-10-01 18:35:01

+0

如果這是Scala或Haskell,您可以分別返回'Option '或'Maybe Book',以表明不存在任何書。 – 2010-10-01 18:41:32

回答

10

如果沒有書可用,您可以返回null。然後,你必須在你每次請求書,當然時間來檢查null

如果在沒有書可用時調用方法getBook(),我將執行方法isBookAvailable()並引發異常。

+0

YMMV但我發現處理空迴應(正確記錄時)比捕獲異常更容易 – 2010-10-01 17:57:03

+0

我認爲,如果存在'isBookAvailable()',那麼從'getBook()'返回'null'就可以。這個想法是,如果得到你知道的東西不存在,你不能指望'getBook()'會返回什麼。另一種看待它的方法是,你可以拋出未被選中的'IllegalStateException',並且你不需要任何東西。 – 2010-10-01 18:07:32

+0

@matt b:我認爲這個想法是,如果書不存在,你就不會發現異常。如果isBookAvailable()返回了'true',那麼該類的客戶端只需調用'getBook()',所以當一本書不可用時調用'getBook()'會顯示編程錯誤。通過使用一個異常而不是一個可能沉默的,被忽略的'null',任何這樣的錯誤都會被提前發現。 – ColinD 2010-10-01 18:37:32

4

正如tangens所說,你可以返回null或拋出異常。哪個選項取決於您選擇是否從空Bookshelf請求書是錯誤或不。

理想情況下Bookshelf將持有對Book實例的集合的引用,如果需要可以爲空。這對你的模型來說是一個更好的抽象。

+0

+1:要求一本書隨機拿一本書是無稽之談。我喜歡這個想法,以返回可用書籍的集合,可能是空的。 – tangens 2010-10-01 17:54:48

+0

他說這個類沒有覆蓋迭代器,也可能他們還沒有完成集合。 – FrustratedWithFormsDesigner 2010-10-01 17:58:03

+0

準確地說 - 我已經有了比Java更多的Python經驗,但是如果Python像Java這樣的東西,那看起來更像是一種更爲理智的方式。不幸的是,我們還沒有觸及集合。 : -/ – chimeracoder 2010-10-01 18:08:33

0

如果你不想返回NULL,那麼你需要返回的東西是一本書或不是一本書。要實現這一點,你需要一個父類或接口是一樣的東西「BookOrEmptySpace」(愚蠢的名字),可以生孩子「尚書」或「EmptySpace」。

你是在談論一個BookOrEmptySpace那麼你測試,看它是否是一個instanceof書或一個instanceof EmptySpace回報的方法。

這不會添加任何內容,除非EmptySpace具有它自己的某些屬性,所以幾乎每個人都只返回null - 事實上,null正是您的情況所需,並且是對大多數人來說本質上直觀的情況之一程序員。

您可能希望與註釋標記它 - 在這種情況下,我認爲這是@Nullable(這表明大多數程序員,如果沒有的書要歸還它會返回null)

0

你將如何如果沒有任何東西,它就不會返回任何東西,就知道這裏沒有東西?!?!最終,你必須測試,看看如果事情是存在的 - 這既可以嘗試得到的東西之前或之後完成你再檢查,看看是否是你得到的是一本書。

老實說你期望什麼任何在這種情況下做的編程語言?!?!

1

你有兩個非基於迭代器選項。

  1. 你可以返回null,這基本上意味着Book getBook(...)如果書架上沒有書,它將不會返回任何東西。

在這種情況下,代碼會看起來像:

public class BookShelf { 

    Book getBook(...) { 
    if (empty) { 
     return null; 
    } 
    } 

} 
  1. 您可以創建一個哨兵對象,Book,表示沒有其他書籍。如果貨架是空的,你會返回哨兵。

典型的哨兵是用NIL約定來命名的,它與null類似,但是是一個完整的對象。所以在你的課堂上,你會有這樣的:

public class BookShelf { 
    public static final NIL = new Book(); 

    ... 

    public Book getBook(...) { 
    if (empty) { 
     return NIL; 
    } 
    } 

} 

這避免使用空指針;但是,它涉及使用額外的「NIL」對象。在Java中,儲蓄是最小的,但有時他們是值得的。基本上與第一解決方案的代碼看起來像

if (shelf.getBook(...) == null) { 
    System.out.println("We ran out of books!"); 
} 

,而在第二個解決方案的代碼看起來像

if (shelf.getBook(...) == BookShelf.NIL) { 
    System.out.println("We ran out of books!"); 
} 

除了因爲這是Java中,更好的回答第二個選項是

if (BookShelf.NIL.equals(shelf.getBook(...))) { 
    System.out.println("We ran out of books!"); 
} 

所以你看,有很多方法可以解決這個問題,但每個方法都有不同的優缺點。關鍵是要麼你什麼都沒有返回(並且編寫你的代碼來處理沒有被返回的東西),要麼你返回的東西意味着「沒有書架」。

1

如果沒有可用的書籍,則應該拋出java.lang.IllegalStateException。從javadocs,IllegalStateException

表示方法在非法或不適當的時間被調用。換句話說,對於請求的操作,Java環境或Java應用程序不處於適當的狀態。

所以我期望的代碼看起來是這樣的:這樣做的

public Book getBook() { 
    if(books.isEmpty()) { 
     throw new IllegalStateException(); 
    } 
    // return the book, knowing that the books list has at least one item in it. 
} 
+0

這比返回null更好。因爲如果你忘記檢查空白或無效,如果你不會在你的代碼周圍出現null。它會提前失敗,並帶有乾淨的堆棧跟蹤。 – paradigmatic 2010-10-01 18:48:41

0

兩種不同的方式。基於

  1. 返回值:
    • 返回null爲無書
    • 檢查NULL值基於
  2. 例外:
    • 拋出異常時,沒有書在書架
    • 處理呼叫代碼中的例外情況

已在C/C編程大多++和Python我可以告訴你,爲的情況下沒有可供使用的,沒有具體標識規定(例如getBookAtIndex(14))約定是返回null,NULL,None等。拋出異常保留用於您希望具有剛性標識符的書出現而不出現的情況。

0

實際上,我看到了許多可行的選擇,每個選項都有自己的優勢/弱點。

返回時,有沒有更多的書,由埃德溫·巴克描述的定點對象:

public Book getBook() { 
    public static Book NO_BOOK = new Book(); 
    if(books.empty()) { 
     return NO_BOOK; 
    } 
    ... 
} 
book = shelf.getBook(); 
if(Book.NO_BOOK.equals(book)) { 
    // there were no books 
} 

返回NULL如果沒有更多的書,因爲你提到你不想做

public Book getBook() { 
    if(books.empty()) { 
     return null; 
    } 
    ... 
} 
book = shelf.getBook(); 
if(book == null) { 
    // there were no books 
} 

拋出一個異常時,有沒有留下的書籍,並實現hasMoreBooks。

public boolean hasMoreBooks() { 
    return (! books.empty()); 
} 
public Book getBook() { 
    if(books.empty()) { 
     throw new IllegalStateException("no more books"); 
    } 
    ... 
} 
if(shelf.hasMoreBooks()) { 
    book = shelf.getBook(); 
    // you know it's a valid book here 
} 

在其他語言中實現一個也許類型包裝按哈斯克爾。這種類型的對象表示「可能是書,或可能沒有」的東西。然後調用者負責檢查它是否是有效的書。對於爲這種類型的操作(模式匹配等)提供良好支持並且不支持null的語言(null是魔鬼;),這是一個很好的解決方案。對於Java,我傾向於認爲它是過度的。

至於「揭露實施」,我不認爲這是不合理的,用戶知道書架可以「出書」,並認爲這是無法從它那裏得到一本書,如果是這樣的話。

編輯:我會添加一個與這個問題沒有直接關係的註釋,但值得一提。在沒有圖書的情況下拋出異常(並實現hasMoreBooks)的好處之一是,你並不總是需要檢查是否有書。

舉例來說,如果你有一個緊密的循環,通過書籍進行迭代,並有一本書的次數遠遠多於沒有一個,你可以做類似如下:

try { 
    while(true) { 
     book = shelf.getBook(); 
     ... 
    } 
} catch(IllegalStateException ex) { 
    // no more books 
} 

要公平,在大多數情況下,這並不是那麼有用......但如果您擔心必須致電hasMoreBooks的性能成本,並且您知道您很少擁有更多書籍,則上述內容可能會很方便。