为什么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<>()

相关推荐
llwszx11 分钟前
【Java/Go后端手撸原生Agent(第七篇):Token预算管理 + 滑动窗口上下文裁剪】
java·后端·python·agent开发·上下文工程·上下文裁剪·滑动窗口裁剪
weixin_BYSJ19871 小时前
springboot3家政平台小程序--附源码00904
java·javascript·spring boot·python·django·flask·php
梦幻通灵1 小时前
Java中finally失效的几种情况【持续更新】
java·开发语言
月落归舟1 小时前
SpringMVC 多种响应返回方式
java·开发语言
吃饱了得干活2 小时前
JVM垃圾回收:从新生代到ZGC,从理论到调优
java·jvm·后端
长不胖的路人甲2 小时前
二叉排序树(BST)Java 完整实现 + 删除思路详解
java·开发语言·算法
大模型码小白2 小时前
Java 部署:Jenkins Pipeline 构建 Java 项目(自动化)
java·人工智能·python·机器学习
长不胖的路人甲2 小时前
可达性分析法(根搜索算法)完整详解
java·jvm·算法
笨笨饿2 小时前
#102_Codex无在VSCold无法打开
java·c语言·数据库·笔记
程序员清风2 小时前
AI不是万能的,大家要专注实践!
java·后端·面试