多平台统一管理软件接口,如何实现多平台统一管理软件接口
754
2022-09-14
Java Collections的emptyList、EMPTY_LIST详解与使用说明
目录Collections的emptyList、EMPTY_LIST使用Collections.emptyList()使用注意
Collections的emptyList、EMPTY_LIST使用
今天在看大佬写的代码的时候,结果集为空的情况,他返回的不是null,而是:
return Collections.EMPTY_LIST;
我们都知道返回null,很有可能造成空指针异常,可以使用emptyList或EMPTY_LIST就可以避免这个问题,除非你想捕获这个为空的信息
我们在使用emptyList空的方法返回空集合的时候要注意,这个空集合是不可变的。
空的集合不可以使用add方法,会报UnsupportedOperationException异常,看如下源码:
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
空集合对象不可以使用put方法,会报IndexOutOfBoundsException异常,看如下源码:
public E get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}
但是对于for循环都不会发生异常,如下的示例:
List
for(String s:list1) {
}
for(int i=0;i } 上面的两种for循环都可以正常的执行,第一种foreach循环,实际编译之后会变成迭代器的模式,这样我们就好理解为什么可以正常执行;第二种是只调用了size方法,我们可以看到源码直接返回0; public int size() {return 0;} emptyList和EMPTY_LIST的区别,我们看下源码: /** * The empty list (immutable). This list is serializable. * * @see #emptyList() */ @SuppressWarnings("unchecked") public static final List EMPTY_LIST = new EmptyList<>(); /** * Returns the empty list (immutable). This list is serializable. * * This example illustrates the type-safe way to obtain an empty list: *
}
上面的两种for循环都可以正常的执行,第一种foreach循环,实际编译之后会变成迭代器的模式,这样我们就好理解为什么可以正常执行;第二种是只调用了size方法,我们可以看到源码直接返回0;
public int size() {return 0;}
emptyList和EMPTY_LIST的区别,我们看下源码:
/**
* The empty list (immutable). This list is serializable.
*
* @see #emptyList()
*/
@SuppressWarnings("unchecked")
public static final List EMPTY_LIST = new EmptyList<>();
/**
* Returns the empty list (immutable). This list is serializable.
*
*
This example illustrates the type-safe way to obtain an empty list:
*
* List<String> s = Collections.emptyList();
*
* Implementation note: Implementations of this method need not
* create a separate List object for each call. Using this
* method is likely to have comparable cost to using the like-named
* field. (Unlike this method, the field does not provide type safety.)
*
* @see #EMPTY_LIST
* @since 1.5
*/
@SuppressWarnings("unchecked")
public static final
return (List
}
我们看到EMPTY_LIST 是Collections类的一个静态常量,而emptyList是支持泛型的。若是不需要泛型的地方可以直接使用 EMPTY_LIST ,若是需要泛型的地方就需要使用emptyList。
通过上面的分析我们可以很清楚的知道什么时候使用emptyList;Collections集合中还有其它的几种空集合emptyMap、emptySet,他们的使用方法跟上面的大同小异。
Collections.emptyList()使用注意
偶然发现有小伙伴错误地使用了Collections.emptyList()方法,这里记录一下。它的使用方式是:
public void run() {
......
List list = buildList(param);
......
Object newNode = getNode(...);
list.add(newNode);
......
}
public List buildList(Object param) {
if (isInValid(param)) {
return Collections.emptyList();
} else {
......
}
}
buildList方法中可能会返回一个"空的List",后续还可能往这个List添加元素(或者移除元素),但是没有注意Collections.emptyList方法返回的是一个EMPTY_LIST:
public static final
return (List
}
它是一个static final修饰的成员变量,是一个EmptyList类的实例:
public static final List EMPTY_LIST = new EmptyList<>();
这个EmptyList是一个静态内部类,和ArrayList一样继承自AbstractList:
private static class EmptyList
extends AbstractList
implements RandomAccess, Serializable {
private static final long serialVersionUID = 8842843931221139166L;
public Iterator
return emptyIterator();
}
public ListIterator
return emptyListIterator();
}
public int size() {return 0;}
public boolean isEmpty() {return true;}
public boolean contains(Object obj) {return false;}
public boolean containsAll(Collection> c) { return c.isEmpty(); }
public Object[] toArray() { return new Object[0]; }
public
if (a.length > 0)
a[0] = null;
return a;
}
public E get(int index) {
throw new IndexOutOfBoundsException("Index: "+index);
}
public boolean equals(Object o) {
return (o instanceof List) && ((List>)o).isEmpty();
}
public int hashCode() { return 1; }
// Preserves singleton property
private Object readResolve() {
return EMPTY_LIST;
}
}
可以看到这个EmptList没有重写add方法,并且get方法也是直接抛出一个IndexOutOfBoundsException异常。既然没有重写add方法,那么看看父类AbstractList中的add方法:
public boolean add(E e) {
add(size(), e);
return true;
}
public void add(int index, E element) {
throw new UnsupportedOperationException();
}
可以看到直接抛出的UnsupportedOperationException异常。再回到EmptyList类中,它对外提供的一些方法也很明显地限制了它的使用范围。
对于Collections.emptyList(),或者说Collections.EMPTY_LIST,最好只把它当做一个空列表的标识(可以想象成一个frozen过的空List),不要对其做一些增删改查的操作。如果程序中的一些分支逻辑返回了这种实例,测试的时候又没有覆盖到,在生产环境如果走到了这个分支逻辑,那就麻烦了~
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~