在编码中,经常使用到各种集合常量,比如List(列表)常量、Set(集合)常量、Map(映射)常量等。
普通方式一般这样写:
- public static final List<Integer> CONST_VALUE_LIST = Arrays.asList(1,2,3);
-
- public static final Set<Integer> CONST_VALUE_SET = new HashSet<>(Arrays.asList(1,2,3));
-
- public static final Map<Integer,String> CONST_VALUES_MAP;
-
- static {
- CONST_VALUES_MAP = new HashMap<>();
- CONST_VALUES_MAP.put(1,"a");
- CONST_VALUES_MAP.put(2,"b");
- }
问题:
由于普通的集合对象(如ArrayList、HashMap、HashSet等)都是可变集合对象,即便是定义为静态常量,
也可以通过操作方法进行修改。所以,上面方法定义的集合常量,并不是真正意义上的集合常量。
其中,Arrays.asList方法生成的内部ArrayList不能执行add/remove/clear方法,但是可以执行set方法,也属于可变集合对象。
注:
博客:
霸道流氓气质的博客_CSDN博客-C#,架构之路,SpringBoot领域博主
最佳方式使用如下
在JDK中,Collections工具类中提供一套方法,用于把可变集合对象变为不可变
(不可修改,修改时会抛出UnsupportedOperationException异常)集合对象。所以,可以利用这套方法定义集合静态常量。
- public static final List<Integer> CONST_VALUE_LIST_2 = Collections.unmodifiableList(Arrays.asList(1,2,3));
-
- public static final Set<Integer> CONST_VALUE_SET_2 = Collections.unmodifiableSet(new HashSet<>(Arrays.asList(1,2,3)));
-
- public static final Map<Integer,String> CONST_VALUE_MAP_2;
-
- static {
- CONST_VALUE_MAP_2 = Collections.unmodifiableMap(new HashMap<Integer,String>(){{
- put(1,"a");
- put(2,"b");
- }});
- }
一般定义数组常量,会像下面代码一样,定义一个公有数组常量
public static final int[] CONST_ARRAY = new int[]{1,2,3};
但是,可以通过下标修改数组值,导致数组常量的值可变。所以,这种方法定义的数组常量,并不是一个真正意义上的数组常量。
最佳法“私有数组常量+公有克隆方法”的解决方案。
如下代码所示:先定义一个私有数组常量,保证不会被外部类使用;在定义一个获取数组常量方法,并返回一个数组常量的克隆值。
- private static final int[] CONST_ARRAY_2 = new int[]{1,2,3};
-
- public static int[] getConstArray2(){
- return CONST_ARRAY_2.clone();
- }
由于每次返回的是一个克隆数组,即便修改了克隆数组的常量值,也不会导致原始数组常量值的修改。