在Java中有条件地返回对象(没有迭代器)

时间:2010-10-01 17:47:54

标签: java

假设我在Bookshelf类中有一个方法getBook()。如果Bookshelf不为空,则该方法应仅返回Book对象。但是,Java要求该方法在所有情况下都返回Book对象。我可以有一个首先调用的方法isShelfEmpty(),但是向调用者展示Bookshelf的实现似乎很尴尬。最干净的方法是什么?

Iterator会使这更简单,但是这是针对一个类项目的,我们还没有在类中讨论过迭代器。

修改

我考虑过返回null,但出于某种原因,这对我来说似乎有些难看。这是最好的选择,还是有其他选择?

8 个答案:

答案 0 :(得分:10)

如果没有可用的书,您可以返回null。然后,当然,每次你要书时都需要检查null

我会实现一个方法isBookAvailable()并在没有可用的书时调用方法getBook()时抛出异常。

答案 1 :(得分:4)

正如tangens所说,你可以返回null或抛出异常。您选择哪个选项取决于是否从空Bookshelf请求图书是错误。

理想情况下,Bookshelf将保留对Book个实例集合的引用,如果需要,它们可以为空。这对您的模型来说是一个更好的抽象。

答案 2 :(得分:1)

您有两个基于非迭代器的选项。

  1. 您可以返回null,这基本上意味着如果书架上没有书籍,Book getBook(...)将不会返回任何内容。
  2. 在这种情况下,代码看起来像:

    public class BookShelf {
    
      Book getBook(...) {
        if (empty) {
          return null;
        }
      }
    
    }
    
    1. 您可以创建一个标记对象,Book表示没有其他图书。如果货架是空的,您将返回哨兵。
    2. 通常,Sentinel使用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!");
      }
      

      所以你看,有很多方法可以解决这个问题,但每种方法都有不同的优点和缺点。关键是要么你没有返回任何东西(并编写你的代码来处理没有被返回的东西),要么你返回的东西意味着“书架上没有书籍”。

答案 3 :(得分: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.
}

答案 4 :(得分:0)

如果您不想返回Null,那么您需要返回书籍或书籍。要实现这一点,您需要一个类似于“BookOrEmptySpace”(愚蠢名称)的父类或接口,它可以有子项“Book”或“EmptySpace”。

您正在讨论的方法会返回BookOrEmptySpace,然后您进行测试以查看它是Book的实例还是EmptySpace的实例。

除非EmptySpace拥有自己的某些属性,否则这不会添加任何内容,因此几乎所有人都只返回null - 实际上,null正是您的情况所需要的,并且是大多数程序员本质上直观的案例之一。

你可能希望用注释标记它 - 在这种情况下我认为它是@Nullable(这表明大多数程序员如果没有书要返回它将返回null)

答案 5 :(得分:0)

如果没有任何东西,你怎么知道什么都没有?!?!最后你必须进行测试,看看是否有东西 - 这可以在你尝试获得某些东西之前完成,也可以在你获得之后完成,然后检查你得到的东西是否是一本书。

老实说,你希望任何编程语言在这种情况下做什么?!?!

答案 6 :(得分:0)

两种不同的做法。

  1. 返回值基于:
    • 为无书而返回null
    • 检查空值
  2. 基于例外情况:
    • 当书架上没有书籍时抛出例外
    • 处理调用代码中的异常
  3. 主要使用C / C ++和Python进行编程我可以告诉您,对于没有任何可用且没有指定具体标识符的情况(例如getBookAtIndex(14)),约定是返回null,NULL,None等。抛出异常保留用于您希望存在具有严格标识符的书但不存在的情况。

答案 7 :(得分:0)

实际上,我看到了许多可行的选择,每个选项都有自己的优点/缺点。

如Edwin Buck所描述的那样,在没有书籍时返回一个哨兵对象:

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
}

在其他语言中按照Haskell实现Maybe类型包装。这种类型的对象表示“可能是Book,或者可能是Nothing”。然后,呼叫者负责检查它是否是有效的书。对于为这种类型的操作提供良好支持的语言(模式匹配等)并且不支持null(null是teh devil;),这是一个很好的解决方案。对于Java,我倾向于认为它太过分了。

至于“揭露实施”,我认为用户不知道书架可能“没有书籍”是不合理的,如果是这样的话就不可能从中获取书籍。

修改:我会添加另一个与此问题没有直接关系的备注,但值得一提。在没有书籍(以及实施hasMoreBooks)上抛出异常的好处之一是你不“总是”需要检查是否有书。

例如,如果你有一个紧密的循环遍历书籍并且有一本书FAR比没有书更频繁,你可以做如下的事情:

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

公平地说,在大多数情况下并不是那么有用......但是如果你担心必须打电话给hasMoreBooks的性能成本,而且你知道你很少有更多的书,上面可能是方便考虑。