关于“Return empty arrays or collections, not nulls”的思考

在Java编程中,为了提高代码健壮性和可维护性,《Effective Java》建议在需要返回数组或集合的方法中,即便没有数据也应返回空数组或空集合而非null。本文详细解释了这一做法的理由,并提供了具体的实现示例。

《effective java》第二版第43条是:Return empty arrays or collections, not nulls

意思是在需要返回数组或者集合的方法中,如果需要返回空数据,不要返回null,而是要返回大小为0的数组或者集合。

可能很多情况下,会出现这样的代码:

复制代码
 1 private final List<Cheese> cheesesInStock = ...;
2 /**
3 * @return an array containing all of the cheeses in the shop,
4 * or null if no cheeses are available for purchase.
5 */
6 public Cheese[] getCheeses() {
7   if (cheesesInStock.size() == 0)
8     return null;
9   ...
10 }
复制代码

当没有数据时,直接返回null。

但是,采用此种方式,会出现一个问题,就是调用这个代码的client必须要判断这个方法返回的是否为null,否则,可能会抛出NullPointerException异常。

比如:

代码1:

1 Cheese[] cheeses = shop.getCheeses();
2 if (cheeses != null &&
3 Arrays.asList(cheeses).contains(Cheese.STILTON))
4   System.out.println("Jolly good, just the thing.");

每一次调用都要加上是否为null的判断,而且很容易忘记检查导致抛出异常。

有人坚持选择返回null的原因是因为,他们认为分配一个空数组或者集合是需要花费时间和空间的,会影响性能。而作者则认为:

1)这点性能损耗微不足道;

2)返回的空数组或者集合通常是immutable,即不可变的。所以可定义成static final(对于数组)或者Collections.emptyList()/emptyMap()/emptySet()来公用同一个对象,减少性能影响。

代码2:

复制代码
1 // The right way to return an array from a collection
2 private final List<Cheese> cheesesInStock = ...;
3 private static final Cheese[] EMPTY_CHEESE_ARRAY = new Cheese[0];
4 /**
5 * @return an array containing all of the cheeses in the shop.
6 */
7 public Cheese[] getCheeses() {
8   return cheesesInStock.toArray(EMPTY_CHEESE_ARRAY);
9 }

复制代码

代码3:

复制代码
1 // The right way to return a copy of a collection
2 public List<Cheese> getCheeseList() {
3   if (cheesesInStock.isEmpty())
4     return Collections.emptyList(); // Always returns same list
5   else
6     return new ArrayList<Cheese>(cheesesInStock);
7 }
复制代码

几点思考:

1)自己写接口方法时尽量遵守这条规范,并在方法注释中标明。返回大小为0的数组或者集合。

2)文中提到的Collections.emptyList()/emptyMap()/emptySet()这个需要慎用。因为这几个方法返回的集合对象都是immutable的,即不可更改的。而有时候我们可能需要向返回的集合中添加或者删除元素,这样的话,就会报UnsupportedOperationException异常。

3)tips:

  a) 当要判断某个元素是否在数组中时,可以Arrays.asList(T[] array).contains(T obj))来实现,而无需用循环迭代每个元素来判断。

  b) 如代码2所示,如果要把ArrayList变成数组,可以使用ArrayList.toArray(T [] array),里面的array只需设成大小为0的数组即可,仅用来指定返回的类型,T可能为ArrayList中元素的子类。


举个例子:

Colllections.emptyMap()只能获取get元素,但是不能添加add元素。

package com.yxq.spring2.di; import java.util.Arrays; public class Emp { private String empName; private Integer age; private Dept dept; private String[] loves; public void work() { System.out.println(empName+"-work-age:"+age); dept.info(); System.out.println(Arrays.toString(loves)); } public String getEmpName() { return empName; } public void setEmpName(String empName) { this.empName = empName; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } public Dept getDept() { return dept; } public void setDept(Dept dept) { this.dept = dept; } public String[] getLoves() { return loves; } public void setLoves(String[] loves) { this.loves = loves; } @Override public String toString() { return "Emp{" + "empName='" + empName + '\'' + ", age=" + age + ", dept=" + dept + ", loves=" + Arrays.toString(loves) + '}'; } } package com.yxq.spring2.di; import java.util.List; public class Dept { private String deptName; private List<Emp> empList; public void info() { System.out.println("deptName:" + deptName); for (Emp emp : empList) { System.out.println(emp); } } public String getDeptName() { return deptName; } public void setDeptName(String deptName) { this.deptName = deptName; } public List<Emp> getEmpList() { return empList; } public void setEmpList(List<Emp> empList) { this.empList = empList; } @Override public String toString() { return "Dept{" + "deptName='" + deptName + '\'' + ", empList=" + empList + '}'; } } 这两个类我调用 for (Emp emp : empList) { System.out.println(emp); }报错应该怎么解决
最新发布
08-03
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值