Tips

书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code

注意,书中的有些代码里方法是基于Java 9 API中的,所以JDK 最好下载 JDK 9以上的版本。

54. 返回空的数组或集合不要返回null

看到类似这样的方法并不罕见:

// 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)可供购买的情况进行特殊处理。这样需要在客户端做额外的代码处理可能为null的返回值,例如:

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

在几乎每次使用返回null来代替空集合或数组的方法时,都需要使用这种迂回的方式。 它容易出错,因为编写客户端的程序员可能忘记编写特殊情况代码来处理null返回。 多年来这种错误可能会被忽视,因为这种方法通常会返回一个或多个对象。 此外,返回null代替空容器会使返回容器的方法的实现变得复杂。

有时有人认为,null返回值比空集合或数组更可取,因为它避免了分配空容器的开销。这个论点有两点是不成立的。首先,除非测量结果表明所讨论的分配是性能问题的真正原因,否则不宜担心此级别的性能(条目67)。第二,可以在不分配空集合和数组的情况下返回它们。下面是返回可能为空的集合的典型代码。通常,这就是你所需要的:

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

如果有证据表明分配空集合会损害性能,可以通过重复返回相同的不可变空集合来避免分配,因为不可变对象可以自由共享(条目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的数组。研究表明,这样做会适得其反[Shipilev16]:

// Don’t do this - preallocating the array harms performance!

return cheesesInStock.toArray(new Cheese[cheesesInStock.size()]);

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

Effective Java 第三版——54. 返回空的数组或集合不要返回null的更多相关文章

  1. 《Effective Java 第三版》目录汇总

    经过反复不断的拖延和坚持,所有条目已经翻译完成,供大家分享学习.时间有限,个别地方翻译得比较仓促,希望有疑虑的地方指出批评改正. 第一章简介 忽略 第二章 创建和销毁对象 1. 考虑使用静态工厂方法替 ...

  2. 《Effective Java 第三版》新条目介绍

    版权声明:本文为博主原创文章,可以随意转载,不过请加上原文链接. https://blog.csdn.net/u014717036/article/details/80588806前言 从去年的3月份 ...

  3. Effective Java 第三版——47. 优先使用Collection而不是Stream来作为方法的返回类型

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  4. Effective Java 第三版——55. 明智而审慎地返回Optional

    Tips 书中的源代码地址:https://github.com/jbloch/effective-java-3e-source-code 注意,书中的有些代码里方法是基于Java 9 API中的,所 ...

  5. Effective Java 第三版——10. 重写equals方法时遵守通用约定

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  6. Effective Java 第三版——11. 重写equals方法时同时也要重写hashcode方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  7. Effective Java 第三版——14.考虑实现Comparable接口

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  8. Effective Java 第三版——30. 优先使用泛型方法

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

  9. Effective Java 第三版——34. 使用枚举类型替代整型常量

    Tips <Effective Java, Third Edition>一书英文版已经出版,这本书的第二版想必很多人都读过,号称Java四大名著之一,不过第二版2009年出版,到现在已经将 ...

随机推荐

  1. 【莫比乌斯反演】HDU1695_GCD

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1695 第一道莫比乌斯反演 感觉很巧妙的就是利用了F(x)=(n/x)*(m/x) 之后的那个去重也挺不 ...

  2. 类 __new__方法实现单例

    继承了单例的类,子类也是单例模式

  3. Shell学习之Shell特性(一)

    Shell学习之Shell特性 目录 命令和文件自动补齐功能 命令历史记忆功能 history.上下键.!number.!string.!$.!! 别名功能 alias.unalias cp.~use ...

  4. Nmap的详细使用

    Nmap的详细使用 介绍常用参数选项主机发现端口扫描服务和版本探测操作系统探测性能优化防火墙/IDS 躲避和哄骗输出 (一)介绍 Nmap — 网络探测工具和安全/端口扫描器. Nmap (“Netw ...

  5. LVN与其在Linux上的实现

    参考资料: LVM详解-骏马金龙-博客园 How to reduce the size of an LVM partition formatted with xfs filesystem on Cen ...

  6. loj#2016. 「SCOI2016」美味

    题目链接 loj#2016. 「SCOI2016」美味 题解 对于不带x的怎么做....可持久化trie树 对于带x,和trie树一样贪心 对于答案的二进制位,从高往低位贪心, 二进制可以表示所有的数 ...

  7. 牛客国庆集训派对Day4 Solution

    A    深度学习 puts(n) #include <bits/stdc++.h> using namespace std; int main() { double n; while ( ...

  8. URL中可以出现的字符

    http://blog.csdn.net/hejisan/article/details/51786969

  9. 移动端tap与click的区别 && 点透事件

    移动端的问题 移动端的主要问题是click会有300ms的延迟,主要原因是苹果手机在设计时,考虑到用户在浏览网页时需要放大,所以,在用户点击的300ms之后,才触发click,如果300ms之内还有c ...

  10. Xshell 连接 CentOS 7 与 Ubuntu Server

    操作系统:windows 7 应用软件:Ware Workstation & Xshell 5 Linux:CentOS 7 Minimal & Ubuntu Server 16 == ...