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

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更难于使用,更容易出错,并且没有性能优势。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,951评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,606评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,601评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,478评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,565评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,587评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,590评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,337评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,785评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,096评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,273评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,935评论 5 339
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,578评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,199评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,440评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,163评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,133评论 2 352

推荐阅读更多精彩内容