一.
泛型的基本使用已经说完了,泛型类,泛型接口和泛型方法的体现也已经讲述完了。现在讲述一下,泛型的高级使用。
来一个String,定义一个集合,里面存储的全都是字符串,那我们就明确类型。明确完之后,就导一个包,采用add方法往里面传递几个字符串。
接着对它进行遍历,遍历的时候类型也是字符串,
运行的时候没有问题,非常简单。
但是有一个问题,集合不唯一。其实就是介绍各种不同的情况,来显示事物的用法,这里就是显示泛型的用法。
有很多集合同时存在的情况下,如何迭代其中的某一个集合。
再继续写迭代器就不合适了,原因是:容器是不断在变化的,元素是不断在添加,但是怎么迭代都是一样的,为了提高代码复用性。
不论哪个集合都用这个方法来迭代,这个方法是用来打印集合的功能(迭代并打印集合中的元素)。
如果不搞Arraylist集合,搞一个hashset集合也是可以的,但是这个方法只能打印list或者Arraylist。
如果是Arraylist和hashset同时存在,那么方法中就用collection,提高复用性,扩展性就高多了。
collection级别比较高,可以承接list或者hashset。上面的例子中虽然集合不同,但是存储元素的种类是相同的,下面看存储不同种类时的情况。
这样一来al2就不能往里面传递了,如果我们写两个方法,显示错误,因为,参数类型一致都是集合,都是collection。这两个方法不能同时存在,因为接收到的全都是集合,这时候该怎么办?
这时候就是说,方法中集合里存放的元素种类不确定。当一旦要操作的类型不确定的时候,里面还不准备用具体类型的情况下,比如说不准备用String,
如果全都是string,那就是下图的写法。但是我们不准备用string,或者说不一定用string,可以用另外一种通配符的形式来表示。
现在给大家介绍的是泛型的通配符,通通都匹配的符号,这个通配符就是问号?,位置类型。
下图中不能明确类型,就还是写it.next()。
当我们写成问号的时候,就什么都能传递。还有一种方式,就是不写,这也是可以的。原因是:老版本中是没有泛型的,老版本中定义的方法就没有泛型,但是我们用的是新版本中的集合,那必须要兼容,但是左侧会报警报提示,还是不要这么写。运行一下,程序是没有问题的。
上面就是通配符的使用,再说一点就是,这个问号和后面写的一种方式差不多。未知类型就是当指的是当不明确类型情况下,可以用问号来表示。
有人说,我们能不能这样做,区别不大,将问号换成字母,运行一样是可以的。
有点区别,如果用T来书写的话,是可以写成下面的形式的,当程序在运行的时候,这里面只要有一个类型具备了,都是统一类型。只不过这方法是静态的,不需要对象去明确,直接调用就可以了,这和问号的区别并不大。有必要写这么麻烦么?没有。
区别是什么呢?如果有指定T的话,就意味着这个T能代表一个具体类型,并能被操作。具体的显示如下,当我们有些工具类中带有返回值为t的话,这个类型可以进行操作,而对于问号来讲,只仅在不明确类型并不对这个类型进行操作,用问号来表示。像这样仅仅是打印,就可以使用问号的表现形式,没必要写成字母的这种复杂的代码,最终调用object的toString方法,这就是问号通配符的特点。
上面的都是通配符的简单使用,下面描述一下它的高级用法。(后面这些知识点的介绍都是建立在前面知识的基础上展开的,一个发展的过程)
例子中,往集合里传递的是对象worker,为了后期打印的效果,将worker类中的tostring方法覆写。同时,学生类里面也进行相同的修改,因为是继承过来的,所以可以采用getname这样的方法。这是父类有的,不是本类私有的,
其它问号的部分不变,最终的结果显示worker和integer都打印出来了,任意类型都可以
现在我们有一个需求,有两个集合,除了worker就是student,
现在探讨worker类和String一起存在时的情况。
现在想打印一个容器中的元素,但是这个容器得有一个条件,不是什么都打印,只打印person的子类。既不是打印一个类(如果是一个类,那么T就可以明确),如果是打印所有类,则是问号表示。现在是想打印一部分类,就是打印worker,和student。有人说直接用person就可以了,但是左侧的小图标显示这是错误的。
person是一个单独的类型,而worker和student也是单独的类型,它们之间存在继承关系,但是在这里collection里面只能存储person的对象,这是一个具体类型。
举个例子来看,写全了如下所示,左右两边的泛型不匹配。现在有一集合al,如果它们可以用继承关系来表现的话,集合声明的时候说里面存的全都是人,也就是说无论是worker还是student都可以存进来。但是右侧的实体中标明只能存student,这就产生了矛盾(多态和泛型在这点上的区别是在哪?)。一般情况下写泛型要具备左右两边一致的特点。
但是我们现在就想要接收worker和student,要想接收person或者person的子类对象,可以这么弄。person子类对象很多,不确定,写法如下。这里还有波浪线,导个包就可以了。
可上面所讲的知识点就是泛型的限定,这属于泛型的高级应用。以前在用object的时候,只要写个object,那么什么都可以解决,现在做了限定以后,只能有一部分类型能进来,如果不是这个类型或它的子类,那么就直接编译失败。以前是编译没事,运行出事。
现在java的很多更新都是将运行时期的错误,往编译时期转,这样更加的安全。
泛型的限定知识点具体的写法如下,限定之后,可以直接拿继承方法。只要存进来都是它的子类的话,编译时检测都是对的。取得时候,都可以用父类来取,不能用student取是必然得,因为是问号,泛型限定中第一种体现搞定。在遍历的时候,貌似存在能否直接调用父类方法的问题。