美文网首页
ITEM 54: 返回空集合/数组,而不是null

ITEM 54: 返回空集合/数组,而不是null

作者: rabbittttt | 来源:发表于2019-12-14 15:44 被阅读0次

    ITEM 54: RETURN EMPTY COLLECTIONS OR ARRAYS, NOT NULLS
      常见的方法是这样的:

    // Returns null to indicate an empty collection. Don't do this!
    private final List<Cheese> cheesesInStock = ...;
    /**
    * @return a list containing all of the cheeses in the shop, 
    * or null if no cheeses are available for purchase.
    */
    public List<Cheese> getCheeses() { 
      return cheesesInStock.isEmpty() ? null : new ArrayList<>(cheesesInStock); 
    }
    

      没有理由对没有 Cheese 可供购买的情况进行特殊处理。这样做需要额外的代码在客户端处理可能的空返回值,例如:

    List<Cheese> cheeses = shop.getCheeses();
    if (cheeses != null && cheeses.contains(Cheese.STILTON))
      System.out.println("Jolly good, just the thing.");
    

      在几乎每次使用返回 null 来代替空集合或数组的方法时,都需要使用这种绕圈子的方法。它很容易出错,因为编写客户机的程序员可能忘记编写处理 null 返回的特殊情况代码。这样的错误可能会被忽略多年,因为这样的方法通常返回一个或多个对象。此外,在空容器中返回 null 会使返回容器的方法的实现复杂化。
      有人认为,空返回值比空集合或数组更可取,因为它避免了分配空容器的开销。这个论点有两点是站不住脚的。
      首先,在这个级别上担心性能是不明智的,除非度量结果表明有问题的分配确实会导致性能问题(item 67)。其次,可以返回空的集合和数组而不分配它们。下面是返回可能为空的集合的典型代码。通常,这就是你所需要的:

    //The right way to return a possibly empty collection
    public List<Cheese> getCheeses() {
      return new ArrayList<>(cheesesInStock);
    }
    

      在不太可能的情况下,有证据表明分配空集合会损害性能,您可以通过重复返回相同的不可变空集合来避免分配,因为不可变对象可以自由共享(item 17)。下面是使用 Collections.emptyList() 完成此任务的方法。如果你返回一个 Set,你应当 使用 Collections.emptySet() ; 如果你要返回一个 Map ,你会使用Collections.emptyMap() 。但是请记住,这是一个优化,很少需要它。如果你认为你需要它,衡量前后的表现,以确保它确实有帮助:

    // Optimization - avoids allocating empty collections
    public List<Cheese> getCheeses() {
      return cheesesInStock.isEmpty() ? Collections.emptyList() : new ArrayList<>(cheesesInStock); 
    }
    

      数组的情况与集合的情况相同。不要返回 null,而要返回零长度的数组。通常,您应该简单地返回一个长度正确的数组,它可能是零。注意,我们将一个零长度的数组传递到toArray方法中,以指示所需的返回类型,即 Cheese[]:

    //The right way to return a possibly empty array
    public Cheese[] getCheeses() {
      return cheesesInStock.toArray(new Cheese[0]);
    }
    

      如果你认为分配零长度数组会损害性能,你可以重复返回相同的零长度数组,因为所有的零长度数组都是不可变的:

    // Optimization - avoids allocating empty arrays
    private static final Cheese[] EMPTY_CHEESE_ARRAY = new Cheese[0];
    public Cheese[] getCheeses() {
      return cheesesInStock.toArray(EMPTY_CHEESE_ARRAY);
    }
    

      在优化的版本中,我们将相同的空数组传递到每个toArray调用中,当cheesesInStock 为空时,这个数组将从 getCheeses 返回。
      不要为了提高性能而预先分配传递给 toArray 的数组。研究表明,它是适得其反(Shipilëv16):

    // Don’t do this - preallocating the array harms performance!
    return cheesesInStock.toArray(new Cheese[cheesesInStock.size()]);
    

      总之,永远不要用null来代替空数组或集合。它使您的API更难于使用,更容易出错,并且没有性能优势。

    相关文章

      网友评论

          本文标题:ITEM 54: 返回空集合/数组,而不是null

          本文链接:https://www.haomeiwen.com/subject/cjncnctx.html