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

前提

我们需要知道两点

(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.mzph.cn/news/701181.shtml

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

相关文章

车载电子测试学习内容

搜集了一些车载测试的学习内容&#xff0c;大家可以参考。

从ChatGPT到Sora,来了解大模型训练中的存储

1 从chatGPT到Sora 2022年底&#xff0c;OpenAI推出人工智能聊天机器人ChatGPT&#xff0c;开启了大模型领域的“竞速跑”模式。2024年2月15日&#xff0c;随着视频生成模型Sora的横空出世&#xff0c;OpenAI再度掀起热潮。 Sora将视频生成内容拉到了一个全新的高度&#xff0c…

osmnx笔记:从OpenStreetMap中提取点和边的shp文件(FMM文件准备内容)

1 导入库 import osmnx as ox import time from shapely.geometry import Polygon import os import numpy as np 2 提取Openstreetmap 的graph Gox.graph_from_place(Huangpu,Shanghai,China,network_typedrive,simplifyTrue) ox.plot_graph(G) 3 提取graph中的点和边 gdf…

冯诺依曼体系结构 计算机组成的金字塔

01 冯诺依曼体系结构&#xff1a;计算机组成的金字塔 学习计算机组成原理&#xff0c;到底是在学些什么呢&#xff1f;这个事儿&#xff0c;一两句话还真说不清楚。不过没关系&#xff0c;我们先从“装电脑”这个看起来没有什么技术含量的事情说起&#xff0c;来弄清楚计算机到…

4 种策略让 MySQL 和 Redis 数据保持一致

先阐明一下 MySQL 和 Redis 的关系&#xff1a;MySQL 是数据库&#xff0c;用来持久化数据&#xff0c;一定程度上保证数据的可靠性&#xff1b;Redis 是用来当缓存&#xff0c;用来提升数据访问的性能。 关于如何保证 MySQL 和 Redis 中的数据一致&#xff08;即缓存一致性问…

2_怎么看原理图之协议类接口之UART笔记

通信双方先约定通信速率&#xff0c;如波特率115200 一开始时&#xff0c;2440这边维持高电平 1> 开始发送时&#xff0c;由2440将&#xff08;RxD0&#xff09;高电平拉低&#xff0c;并持续一个T的时间&#xff08;为了让PC机可以反应过来&#xff09;&#xff0c;T1/波…

汇编语言movs指令学习

字符串传送指令(Move String Instruction) movs 该指令是把指针DS:SI所指向的字节、字或双字传送给指针ES:DI所指向内存单元&#xff0c;并根据标志位DF对寄存器DI和SI作相应增减。该指令的执行不影响任何标志位。 记不清这指令是8086就有的&#xff0c;还是386以后新加的&…

C# OpenVINO PaddleSeg实时人像抠图PP-MattingV2

目录 效果 项目 代码 下载 C# OpenVINO 百度PaddleSeg实时人像抠图PP-MattingV2 效果 项目 代码 using OpenCvSharp; using Sdcb.OpenVINO; using System; using System.Diagnostics; using System.Drawing; using System.Security.Cryptography; using System.Text; us…

一种新型的AlGaN/GaN HEMTs小信号建模与参数提取方法

来源&#xff1a;A new small-signal modeling and extraction methodin AlGaN/GaN HEMTs&#xff08;SOLID-STATE ELECTRONICS 07年&#xff09; 摘要 本文提出了一种新型的用于GaN HEMTs&#xff08;氮化镓高电子迁移率晶体管&#xff09;的小信号等效电路&#xff0c;包含2…

Edting While Playing 瓦片地图编辑器开发整合导入自定义贴图 DEVC++ VS2022都可复制粘贴运行

接 多种类型图片模块读取-CSDN博客 与 Editing While Playing 使用 Easyx 开发的 RPG 地图编辑器 tilemap eaitor-CSDN博客 整合实现平面贴图纹理自定义 操作同上 导入步骤&#xff1a; 先运行程序&#xff0c;然后关闭&#xff0c;同目录下有四个文件夹&#xff0c; 把…

模型评估方式

文章目录 一、有监督-分类模型1、混淆矩阵2、分类模型的精度和召回率3、ROC曲线与AUC 二、有监督-回归模型1、均方误差MSE2、 R 2 R^2 R2决定系数3、回归模型代码示例 三、无监督模型1、kmeans求解最优k值的方法&#xff1a;轮廓系数、肘部法2、GMM的最优组件个数&#xff1a;A…

Vue+SpringBoot打造快递管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、研究内容2.1 数据中心模块2.2 快递类型模块2.3 快递区域模块2.4 快递货架模块2.5 快递档案模块 三、界面展示3.1 登录注册3.2 快递类型3.3 快递区域3.4 快递货架3.5 快递档案3.6 系统基础模块 四、免责说明 一、摘要 1.1 项目介绍 …

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

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

进阶了解C++(2)——复杂的继承及其底层原理

在上篇文章中&#xff0c;给出了关于继承这部分的相关知识&#xff0c;例如继承的定义&#xff0c;继承与默认成员函数等。本文将针对复杂的继承方式&#xff0c; 1. 复杂的继承方式&#xff1a; 1.1 单继承&#xff1a; class Professor { public:int _age;string _name; }…

Windows安装HBuilderX

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

计算机组成原理(13)-----硬件多线程

目录 1.细粒度多线程 2.粗粒度多线程 3.同时多线程&#xff08;SMT&#xff09; 在不支持硬件多线程的处理器中&#xff0c;若要进行线程的切换&#xff0c;就需要保存和恢复线程的运行环境&#xff08;否则会出现数据覆盖引起的错误&#xff09;。 但在支持硬件多线程的处…

Android java中包的使用

一.包的使用 为了更好的实现项目中类的管理&#xff0c;提供包的概念。 package语句作为Java源文件的第一条语句&#xff0c;指明该文件中定义的类所在的包。(若缺省该语句&#xff0c;则指定为无名包)。 它的格式为&#xff1a;package 顶层包名.子包名 ; 二.java中主要的包…

算法分析-面试1-字符串

文章目录 前言一、分类&#xff1a;看看就行了二、字符串API&#xff1a;创建和初始化&#xff1a;查询操作&#xff1a;比较操作&#xff1a;修改操作&#xff1a;截取操作&#xff1a;分割操作&#xff1a;格式化操作&#xff1a;连接操作&#xff08;Java 8 及以后&#xff…

Delphi 11 安卓的蓝牙权限申请

上一篇博客里面的代码&#xff0c;演示如何申请安卓的权限。 如何申请安卓的蓝牙权限&#xff1f; 本博客之前有一篇文章写过。 现在 Google 要求 Android API Level 必须是 33。对于 BLE 的权限申请&#xff0c;有了一些新的要求。 以下描述&#xff0c;基于 Delphi 11。 …

vue页面基本增删改查

练手项目vue页面 新手前端轻喷&#xff1a; 效果如下 1、2两个部分组成&#xff1a; 对应代码中 element-ui中的 el-form 和 el-table 照着抄呗&#xff0c;硬着头皮来&#xff01; 建议&#xff1a;认真读一遍你用的组件 那上边简单得列表举例&#xff1a; 建议大家手敲一个…