Java泛型中的多态

从作为Java程序员的早期开始,我们都知道如何实例化和使用Collection对象。 实例化为具体类的List接口将如下所示。

List myArrayList  =  new ArrayList();

如果myArrayList应该仅保存Integer对象,则从Java 5编译器开始,按照Java Generics规范,实例化将如下所示:

List<Integer> myArrayList = new ArrayList<Integer>();

在同一行中,接受和/或返回字符串列表的方法将从

public List processStrings(ArrayList myStringList);

public List<String> processStrings(ArrayList<String> myStringList);

而且它们是类型安全的,因此我们不必进行强制转换即可检索列表对象的项目

String aStringFromMyStringList = myStringList.get(0); //No ClassCastException possible.

如果将aStringFromMyStringList声明为String以外的任何内容,则以上内容将不会编译。

到这里为止,我们应该对面向对象的Java如何工作感到满意,但是下一项可能会让很多人感到惊讶。

当我们使用List<Integer> myArrayList = new ArrayList<Integer>(); 意味着我们应该只在ArrayList和NOTHING ELSE中使用“ Integer”。 等一下,泛型不是OOP的一部分,这意味着我们不能在这些对象中应用多态吗? 答案是不。 让我们看看为什么。

我们已经看到多态性适用于集合的基本类型,这就是为什么List<Integer> myArrayList可以实例化为新的ArrayList<Integer>();

但是呢:

class Parent{}class Child extends Parent{}

使用以上方法,以下实例将无法正常工作,并最终导致编译错误。

List<Parent> myList = new ArrayList<Child>() //Compilation Error;

一个简单的规则是变量声明的类型必须与您传递给实际对象类型的类型相匹配。 如果我们声明List<Parent> myList那么我分配给myList任何myList必须仅是<Parent>类型,而不是Parent类的子类型,而不是Parent类的超类型。

这意味着正确的代码是:

List<Parent> myList = new ArrayList<Parent>(); // Compiles fine

但是以上内容与习惯于使用以下合法内容的传统Java程序员矛盾。

Parent[] myParentArray = new Child[10];

要详细了解上述差异,让我们有一个如下的继承结构:

public class Animal{}public class Cat extends Animal{}public class Dog extends Animal{}

我们可以在数组中实现多态,因为不应将数组指定为安全类型。 请参见下面的数组示例,以及为什么我们需要将类型安全列表作为Collection对象。

public void addAnimals(Animal[] animals ) {animals [0] = new Animal();// If passed animal[] is of type Dog[] then we are adding a Cat object to a Dog[] array.animals [1] = new Cat();// If passed animal[] is of type Cat[] then we are adding a Dog object to a cat[] array.animals [1] = new Dog(); 
}

由于猫或狗是动物的类型,因此可以将猫阵列或狗阵列作为动物阵列进行传递。

public class callerClass() {Animal[] animalArray = new Animal[10];Cat[] catArray = new Cat[10];Dog[] dogArray = new Dog[10];addAnimals(animalArray); //Expected, no questions raised here. addAnimals(catArray); //As Cat[] is a type of Animal[] so we may end up in adding a Cat in Dog Array.                                                addAnimals(dogArray); // As Dog[] is a type of Animal[] so if Cat[] is passed we may end up in adding a Dog in a //Cat array.
}

但是看看如果我们使用Collections会发生什么。 我们可以有类似上面的方法:

public void addAnimals(List<Animal> myAnimalList()) {     //Some code here.  }

调用上述方法的调用方方法如下所示。

public class callerClass() {List<Animal> animalList = new ArrayList<Animal>();List<Cat> catList = new ArrayList<Cat>();List<Dog> dogList = new ArrayList<Dog>();addAnimals(animalList); addAnimals(catList);addAnimals(dogList); 
}

如果我们尝试编译以上内容,会发生什么? 它将在addAnimals(catList);行失败addAnimals(catList);addAnimals(dogList) ,因为List类型与addAnimals(List<Animal> myAnimalList())方法的预期列表类型不匹配。 该方法期望列表仅声明为动物类型。

尽管上面的方法失败了,但是当列表被声明为超类型列表时,泛型实际上可以保留子类型的实例。 例如,我们可以像下面这样详细实现addAnimals( List<Animal> myAnimalList () myAnimalList List<Animal> myAnimalList () )方法。

public void addAnimals(List<Animal> myAnimalList ()) {aList.add(new Animal()); // Expected code.aList.add(new Cat()); //Yes this works.aList.add(new Dog()); //Any Animal subtype works.
}

这意味着我们可以将子超类继承概念应用到对象列表中,而不是将对象作为方法参数分配或传递给列表。

这就是Java禁止编译addAnimals(catList)代码的原因,因为如果编译了该代码,则稍后在已实现的addAnimals方法中,即使aList是一个aList,也始终可以使用aList.add(new Dog())代码。猫名单的类型,这是错误的! 我们不能将Dog对象添加到Cat列表中,因为该列表仅声明为具有Cat对象(或其子类)。 泛型可以使列表类型安全并且在技术上有意义。 为了接受多态子/超类,我们可以使用通配符来增强方法签名,这可以在另一个会话中进行讨论。

翻译自: https://www.javacodegeeks.com/2015/03/polymorphism-in-java-generics.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/360269.shtml

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

相关文章

ASP.NET伪静态-无法读取配置文件,因为它超过了最大文件大小的解决办法

一直都在使用微软URLRewriter&#xff0c;具体的使用方法我就不多说了&#xff0c;网上文章很多。 但最近遇到一个问题&#xff0c;就是当web.config文件里面设置伪静态规则过多&#xff0c;大于2M的时候&#xff0c;就报错&#xff1a;无法读取配置文件&#xff0c;因为它超过…

java定义list_我的Java Web之路59 - Java中的泛型

本系列文章旨在记录和总结自己在Java Web开发之路上的知识点、经验、问题和思考&#xff0c;希望能帮助更多(Java)码农和想成为(Java)码农的人。目录介绍再谈Java中的类型为什么需要泛型&#xff1f;Java中的泛型泛型类型泛型方法总结介绍还记得我在这篇文章(我的Java Web之路3…

Spring查找方法示例

当一个bean依赖于另一个bean时&#xff0c;我们使用setter属性或通过构造函数注入bean。 getter方法将向我们返回已设置的引用&#xff0c;但是假设您每次调用getter方法时都想要一个依赖bean的新实例&#xff0c;那么您可能将不得不采用另一种方法。 在本文中&#xff0c;我…

mysql判断数字的函数_Mysql必读MySql判断汉字、日期、数字的具体函数

《Mysql必读MySql判断汉字、日期、数字的具体函数》要点&#xff1a;本文介绍了Mysql必读MySql判断汉字、日期、数字的具体函数&#xff0c;希望对您有用。如果有疑问&#xff0c;可以联系我们。MYSQL学习几个平常用的mysql函数,MySql判断汉字、日期、数字的具体函数分享给大家…

编码:可视化位图

在过去的一个月左右的时间里&#xff0c;我每天花费一些时间来阅读Neo4j代码库的新部分&#xff0c;以使其更加熟悉&#xff0c;而我最喜欢的类之一是Bits类&#xff0c;该类可以完成所有底层工作&#xff0c;并且到磁盘。 特别是&#xff0c;我喜欢它的toString方法&#xff…

通过更改透明度使图片为透明

使用AlphaBlend函数 函数功能 该函数用来显示具有指定透明度的图像。函数原型 AlphaBlend(HDC hdcDest,int nXOriginDest,int nYOriginDest,int nWidthDest,int hHeightDest,HDC hdcSrc,int nXOriginSrc,int nYOriginSrc,int nWidthSrc,int nHeightSrc,BLENDFUNCTION blendFunc…

(转)CocoaPods:管理Objective-c 程序中各种第三方开源库关联

在我们的iOS程序中&#xff0c;经常会用到多个第三方的开源库&#xff0c;通常做法是去下载最新版本的开源库&#xff0c;然后拖拽到工程中。 但是&#xff0c;第三方开源库的数量一旦比较多&#xff0c;版本的管理就非常的麻烦。有没有什么办法可以简化对第三方库的管理呢&…

为什么子进程每次执行顺序不一样_看完这篇还不懂Redis的RDB持久化,你来打我...

推荐观看&#xff1a;Redis缓存穿透的终极解决方案&#xff0c;手写布隆过滤器_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​www.bilibili.comP8架构师串讲&#xff1a;Redis&#xff0c;zookeeper&#xff0c;kafka&#xff0c;Nginx等技术_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili​w…

Spring XD用于数据提取

Spring XD是一个功能强大的工具&#xff0c;它是一组可安装的Spring Boot服务&#xff0c;可以独立运行&#xff0c;在YARN或EC2之上运行。 Spring XD还包括一个管理UI网站和一个用于作业和流管理的命令行工具。 Spring XD是一组功能强大的服务&#xff0c;可与各种数据源一起使…

JDK 9 REPL:入门

会议是聚会Java名人的好地方。 Devoxx France是与Java语言架构师&#xff0c;前同事和老朋友Brian Goetz&#xff08; briangoetz &#xff09;见面的一个机会。 我们谈论了JDK 9&#xff0c;而他全都热衷于REPL。 他提到&#xff0c;尽管Java SE 9中有很多重要功能 &#xff0…

sinaapp mysql连接_手把手教你在新浪云上免费部署自己的网站--连接数据库

看完之后&#xff0c;默认你知道怎么将代码上传到新浪云SAE&#xff0c;并且能够成功运行&#xff0c;连接数据库之前&#xff0c;你必须先创建有一个应用。现在我创建一个名称为sampleone的应用&#xff0c;如下图点击左侧的代码管理&#xff0c;选在右侧创建一个版本然后就会…

HDU-4527 小明系列故事——玩转十滴水 模拟

题意&#xff1a;就是平时玩的十滴水游戏&#xff0c;游戏者拥有一定的水滴&#xff0c;能够滴在某些位置&#xff0c;如果一个点上的体积超过了4就会爆炸&#xff0c;向四周传递一个小水滴。该题就是要求模拟这个过程。 分析&#xff1a;这里有一个问题就是不能够使用递归来处…

win8改win7 教程

新入手的WIN8怎么改成WIN7呢&#xff1f;下面以戴尔Dell V3560 win8换win7系统为例说明&#xff1a; win8改win7本文转自http://jingyan.baidu.com/article/ed2a5d1f2a97ee09f6be17e2.html 第一步&#xff1a;开机过程中不断按F2进入到BIOS&#xff0c;更改bios设置&#xff0c…

7 centos 查看程序文件数量_解析CentOS 7中系统文件与目录管理

LINUXLinux操作系统解析CentOS 7中系统文件与目录管理Linux目录结构Linux目录结构是树形的目录结构根目录所有分区、目录、文件等的位置起点整个树形目录结构中&#xff0c;使用独立的一个“/”表示常见的子目录目录目录名称目录目录名称/root管理员家目录/bin所有用户可执行命…

IE浏览器模式设置

文件兼容性用于定义让IE如何编译你的网页。此文件解释文件兼容性&#xff0c;如何指定你网站的文件兼容性模式以及如何判断一个网页该使用的文件模式。 前言 为了帮助确保你的网页在所有未来的IE版本都有一致的外观&#xff0c;IE8引入了文件兼容性。在IE6中引入一个增设的兼容…

mysql存储过程套嵌_mysql存储过程套嵌

{"moduleinfo":{"card_count":[{"count_phone":1,"count":1}],"search_count":[{"count_phone":4,"count":4}]},"card":[{"des":"阿里云数据库专家保驾护航&#xff0c;为用户…

拆卸invokedynamic

许多Java开发人员认为JDK的第七版有些令人失望。 从表面上看&#xff0c;仅少数语言和库扩展使它成为了发行版&#xff0c;即Project Coin和NIO2 。 但在幕后&#xff0c;该平台的第七个版本对JVM类型系统进行了最大的扩展&#xff0c;这是它最初发布后引入的。 添加invokedyna…

CRON

http://blog.csdn.net/tianlesoftware/article/details/5315039 1. 同时修改文件的修改时间和访问时间 touch -d "2010-05-31 08:10:30" test.doc 2. 只修改文件的修改时间 touch -m -d "2010-05-31 08:10:30" test.doc 3. 只修改文件的访问时间 touch -a …

mysql innodb_file_format_Innodb表压缩过程中遇到的坑(innodb_file_format)

对于越来越多的数据&#xff0c;数据库的容量越来越大&#xff0c;压缩也就越来越常见了。在我的实际工作中进行过多次压缩工作&#xff0c;也遇到多次问题&#xff0c;在此和大家分享一下。首先&#xff0c;我们先说说怎么使用innodb的压缩.第一&#xff0c;mysql的版本需要大…

java内存泄漏和内存溢出_Java和内存泄漏

java内存泄漏和内存溢出总览 术语“内存泄漏”在Java中的使用方式不同于在其他语言中使用的方式。 通用术语中的“内存泄漏”是什么意思&#xff0c;在Java中如何使用&#xff1f; 维基百科的定义 当计算机程序消耗内存但无法将其释放回操作系统时&#xff0c;就会发生计算机科…