先说明一下好处有哪些:
1、如果你想 new 一个空的 List ,且 这个 List 以后也不会再添加元素(有大坑,看下面更新)
那么就用 Collections.emptyList() 好了。
new ArrayList() 或者 new LinkedList() 在创建的时候有会有初始大小,多少会占用一内存。
每次使用都new 一个空的list集合,浪费就积少成多,浪费就严重啦,就不好啦
2、为了编码的方便
比如说一个方法返回类型是List,当没有任何结果的时候,返回null,有结果的时候,返回list集合列表。
那样的话,调用这个方法的地方,就需要进行null判断。使用emptyList这样的方法,可以方便方法调用者。返回的就不会是null,省去重复代码。
但是,需要注意的地方:
这个空的集合是不能调用.add(),添加元素的。因为直接报异常。因为源码就是这么写的:直接抛异常。
哦,Collections里面没这么写,但是EmptyList继承了AbstractList这个抽象类,里面简单实现了部分集合框架的方法。
这里面的add方法最后调用的方法体,就是直接抛异常。
throw new UnsupportedOperationException();
这么解释add报异常就对啦。
下面简单看下这个源码:
/** * Collections 类里面的方法如下,一步步往下看就是啦 */ public static final <T> List<T> emptyList() { return (List<T>) EMPTY_LIST; } //。。。。。 /** * Collections 类里面的方法如下,一步步往下看就是啦 */ public static final List EMPTY_LIST = new EmptyList<>(); //。。。。。 /** * Collections里面的一个静态内部类 */ private static class EmptyList<E> extends AbstractList<E> implements RandomAccess, Serializable { private static final long serialVersionUID = 8842843931221139166L; public Iterator<E> iterator() { return emptyIterator(); } public ListIterator<E> 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 <T> T[] toArray(T[] a) { 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; } }
除了这个emptyList,之外,还有类似的,emptyMap,emptySet等等。具体看下图,都是一个套路。
看下面的代码,咱先弄个empty出来,然后,可能有需求要继续在这个空集合里面添加内容。那么,bug就来啦。
/** * 测试这个空集合是某个Java bean 的某个属性的时候的操作,也是不能add的 */ private static void testModelEmptyField() { Car car = new Car(); car.setBoys(Collections.emptyList()); car.getBoys().add("sss"); } /** * Collections.emptyMap() 返回的空集合是不能进行put的 */ private static void testEmptyMap() { Map<String,String> map = Collections.emptyMap(); for (Map.Entry<String, String> entry : map.entrySet()) { System.out.println(entry.getKey() + ":"+ entry.getValue()); } map.put("a","a"); for (Map.Entry<String, String> entry : map.entrySet()) { System.out.println(entry.getKey() + ":"+ entry.getValue()); } } /** * Collections.emptyList() 返回的空集合是不能进行add的 */ private static void testEmptyList() { List<String> list = Collections.emptyList(); for (String s : list) { System.out.println(s); } //异常 list.add("1"); for (String s : list) { System.out.println(s); } }
具体出的bug,看下面的截图。
阿弥陀佛,算了 ,这个咱还是不用了吧。
很危险的,分分钟代码就bug啦。这个不好,不好。。。不用啦,了解下就得啦。
为什么不推荐使用:
因为这个是返回了个默认集合,这个集合不是null了,其他人在使用你这个返回值的时候,省去了判断null这一步。
假设,这有个接盘的老铁,一看,哎这个方法始终都是返回一个集合的,那么万一需求变了,要是空集合的时候,给这个空集合添加个默认值,或者怎么滴,反正,就是有进一步的操作,要往这个返回的集合里面添加东西。那么,在这个接盘的老铁写代码的阶段,这个代码是不会报错的。代码看上去一切OK,但是,一旦,项目运行,这个代码运行了,就会出现我最后一个图的,异常了。要是这个老铁是个新人或者说不了解,你这个“高级装逼”操作的返回集合有这个问题的话,打死他,他也不知道,他这个异常问题,出在哪里。
摘自:Java之Collections.emptyList()、emptySet()、emptyMap()的作用和好处以及要注意的地方
自己创建一个工具类
package com.wanma.framework_web.helper; import java.util.*; /** * 空实例 助手类 */ public class EmptyHelper { /** * 返回空的ArrayList实例 */ public static <T> ArrayList<T> emptyArrayList() { return new ArrayList<>(); } /** * 返回空的LinkedList实例 */ public static <T> LinkedList<T> emptyLinkedList() { return new LinkedList<>(); } /** * 返回空的HashSet实例 */ public static <T> HashSet<T> emptyHashSet() { return new HashSet<>(); } /** * 返回空的LinkedHashSet实例 */ public static <T> LinkedHashSet<T> emptyLinkedHashSet() { return new LinkedHashSet<>(); } /** * 返回空的HashMap实例 */ public static <K, V> HashMap<K, V> emptyHashMap() { return new HashMap<>(); } /** * 返回空的LinkedHashMap实例 */ public static <K, V> LinkedHashMap<K, V> emptyLinkedHashMap() { return new LinkedHashMap<>(); } }
使用示例:
/** * 获取角色的模块Ids */ @Override public List<Integer> getRoleModuleIds(int roleId) { if (roleId <= 0) { return EmptyHelper.emptyArrayList(); } // ...... }