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

相关推荐
夜郎king4 小时前
RuoYi-Vue3 企业级后台快速落地实战指南
java·开发语言
AI人工智能+电脑小能手5 小时前
【大白话说Java面试题 第156题】【06_Spring篇】第16题:Spring 用到了哪些设计模式?
java·spring·设计模式·代理模式·工厂模式
曹牧5 小时前
XML 解析过程中遇到 `org.xml.sax.SAXParseException
java·开发语言
要开心吖ZSH6 小时前
处方物流信息同步优化:从 36 秒到亚秒级的踩坑记录
java·数据库·mysql·性能优化
Wang's Blog6 小时前
JavaWeb快速入门: MyBatis入门与实战
java·mybatis
EntyIU6 小时前
Java NIO 实战
java·开发语言·nio
二宝哥6 小时前
springboot项目使用Gradle工具实现依赖版本控制
java·spring boot·后端·gradle·版本
济*沧*海7 小时前
Set集合深度解析:原理、特性与应用场景全攻略
java
geovindu7 小时前
java: Singleton Pattern
java·开发语言·后端·单例模式·设计模式·创建型模式
一路向北North7 小时前
Spring Security OAuth2.0(16):密码模式
java·后端·spring