Java中List.of()和Arrays.asList()的区别及原因分析

 更新时间:2021年09月02日 14:43:32   作者:爱唱歌的瓜皮  
这篇文章主要介绍了Java中List.of()和Arrays.asList()的区别及原因分析,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教

Java中List.of()和Arrays.asList()的区别及原因

动手写一下,让自己更有印象

1.Arrays.asList()可以插入null

而List.of()不可以

import java.util.List;
import java.util.Arrays;
class Solution {
    public static void main(String[] args) {
     List<Integer> ls1 = Arrays.asList(1, 2, null);
     //List<Integer> ls2 = List.of(1,2,null);
     System.out.println(ls1);
     //System.out.println(ls2);
    }
}
 
/*结果
[1, 2, null]
*/
import java.util.List;
import java.util.Arrays;
class Solution {
    public static void main(String[] args) {
     //List<Integer> ls1 = Arrays.asList(1, 2, null);
     List<Integer> ls2 = List.of(1,2,null);
     //System.out.println(ls1);
     System.out.println(ls2);
    }
}
 
/*结果
Exception in thread "main" java.lang.NullPointerException.....
*/

2.用List.of的List自然是不包含null

而用Arrays.asList的List包含null。上面结果也可得知。

import java.util.List;
import java.util.Arrays;
class Solution {
    public static void main(String[] args) {
     List<Integer> ls1 = Arrays.asList(1, 2, null);
     //List<Integer> ls2 = List.of(1,2);
     System.out.println(ls1.contains(null));
     //System.out.println(ls2.contains(null));
    }
}
 
/*结果
true
*/
import java.util.List;
import java.util.Arrays;
class Solution {
    public static void main(String[] args) {
     //List<Integer> ls1 = Arrays.asList(1, 2, null);
     List<Integer> ls2 = List.of(1,2);
     //System.out.println(ls1.contains(null));
     System.out.println(ls2.contains(null));
    }
}
 
/*结果
Exception in thread "main" java.lang.NullPointerException.....
*/

3.List.of生成的List不能修改

Arrays.asList生成的List能修改。

import java.util.List;
import java.util.Arrays;
class Solution {
    public static void main(String[] args) {
     List<Integer> ls1 = Arrays.asList(1, 2, null);
     //List<Integer> ls2 = List.of(1,2);
     ls1.set(0,5);
     //ls2.set(0,5);
     System.out.println(ls1);
     //System.out.println(ls2);
    }
}
 
/*结果
[5, 2, null]
*/
import java.util.List;
import java.util.Arrays;
class Solution {
    public static void main(String[] args) {
     //List<Integer> ls1 = Arrays.asList(1, 2, null);
     List<Integer> ls2 = List.of(1,2);
     //ls1.set(0,5);
     ls2.set(0,5);
     //System.out.println(ls1);
     System.out.println(ls2);
    }
}
 
/*结果
Exception in thread "main" java.lang.UnsupportedOperationExceptio.....
*/

4.关于数组修改对List的影响

数组修改对Arrays.asList生成的List有影响,对List.of 生成的List无影响

import java.util.List;
import java.util.Arrays;
class Solution {
    public static void main(String[] args) {
     Integer[] a = new Integer[]{1,2,3,4};
        // 不能用int[],会导致转型错误,错误: 不兼容的类型: 推论变量 T 具有不兼容的上限
     List<Integer> ls1 = Arrays.asList(a);
     //List<Integer> ls2 = List.of(a);
     System.out.println(ls1);
     //System.out.println(ls2);
     a[0] = 5;
     //ls2.set(0,5);
     System.out.println(ls1);
     //System.out.println(ls2);
    }
}
 
/*结果
[1, 2, 3, 4]
[5, 2, 3, 4]
*/
import java.util.List;
import java.util.Arrays;
class Solution {
    public static void main(String[] args) {
     Integer[] a = new Integer[]{1,2,3,4};
     //List<Integer> ls1 = Arrays.asList(a);
     List<Integer> ls2 = List.of(a);
     //System.out.println(ls1);
     System.out.println(ls2);
     a[0] = 5;
     //ls2.set(0,5);
     //System.out.println(ls1);
     System.out.println(ls2);
    }
}
 
/*结果
[1, 2, 3, 4]
[1, 2, 3, 4]
*/

原因

关于List.of为什么不能插入null,和修改了原数组不影响到List.of生成的List。先看看List.of有关的源码

   @SafeVarargs
    @SuppressWarnings("varargs")
    static <E> List<E> of(E... elements) {
        switch (elements.length) { // implicit null check of elements
            case 0:
                return ImmutableCollections.emptyList();
            case 1:
                return new ImmutableCollections.List12<>(elements[0]);
            case 2:
                return new ImmutableCollections.List12<>(elements[0], elements[1]);
            default:
                return new ImmutableCollections.ListN<>(elements);
        }
    }
//---------------------------------------------------------------------------------------
    @Stable
        private final E[] elements;    
 
    @SafeVarargs
        ListN(E... input) {
            // copy and check manually to avoid TOCTOU
            @SuppressWarnings("unchecked")
            E[] tmp = (E[])new Object[input.length]; // implicit nullcheck of input
            for (int i = 0; i < input.length; i++) {
                tmp[i] = Objects.requireNonNull(input[i]);
            }
            elements = tmp;
        }
 
//---------------------------------------------------------------------------------------
 
    public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
    }

可以看到Objects.requireNonNull()。所以不能插入空值。

E[] tmp = (E[])new Object[input.length];表示新建了个新的数组对象,所以修改了原数组,不影响生成的LIst底层的数组。

返回的数组是个final类型的,所以不能修改

再看看Arrays.asList源码

    @SafeVarargs
    @SuppressWarnings("varargs")
    public static <T> List<T> asList(T... a) {
        return new ArrayList<>(a);
    }
 
//----------------------------------------------------------------------------------------
 
    ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }
 
//----------------------------------------------------------------------------------------
 
    public static <T> T requireNonNull(T obj) {
        if (obj == null)
            throw new NullPointerException();
        return obj;
    }

由源码可知,底层的数组就是传入的数组,所以对原数组的修改会影响到用Arrays.asList方法生成的List。而且Objects.requireNonNull(array)检查的是整个数组是不是null,而非对每个元素进行检查是否为null。所以用Arrays.asList方法可以插入空值。

也没有规定是final的,所以支持修改。

java listof报错处理

List.of()生成不可变数组(字符串也行)

是在jdk1.8以后才出现的,在jdk1.9版本及以后才能运行。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • IDEA 2022 中的Lombok 使用基础教程

    IDEA 2022 中的Lombok 使用基础教程

    ​ Lombok是使用java编写的一款开源类库。其主作用是使用注解来代替一些具有格式固定,没有过多技术含量的编码工作,这篇文章主要介绍了IDEA 2022 中的Lombok 使用基础教程,需要的朋友可以参考下
    2022-12-12
  • Java实现调用MySQL存储过程详解

    Java实现调用MySQL存储过程详解

    相信大家都知道存储过程是在大型数据库系统中,一组为了完成特定功能的SQL语句集。存储过程是数据库中的一个重要对象,任何一个设计良好的数据库应用程序都应该用到存储过程。Java调用mysql存储过程,实现如下,有需要的朋友们可以参考借鉴,下面来一起看看吧。
    2016-11-11
  • Java使用代码模拟高并发操作的示例

    Java使用代码模拟高并发操作的示例

    本篇文章主要介绍了Java使用代码模拟高并发操作的示例,Java通过代码模拟高并发可以以最快的方式发现我们系统中潜在的线程安全性问题,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2018-05-05
  • Java微服务Filter过滤器集成Sentinel实现网关限流过程详解

    Java微服务Filter过滤器集成Sentinel实现网关限流过程详解

    这篇文章主要介绍了Java微服务Filter过滤器集成Sentinel实现网关限流过程,首先Sentinel规则的存储默认是存储在内存的,应用重启之后规则会丢失。因此我们通过配置中心Nacos保存规则,然后通过定时拉取Nacos数据来获取规则配置,可以做到动态实时的刷新规则
    2023-02-02
  • Java类初始化执行流程解析

    Java类初始化执行流程解析

    这篇文章主要介绍了Java类初始化执行流程,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-05-05
  • Java中RabbitMQ队列实现RPC详解

    Java中RabbitMQ队列实现RPC详解

    这篇文章主要介绍了Java中RabbitMQ队列实现RPC详解,在本教程中,我们将使用RabbitMQ构建一个RPC系统:一个客户端和一个RPC服务器,我们将创建一个返回斐波那契数字的模拟RPC服务,,需要的朋友可以参考下
    2023-08-08
  • Java中跳出多重循环嵌套的三种方法

    Java中跳出多重循环嵌套的三种方法

    这篇文章主要给大家介绍了关于Java中跳出多重循环嵌套的三种方法,很多复杂的运算以及逻辑可能用到嵌套循环,但是如何跳出当前的多重嵌套循环,很多同学特别是新手都操作的不是很清楚,需要的朋友可以参考下
    2023-07-07
  • 利用java实现一个客户信息管理系统

    利用java实现一个客户信息管理系统

    这篇文章主要给大家介绍了关于利用java实现一个客户信息管理系统的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-04-04
  • Java线程并发访问代码分析

    Java线程并发访问代码分析

    这篇文章主要介绍了Java线程并发访问代码分析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-11-11
  • 详解Java关于JDK中时间日期的API

    详解Java关于JDK中时间日期的API

    这篇文章主要介绍了详解Java关于JDK中时间日期的API,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-09-09

最新评论