为什么List<int[]> ans = new ArrayList<>()能成功创建

在Java开发或刷题时能够遇到List<int[]> ans = new ArrayList<>()

这行代码能够完美通过编译并成功运行,但稍作修改,写成List<int> ans = new ArrayList<>()编译器就会报错。

同样是类型,int[]可以作为泛型参数,而int却不行,

一、核心:Java中万物皆对象,除了基本类型

Java泛型有一条铁律,泛型参数必须是引用类型,绝不能是基本数据类型。

Java的数据类型分两种:

  • 基本数据类型
  • 引用类型:类、接口、数组等,存储在堆内存中,变量保存的是指向堆内存的引用

数组本质上是一个对象,声明int[]时,虽然里面装的是基本类型int,但int[]本身是一个继承自Object的引用类型,拥有length属性,并重写了clone()等方法。

因此List<int[]>中的int[]完全符合对引用类型的要求,编译器自然会放行。

二、语法糖的魅力:钻石操作符<>与类型判断

new ArrayList<>()使用了Java7引入的钻石操作符。

在没有这个语法之前,需要写成冗长的List<int[]> ans = new ArrayList<int[]>();

引入<>之后,Java编译器展现出了强大的类型判断能力,当编译器看到等号左侧的List<int[]>时,会自动推断出右侧的ArrayList的泛型参数也必须是int[]

不仅让代码变得简洁,还避免了前后泛型类型不一致导致的潜在错误。

三、面向对象基石:多态与接口契约

体现了Java面向对象编程中的多态原则。

左侧面向接口编程,List是一个接口,

右侧是具体的实现类,ArrayList实现了List接口,提供了基于动态数组的底层实现。

在Java中,父类/接口类型的引用可以指向子类/实现类的对象,因此用List接收ArrayList的实例,是极其标准且推荐的编码规范。

底层探秘:ArrayList是如何存储int\[\]的

JDK中ArrayList的源码,发现:

java 复制代码
// ArrayList的核心成员变量
transient Object[] elementData;

可以发现无论泛型写的是, , int\[\],底层用来存储数据的数组永远是Object[]

这是怎么做到的,归功于Java泛型的类型擦除机制。在编译阶段,泛型<int[]>会提供严格的类型检查;但在编译后的字节码中,泛型信息会被擦除,elementData退化成了普通的Object[],因为所有引用类型都可以向上转型为Object,所以ArrayList能够毫无障碍地将int[]存入底层的Object[]数组中。

为什么不能写List

因为int是基本类型,无法向上转型为Object,如果Java允许List<int>,在底层Object[]数组中就无法存储int值,会破坏Java类型系统的根基。

所以有包装类,Integer对象,List<Integer> nums = new ArrayList<>()

相关推荐
梦想的颜色1 小时前
从零入门:Docker在Ubuntu上的安装、使用与主流镜像仓库实战(Java/Go/MySQL/PostgreSQL/MongoDB/Nginx
java·ubuntu·docker
是多巴胺不是尼古丁2 小时前
期末java复习--string
java·开发语言·python
Survivor0012 小时前
高并发系统流量治理的底层算法
java·开发语言
凡人叶枫2 小时前
Effective C++ 条款35:考虑 virtual 函数以外的其他选择
java·c++·spring
garmin Chen2 小时前
从 Transformer 到 Agent:大模型技术全景解析
java·人工智能·python·深度学习·transformer
愚公移码2 小时前
蓝凌EKP18产品:流程引擎技术篇之流程核心概念模型
java·人工智能·流程引擎·蓝凌
Full Stack Developme2 小时前
Apache Tika 教程
java·开发语言·python·apache
鹅城剑仙2 小时前
Java线程池完全指南
java
李白的天不白2 小时前
SmartAdmin(基于 Spring Boot 框架)中配置跨域请求 VUE3 设置请求头
java·前端