《Effective Java》第54条:返回零长度的数组或者集合,而不是null
2023-03-31 10:56:37 时间
《Effective Java》第54条:返回零长度的数组或者集合,而不是null
一、问题
如果一个方法返回类型是list,如果结果为空的情况下返回null的情况并不少见,如下:
public class Shop_Version1 {
private final List<Cheese> cheesesInStock = new ArrayList<>();
public Shop_Version1(boolean initFlag) {
if (initFlag) {
cheesesInStock.add(Cheese.STILION);
}
}
/**
* @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);
}
}
这样做有一个坏处:调用这个方法的地方必须来处理null返回值,这样很容易出错。
有的认为这样做的好处是:这样做避免了分配零长度的容器所需要的开销。这种说法是站不住脚的,第一,在这个级别上是没有必要担心性能的。第二,不需要分配零长度的集合或者数组,也可以返回它们,如下:
public class Shop_Version2 {
private final List<Cheese> cheesesInStock = new ArrayList<>();
public Shop_Version2(boolean initFlag) {
if (initFlag) {
cheesesInStock.add(Cheese.STILION);
}
}
/**
* @return a list containing all of the cheeses in the shop,
* or empty list if no cheeses are available for purchase.
*/
public List<Cheese> getCheeses() {
return new ArrayList<>(cheesesInStock);
}
}
二、分析
2.1 返回集合情况优化
如果真的分配零长度的集合损害了程序的性能,可以通过重复返回一个不可变的零长度集合,避免了分配的执行,因为不可变对象可以被自由共享。如果返回的是集合,可以使用Collections.emptySet()或Collections.emptyList();如果返回的是映射,可以使用Collections.emptyMap()。这是一个优化,但是几乎用不上,如下:
public class Shop_Version3 {
private final List<Cheese> cheesesInStock = new ArrayList<>();
public Shop_Version3(boolean initFlag) {
if (initFlag) {
cheesesInStock.add(Cheese.STILION);
}
}
/**
* @return a list containing all of the cheeses in the shop,
* or empty list if no cheeses are available for purchase.
*/
public List<Cheese> getCheeses() {
return cheesesInStock.isEmpty() ? Collections.emptyList()
: new ArrayList<>(cheesesInStock);
}
}
2.2 返回数组情况
返回数组与返回集合的情形一样,它永远不会返回null,而是返回零长度的数组。
public class Shop_RetArray_Version1 {
private final List<Cheese> cheesesInStock = new ArrayList<>();
public Shop_RetArray_Version1(boolean initFlag) {
if (initFlag) {
cheesesInStock.add(Cheese.STILION);
}
}
/**
* @return a array containing all of the cheeses in the shop,
* or empty array if no cheeses are available for purchase.
*/
public Cheese[] getCheeses() {
return cheesesInStock.toArray(new Cheese[0]);
}
}
千万不要通过预先分配传入toArray的数组来提升性能,这样只会适得其反,如下:
public class Shop_RetArray_Version2 {
private final List<Cheese> cheesesInStock = new ArrayList<>();
public Shop_RetArray_Version2(boolean initFlag) {
if (initFlag) {
cheesesInStock.add(Cheese.STILION);
}
}
/**
* @return a array containing all of the cheeses in the shop,
* or empty array if no cheeses are available for purchase.
*/
public Cheese[] getCheeses() {
return cheesesInStock.toArray(new Cheese[cheesesInStock.size()]);
}
}
2.3 返回数组情况优化
如果分配零长度的数组会伤害性能,可以重复返回同一个零长度的数组,因为所有零长度的数组都是不可变的,如下:
public class Shop_RetArray_Version3 {
private final List<Cheese> cheesesInStock = new ArrayList<>();
private static final Cheese[] EMPTY_CHEESE_ARRAY = new Cheese[0];
public Shop_RetArray_Version3(boolean initFlag) {
if (initFlag) {
cheesesInStock.add(Cheese.STILION);
}
}
/**
* @return a array containing all of the cheeses in the shop,
* or empty array if no cheeses are available for purchase.
*/
public Cheese[] getCheeses() {
return cheesesInStock.toArray(EMPTY_CHEESE_ARRAY);
}
}
三、总结
简而言之,永远不要返回null,而是返回一个零长度的数组或集合。如果返回null,那样会使API更难以使用,也列容易出错,而且没有任何性能优势。
相关文章
- 没人陪你聊天?教你使用java制作专属智能陪聊机器人
- Java Review - 并发编程_Unsafe
- Java的Integer和Integer比较相等
- Java进阶:【集合】HashMap原理简单理解
- 《深入理解Java虚拟机》读书笔记(七)–虚拟机字节码执行引擎(下)
- Java进阶:【集合】Map接口
- Java进阶:【集合】set接口
- 《深入理解Java虚拟机》读书笔记(七)–虚拟机字节码执行引擎(上)
- Java进阶:【集合】迭代器原理
- Java进阶:【集合】linkedlist的原理,手写linkedlist,源码阅读
- 《深入理解Java虚拟机》读书笔记(六)–虚拟机类加载机制(下)
- Java进阶:【泛型】认识泛型,泛型方法,泛型类,泛型接口和通配符
- Java进阶:【集合】1.8 jdk Arraylist和Vector集合源码分析
- Java进阶:【集合】认识集合相关的数据结构
- 《深入理解Java虚拟机》读书笔记(四)–虚拟机性能监控与故障处理工具
- Java进阶:【集合】认识集合了解简单语法 迭代器原理分析
- 《深入理解Java虚拟机》读书笔记(五)–类文件结构
- 《深入理解Java虚拟机》读书笔记(六)–虚拟机类加载机制(上)
- Java进阶:循环进阶经典练习题
- Java设计模式之(八)——适配器模式