这篇我们讲泛型。讲ArrayList或是Hashmap的时候有些人注意到写声明语句时下面会有黄色的波浪线,把鼠标移到那儿,可以看到它说是个raw type,应该添加generic type。
Raw的意思是原始的,没有修饰的。啥意思呢?之前说过,ArrayList就像个大麻袋,里面可以装很多不同类型的变量或是对象,如果我现在把麻袋口一封,你知道我麻袋里装的是什么类型的东西么?你不知道。现在这个raw就相当于我直接把麻袋一封,啥都不告诉你,是个最原始的状态。那generic type呢?它的意思就是泛型,就相当于我在封好的麻袋口贴的一张标签,告诉你这里面是什么。以ArrayList为例,假设我里面装的都是字符串类型的元素,我就可以给它加个字符串类型的标签:
如果你的ArrayList里只有String类型的元素,那你会发现小黄线马上就不见了,因为有标签了,ArrayList知道它里面装的是什么:
我再声明一个ArrayList, 把标签改成Integer,你就会发现虽然它也是ArrayList,可是这个麻袋现在只能装整型了,你如果还继续装字符串就错了:
提示你整型ArrayList不接受字符串。注意,标签里整型写Integer,不能写int。如果你的ArrayList里什么类型都想装怎么办呢?好办,直接用Object当标签呗,因为在java里所有的类都继承自Object类,自然也就都属于它。这点我们也在讲多态时提过:
加了标签的对象就叫作泛型。你知道泛指是什么意思吧?就是广泛地指定,非特指。这里面是一个意思。还有,这个标签看起来是不是像方法里的参数?只不过用尖括号而不是圆括号。所以我们又给这个标签起了一个更形象的名字 – 参数化类型。并不是所有的类初始化时都可以加参数化类型,上面例子中的ArrayList之所以允许加参数化类型,因为java文档上允许:
看见那个尖括号E了吗?它可以代表任意类型。所以,当我用某一个标签来初始化一个对象时,比如ArrayList<String> al = new ArrayList<String>(),这个E就代表String。
既然可以用基本类型当标签,必然也可以用引用类型当标签。看下面程序:
泛型可以直接告诉你它里边装的是什么类型,一目了然。泛型还有一个优点,不用强制转换。之前讨论ArrayList和Hashmap时说过,从集合里拿元素的时候必须强制转换:
大家都是人脑,人脑都比电脑聪明,我们知道ArrayList里面就是Food类型的东西,我用get方法查看一下取出来的肯定是Food类型的,可不加泛型的ArrayList它就是不知道,它只能识别它是个object,它就是笨。所以你要强转。可加了泛型就不用强转了:
刚才演示的是泛型用在ArrayList的情况。大家知道,ArrayList是java自带的引用类型,那泛型是不是也可以用在自己创建的类上呢?没问题,而且格式也是一样的:
比如我现在自己创建一个叫TypeBag的类,那我可以这么写:
E换成别的字符也行,其实它就好比是一个形参一样。声明完TypeBag类后就可以在主函数里用泛型初始化对象了。和一般参数一样,泛型也可以拥有好几个参数化类型。比如看我下面的例子:
如果不把泛型算进去,这个小程序应该所有人都看得懂了,没什么难度。但TypeBag里接了两个泛型参数Integer和String,中间用逗号隔开,正好对应TypeBag里的K和V。虽然TypeBag类不再像ArrayList是个麻袋那样形象,但它的泛型依然像标签一样起到了提示的作用。这里它明确指示初始化时需要传参数,并且第一个是Integer,第二个是String。
再说最后一个例子,TypeBag类里面放引用类型。比如我是个卖电脑的,我想把产品都打印出来。先写程序再讲解:
这里面除了主类外我又声明了两个类,一个是Computer类,还一个是TypeBag类。当我执行TypeBag<Computer> t1 = new TypeBag<Computer>()时,把TypeBag这个类贴上了一个Computer类的标签,明确提示我这个TypeBag类与Computer类相绑定:
所以,接下来执行t1.setType(asus)为type变量赋值,结果其实就是type = asus。而asus存的是一个Computer对象的地址,意味着t1也存有该对象的地址:
所以,经过贴标签绑定后,TypeBag和Computer本质上成为了同一个类。打印时,t1.getType()得到的当然就是asus,asus再访问自己的成员变量最后一起打印出来。t2和t3同理。
这就是泛型的一些基本概念,最后一个例子可能理解起来需要点时间,别的应该没什么问题。讲selenium自动化测试的时候我们会用到ArrayList,到时我就会把泛型带上,所以请大家好好复习。
这篇文章的源代码是ArrayListGeneric,SelfClassBasicGeneric和SelfClassRefGeneric这三个小项目,再巩固一下。集合到此就暂时告一段落,下篇文章我们开始讲java的另一个重要概念 - 文件的操作。
本篇知识点及注意事项:
1. 泛型又叫参数化类型,可以显式告诉你绑定的是什么类型的元素,既可以是基本类型也可以是复杂类型。
2. 泛型不用强制转换。
3. 可以自己定义一个泛型类,然后绑定其他类。
网友评论