关于Arrays类中asList(T... a)泛型参数辨析

news2024/12/23 16:43:45

前提

我们需要知道两点

(1)T指的是泛型类型,它只能是引用类型,何为引用类型?在java中除了基本数据类型(如byte、short、int、long、float、double、boolean、char)之外的所有类型都是引用类型。引用类型包括类(class)、接口(interface)、数组(array)等

 (2)我们asList返回值是一个List<T>类型,也就是说我们传递什么T最后返回的List中元素类型就是什么T类型,比如我们传递一个Integer 那么List中元素就是Integer,我们传递一个int [] 那么我们list中元素就是int[],有的同志就要问了,为什么传递过去的事int [] 泛型T不会识别为int ,刚才我们说了泛型只能是引用类型,但是我们int是基本类型,不会识别为引用类型,所以我们参数接收的时候直接就将int [] 识别成了引用类型,所以我们返回的结果List<int[]>就是这种类型的。

实验

  public static void main(String[] args) {

        int[] a = {2,3,4,5};
        Integer[] b = {2,3,4,5};

        List listA = Arrays.asList(a);
        List listA1 = Arrays.asList(2,3,4,5);
        List listB = Arrays.asList(b);

        System.out.println(listA.size());
        System.out.println(listA1.size());
        System.out.println(listB.size());
      
         System.out.println("ListA元素类型:"+listA.get(0).getClass());
                                        
        System.out.println("ListA元素:"+Arrays.toString((int[]) listA.get(0)));

        System.out.println("ListA1元素类型:"+listA1.get(0).getClass());

        System.out.println("ListB元素类型:"+listB.get(0).getClass());
    }
 

 运行结果

我们可以看到我们传递过去的int [] array数组,接受参数确实将int [] 识别为了T,也就是说我们List中元素是int[] ,所以我们的元素个数是1。

对于我们传递过去的Arrays.asList(2,3,4,5);这个可变参数我们没有指定类型,但是java会自动装箱操作,将这个几个参数自动封装为Integer类型。

补充

上面都是一维数组,那么如果是二维数组又是什么情况呢?

我们以Arrays中的toArray方法为例

public Object[] toArray() {

return Arrays.copyOf(elementData, size);

}

@SuppressWarnings("unchecked")
    public <T> T[] toArray(T[] a) {
        if (a.length < size)
            // 新建一个运行时类型的数组,但是ArrayList数组的内容
            return (T[]) Arrays.copyOf(elementData, size, a.getClass());
            //调用System提供的arraycopy()方法实现数组之间的复制
        System.arraycopy(elementData, 0, a, 0, size);
        if (a.length > size)
            a[size] = null;
        return a;

class Solution {
    public int[][] reconstructQueue(int[][] people) {
        Arrays.sort(people,(a,b)->{
            if(a[0]==b[0]) return a[1]-b[1];
            return b[0]-a[0];
        });
         LinkedList<int[]> que = new LinkedList<>();
         for (int[] p : people) {
             que.add(p[1],p);
         }
         return que.toArray(new int[people.length][]);
    }
}

实际上我们传递过去的二维数组int[][] ,我们参数中泛型T识别的是int[] ,然后传递到源码中的a实际上就是我们int[] 类型的一维数组,这个可以这样理解:int[3][2] 实际上是 int[3] {int[2], int[2], int[2]}。

然后返回值直接就是T[] 就是int[3][]。

下面这个例子更加好理解一些。

List<int[]> res = new ArrayList<>();
res.add(new int[]{100});
int[][] a = res.toArray(new int[0][]);
System.out.println(a[0][0]);

//成功运行并输出
100

其他问题

2.asList()方法返回对象使用add()方法抛出异常
先进行如下测试:

  public static void main(String[] args) {
        List<String> pets = Arrays.asList("tiger","mice");
        pets.add("lion");
    }
 

结果如下:

我们这里可以看到他抛出了一个异常,难道add方法不是List的基本用法吗?我们继续扒一下源码。

原来原来Arrays的asList方法使用的ArrayList类是一个内部定义的类,而不是java.util.ArrayList类。其部分源码如下:

private static class ArrayList<E> extends AbstractList<E>
        implements RandomAccess, java.io.Serializable
    {
        @java.io.Serial
        private static final long serialVersionUID = -2764017481108945198L;
        @SuppressWarnings("serial") // Conditionally serializable
        private final E[] a;

        ArrayList(E[] array) {
            a = Objects.requireNonNull(array);
        }
        
        ....
     }

我们可以看到这是一个静态内部类,存储数组元素的a变量是final类型的,由此判断,这个静态内部类是不能做任何内部元素的添加删除操作的!就跟String类一样,String对象存储字符数组的变量也是有final修饰符的。因为一旦增加数组元素,这个数组容量已经定好的容器就无法装载增加的元素了。

内部类里面并没有add,remove方法,我们可以看下这个类继承的AbstractList类里面对这些方法的实现:

public abstract class AbstractList<E> extends AbstractCollection<E> implements List<E> {  
    ........  
  
    public void add(int index, E element) {  
        throw new UnsupportedOperationException();  
    }  
  
    public E remove(int index) {  
        throw new UnsupportedOperationException();  
    }  

找到异常的来源了,我们使用asList得到的对象add、remove方法直接就是抛出异常。那么我们如果要想对asList得到的对象使用add、remove方法,该怎么办呢?

List<String> pets = new ArrayList<String>(Arrays.asList("a", "b", "c")); 

可以将传入的参数转换为一个ArrayList对象返回。

3.通过Arrays.asList方法将数组转成集合后,使用set方法修改元素,为什么原来的数组的值也会改变?
测试:

public static void main(String[] args){
            String[] strings={"A","B","C"};
            List<String> stringList=Arrays.asList(strings);
            stringList.set(0,"G");
            System.out.println(stringList);
            System.out.println(strings[0]);
        }
 

结果:

​我们可以看到集合的值和原数组的第一个值都被修改了,为什么原数组也会被修改呢?

原因是静态内部类ArrayList的成员变量a使用了final,用于存储集合的数组引用始终被强制指向原有数组。

所以原数组也会被修改。

​那么怎么在不修改原数组的基础上修改集合呢?我们同样可以采取将传入的参数转换为一个ArrayList对象返回的方式。
参考链接:https://blog.csdn.net/qq_51634677/article/details/131223655

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1468663.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

STL - 并查集

1、并查集原理 在一些应用问题中&#xff0c;需要将n个不同的元素划分成一些不相交的集合&#xff1b;开始时&#xff0c;每个元素自成一个 单元素集合&#xff0c;然后按一定的规律将归于同一组元素的集合合并&#xff1b;在此过程中要反复用到查询某一 个元素归属于那个集合的…

YOLOv5改进 | SPPF篇 | 利用YOLOv9最新的SPPELAN模块改进SPPF(全网独家创新,附手撕结构图)

一、本文介绍 本文给大家带来的改进机制是利用2024/02/21号最新发布的YOLOv9其中提出的SPPELAN模块来改进SPPF&#xff0c;其中YOLOv9针对于这个模块并没有介绍&#xff0c;只是在其项目文件中用到了&#xff0c;我将其整理出来用于我们的YOLOv5的项目&#xff0c;同时空间金字…

vue3中ref创建变量取值时自动补充 .value 插件 volar

插件 TypeScript Vue Plugin (Volar) 设置中配置

自然语言处理中关键概念——词嵌入(Word Embedding)

词嵌入&#xff08;Word Embedding&#xff09;是一种在自然语言处理中广泛使用的表示方法&#xff0c;它将离散的词汇表中的每个词转换为一个连续向量空间中的稠密向量。这种低维度实数向量能够捕捉词语之间的语义和句法关系。 通过训练神经网络模型&#xff08;如word2vec、G…

一周学会Django5 Python Web开发-Http请求HttpRequest请求类

锋哥原创的Python Web开发 Django5视频教程&#xff1a; 2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~_哔哩哔哩_bilibili2024版 Django5 Python web开发 视频教程(无废话版) 玩命更新中~共计25条视频&#xff0c;包括&#xff1a;2024版 Django5 Python we…

open3d KD-Tree K近邻点搜索

open3d KD-Tree K近邻点搜索 一、算法原理1.KD-Tree 介绍2.原理 二、代码三、结果1.原点云2.k近邻点搜索后的点云 四、相关数据 一、算法原理 1.KD-Tree 介绍 kd 树或 k 维树是计算机科学中使用的一种数据结构&#xff0c;用于在具有 k 维的空间中组织一定数量的点。它是一个…

【Django开发】0到1开发美多shop项目:短信验证码和RabbitMQ。全md文档笔记(附代码 文档)

本系列文章md笔记&#xff08;已分享&#xff09;主要讨论django商城项目相关知识。项目利用Django框架开发一套前后端不分离的商城项目&#xff08;4.0版本&#xff09;含代码和文档。功能包括前后端不分离&#xff0c;方便SEO。采用Django Jinja2模板引擎 Vue.js实现前后端…

开源世界的学术问题

自由软件基金会是1983年成立的&#xff0c;到现在是41年。正好很有意思的是&#xff0c;在去年还有一篇文章&#xff08;CSDN 的翻译&#xff09;&#xff0c;专门在质疑说成立 40 年的自由软件基金会是不是已经快不行了&#xff0c;所以我们会用这个标题叫做兴衰发展历程来介绍…

Windows安装HBuilderX

下载 HBuilderX下载地址: 下载地址 解压安装包 HBuilderX&#xff0c;Windows为zip包&#xff0c;解压后才能使用。 首先&#xff0c;选中下载的zip包&#xff0c;点击右键菜单&#xff0c;点击解压到当前文件夹进入解压后的文件夹&#xff0c;找到HBuilderX.exe&#xff0…

OpenFeign整合Sentinel

OpenFeign 整合 Sentinel 实现服务降级 引入依赖 <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!-- nacos服务发现 --><depen…

抖音数据抓取工具|短视频下载工具|视频内容提取软件

一、开发背景&#xff1a; 随着抖音平台的流行&#xff0c;越来越多的人希望能够下载抖音视频以进行个人收藏或分享。然而&#xff0c;目前在网上找到的抖音视频下载工具功能单一&#xff0c;操作繁琐&#xff0c;无法满足用户的需求。因此&#xff0c;我们决定开发一款功能强大…

unity Aaimation Rigging使用多个约束导致部分约束失去作用

在应用多个约束时&#xff0c;在Hierarchy的顺序可能会影响最终的效果。例如先应用了Aim Constraint&#xff0c;然后再应用Two Bone Constraint&#xff0c;可能会导致Two Bone Constraint受到Aim Constraint的影响而失效。因此&#xff0c;在使用多个约束时&#xff0c;应该仔…

代码随想录刷题笔记-Day23

1. 组合 77. 组合https://leetcode.cn/problems/combinations/ 给定两个整数 n 和 k&#xff0c;返回范围 [1, n] 中所有可能的 k 个数的组合。 你可以按 任何顺序 返回答案。 示例 1&#xff1a; 输入&#xff1a;n 4, k 2 输出&#xff1a; [[2,4],[3,4],[2,3],[1,2],…

R3F(React Three Fiber)经验篇

之前一直在做ThreeJS方向&#xff0c;整理了两篇R3F&#xff08;React Three Fiber&#xff09;的文档&#xff0c;这是经验篇&#xff0c;如果您的业务场景需要使用R3F&#xff0c;可以参考一下这个文档。下面是目录&#xff0c;按照需求自取。 基础篇 ⬇️ R3F&#xff08;…

buuctf_N1BOOK_粗心的小李

题目&#xff1a; 看完题目&#xff0c;git下载文件&#xff1f;然后将.git文件传到线上环境&#xff1f;&#xff08;which 会造成git泄露的安全威胁&#xff09;<这个背景抱歉我不太了解哈&#xff0c;可能后续有补充> 这里主要记录做法过程&#xff1a; 工具&#xf…

MAC地址学习和老化

MAC地址学习过程 一般情况下&#xff0c;MAC地址表是设备根据收到的数据帧里的源MAC地址自动学习而建立的。 图1 MAC地址学习示意图 如图1&#xff0c;HostA向SwitchA发送数据时&#xff0c;SwitchA从数据帧中解析出源MAC地址&#xff08;即HostA的MAC地址&#xff09;和VLAN…

7.网络游戏逆向分析与漏洞攻防-游戏网络架构逆向分析-通过逆向分析确定游戏明文接收数据过程

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;通过逆向分析确定游戏明文发送数据过程 上一个内容中得出它是使用的send函数发送的数据包&#xff0c;所以接收数据它指定用的是recv函数接收的数据 然后在跳转recv函数分析时发现跳转到了wsock32.d…

Git diff Word 文档

前言 前段时间用 nodeJS 写了一个提交代码的工具&#xff0c;开发过程中在认证部分遇到了一些小问题&#xff0c;于是就想看看官方的文档中有没有什么说明之类的&#xff0c;没想到文档中的内容十分丰富&#xff0c;除了解释了 git 相关的原理外&#xff0c;还学到了很多有用的…

TensorRT及CUDA自学笔记005 GPU架构和线程束

TensorRT及CUDA自学笔记005 GPU架构和线程束 GPU架构 流处理器streaming multiprocessor &#xff08;SM&#xff09; 每一个SM包含整数个CUDA core、共享内存\L1缓存&#xff08;shared memory\L1cache&#xff09;、注册文件&#xff08;Register File&#xff09;、加载和…

剪辑视频调色怎么让画质变得清晰 视频剪辑调色技巧有哪些方面 剪辑视频免费的软件有哪些 会声会影调色在哪里 会声会影模板素材

视频调色的作用有很多&#xff0c;除了进行风格化剪辑以外&#xff0c;还可以让作品的画质变得清晰。通过调色来增强画面的清晰度&#xff0c;在观感上也会显得十分自然。视频调色的技巧有很多&#xff0c;并且原理大都十分简单。有关剪辑视频调色怎么让画质变得清晰&#xff0…