当前位置: 首页 > news >正文

关于List、List?、ListObject的区别

定义:声明中具有一个或者多个类型参数(type parameter)的类或者接口,就是泛型类或者接口。泛型类和接口统称为泛型(generic type)

clipboard.png
每种泛型定义一组类型形参(formal type parameters),这些类型形参有时也被简称为类型参数(type parameter),例如对于泛型(generic type)List<E>而言,List<String>就是一个参数化的类型(parameterized type),String就是对应于类型形参(formal type parameters)类型实参(actual type parameter)

每个泛型定义一个原生类型(raw type),即不带任何类型参数的类型名称,例如,与List<String>对应的原生类型是List。原生类型就像从类型声明中删除了所有泛型信息一样。实际上原生类型List与Java平台在有泛型之前的接口类型List完全一样。

容器类使用泛型的好处:

  • 安全性:在对参数化类型的容器中放入了错误即不匹配的类型的时候,编译器将会强制性进行错误提示。
  • 便利性:当从容器中取出元素的时候不用自己手动将Object转换为元素的实际类型了,编译器将隐式地进行自动转换。
  • 表述性:带有类型实参的泛型即参数化类型,可以让人看到实参就知道里面的元素E都是什么类型。

所以,不应该使用原生类型的原因如下:

虽然使用原生类型是合法的,但不提倡这样做,因为如果使用原生类型,就失掉了泛型在安全性和表述性方面的所有优势;安全性:比如我们可能会不小心把一个java.util.Date实例错误地放进一个原本包含java.sql.Date实例的集合当中,虽然在编译期不会出现任何错误,但在运行期一旦尝试类型转换就会发生ClassCastException,而泛型原本就是为了避免这种问题而出现的;表述性:不像带有类型实参的泛型即参数化类型那样,让人看到实参就知道里面的元素E都是什么类型。

泛型的子类型化的原则:List<String>类型是原生类型List的一个子类型,而不是参数化类型List<Object>的子类型

List、List<?>、List<Object>的区别

  • List,即原始类型,其引用变量可以接受任何对应List<E>的参数化类型, 包括List<?>,并且可以添加任意类型的元素。但其缺点在于不安全性、不便利性、不表述性(不应该使用原生类型的原因)。
  • List<?>,即通配符类型,其引用变量,同样可以接受任何对应List<E>的参数化类型,包括List,但不能添加任何元素,保证了安全性和表述性。但不具有表述性,从中取出的元素时Object类型,要通过手动转换才能得到原本的类型。
  • List<Object>,即实际类型参数为Object的参数化类型,其引用变量可以接受List,可以添加元素,但不能接受除了其本身外的任何参数化类型(泛型的子类型化原则)。
引用变量的类型名称可以接受的类型能否添加元素安全性便利性表述性
List原始类型任何对应List<E>的参数化类型, 包括List<?>可以添加任意类型的元素
List<?>通配符类型以接受任何对应List<E>的参数化类型,包括List不能添加任何元素
List<Object>实际类型参数为Object的参数化类型仅可以接受List和其本身类型可以添加任意类型元素

可以看到相比参数化类型的List<Object>,List<?>缺点在于不能添加任何元素并且不具有便利性,如果这无法满足功能要求可以考虑使用泛型方法和有边界的通配符。

根据The Java™ Tutorials,原生类型对象可以被赋给参数化类型(包括有界无界通配符参数化类型),同样,参数化类型(包括有界无界通配符参数化类型)对象也能被赋给原生类型

参考:《effective java》

相关文章:

  • 如何合理的规划jvm性能调优
  • 异步
  • 这一次,彻底弄懂TCP三次握手,四次挥手
  • 线程的等待和唤醒
  • js中forEach回调同异步问题
  • 整行读字符串且需分割计算字符串个数
  • 比特大陆新一轮裁员50%,回应称系人员调整
  • zabbix linux系统模板更新
  • 2019.2.20 c++ 知识梳理
  • 微信全局登录设计与实现
  • 朝鲜APT集团Lazarus通过KEYMARBLE Backdoor瞄准俄罗斯组织
  • Less 日常用法
  • 手机端车牌号码键盘的vue组件
  • 回归生活:清理微信公众号
  • Cisco Nexus 系列交换机NX-OS升级
  • JS 中的深拷贝与浅拷贝
  • 《用数据讲故事》作者Cole N. Knaflic:消除一切无效的图表
  • 【347天】每日项目总结系列085(2018.01.18)
  • 【JavaScript】通过闭包创建具有私有属性的实例对象
  • 【译】React性能工程(下) -- 深入研究React性能调试
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • canvas 五子棋游戏
  • Docker下部署自己的LNMP工作环境
  • Hibernate最全面试题
  • JavaScript设计模式系列一:工厂模式
  • k8s 面向应用开发者的基础命令
  • MySQL Access denied for user 'root'@'localhost' 解决方法
  • Python3爬取英雄联盟英雄皮肤大图
  • vue学习系列(二)vue-cli
  • 给新手的新浪微博 SDK 集成教程【一】
  • 基于web的全景—— Pannellum小试
  • 前嗅ForeSpider中数据浏览界面介绍
  • 实战|智能家居行业移动应用性能分析
  • 正则与JS中的正则
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • #单片机(TB6600驱动42步进电机)
  • $NOIp2018$劝退记
  • (09)Hive——CTE 公共表达式
  • (175)FPGA门控时钟技术
  • (4)STL算法之比较
  • (C++)栈的链式存储结构(出栈、入栈、判空、遍历、销毁)(数据结构与算法)
  • (env: Windows,mp,1.06.2308310; lib: 3.2.4) uniapp微信小程序
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (机器学习的矩阵)(向量、矩阵与多元线性回归)
  • (转)ABI是什么
  • (转载)hibernate缓存
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • *** 2003
  • ****Linux下Mysql的安装和配置
  • **CI中自动类加载的用法总结
  • .md即markdown文件的基本常用编写语法
  • .NET 8 中引入新的 IHostedLifecycleService 接口 实现定时任务
  • .net 发送邮件
  • .NET上SQLite的连接