Arrays.asList()返回的List仅仅是一个视图

52 阅读3分钟

/**
 *
 * 1. wrong1() 方法:
 *
 *   - 创建了一个int数组arr并使用Arrays.asList()转换成List
 *
 *   - 但是因为arr是原始类型int数组,所以返回的List中包含的也是int类型,不是Integer类型
 *
 *   - 可以从getClass()看出,list中的元素是int类似,而不是Integer类型
 *
 *   - 这会带来自动装箱/拆箱的问题,不便于使用
 *
 * 2. right1() 方法:
 *
 *   - 两种方式处理了int数组的问题:
 *
 *     1) 使用boxed()先装箱为Stream<Integer>,再收集到List中
 *
 *     2) 创建包装类型Integer数组,然后Arrays.asList()返回正常Generic List<Integer>
 *
 *   - 这样List中的元素就是Integer类型了,可以自动装箱拆箱
 *
 * 3. wrong2() 方法:
 *
 *   - 创建String数组并用Arrays.asList()转换成List
 *
 *   - 但是返回的List大小是固定的,不能添加元素
 *
 *   - 当试图修改List时会抛UnsupportedOperationException
 *
 * 4. right2() 方法:
 *
 *   - 用Arrays.asList()把数组转换成一个中间List
 *
 *   - 然后传递给ArrayList构造函数,生成一个新的List
 *
 *   - 这个List就可以自由修改了
 *
 *   - 添加元素成功
 *
 * 总结:
 *
 * - Arrays.asList()返回一个数组的只读视图List, 而不是一个独立拷贝
 *
 * - 需要处理原始类型数组的装箱问题
 *
 * - 如果需要可修改List,需要配合新建ArrayList使用
 */
@Slf4j
public class AsListApplication {

    public static void main(String[] args) {

        wrong1();
        right1();
        //wrong2();// Arrays.asList()返回的List仅仅是一个视图
        right2();
        System.out.println("--------------------------");
        logger();

    }
    private static void wrong1() {
        log.error("---wrong1---");
        //创建了一个int数组arr并使用Arrays.asList()转换成List
        //但是因为arr是原始类型int数组,所以返回的List中包含的也是int类型,不是Integer类型
        int[] arr = {1, 2, 3};
        List list = Arrays.asList(arr);

        //可以从getClass()看出,list中的元素是int类似,而不是Integer类型
        //这会带来自动装箱/拆箱的问题,不便于使用
        log.info("list:{} size:{} class:{}", list, list.size(), list.get(0).getClass());
    }

    private static void right1() {
        log.error("---right1---");
        //使用boxed()先装箱为Stream<Integer>,再收集到List中
        int[] arr1 = {1, 2, 3};
        List list1 = Arrays.stream(arr1).boxed().collect(Collectors.toList());
        log.info("list:{} size:{} class:{}", list1, list1.size(), list1.get(0).getClass());

        //创建包装类型Integer数组,然后Arrays.asList()返回正常Generic List<Integer>
        Integer[] arr2 = {1, 2, 3};
        List list2 = Arrays.asList(arr2);
        log.info("list:{} size:{} class:{}", list2, list2.size(), list2.get(0).getClass());
    }


    private static void wrong2() {
        log.error("---wrong2---");
        //创建String数组并用Arrays.asList()转换成List
        //但是返回的List大小是固定的,不能添加元素
        //当试图修改List时会抛UnsupportedOperationException
        String[] arr = {"1", "2", "3"};
        List list = Arrays.asList(arr);
        arr[1] = "4"; //2变更成了4
        try {
            //rrays.asList返回的List大小是固定的,不能添加元素
            // Arrays.asList()返回的List仅仅是一个视图
            list.add("5");
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        log.info("arr:{} list:{}", Arrays.toString(arr), list);
    }

    private static void right2() {
        log.error("---right2---");
        log.debug("---right2---");

        String[] arr = {"1", "2", "3"};
        List list = new ArrayList(Arrays.asList(arr));
        arr[1] = "4";
        try {
            list.add("5");
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        log.info("arr:{} list:{}", Arrays.toString(arr), list);

        //Arrays.toString() - 字符串表示
        //Arrays.asList() - List视图
    }
    private static void logger() {
        log.trace("trace log");
        log.debug("debug log");
        log.info("info log");
        log.warn("warn log");
        log.error("error log");
        /**
         * @Slf4j包含了几个不同级别的日志输出方法:
         *
         * trace - 最详细的日志输出
         * debug - 调试相关的日志信息
         * info - 一般重要的运行信息
         * warn - 潜在的问题提示
         * error - 错误信息但不会导致程序停止
         * 日志级别从trace到error等级逐渐升高。
         *
         * 默认情况下,Spring Boot会设置info级别的日志输出。
         */
    }
}

学习:Java 业务开发常见错误 100 例学习笔记