------<a href="http://www.itheima.com" target="blank">Java培训、Android培训、iOS培训、.Net培训</a>、期待与您交流! -------
泛型,在我刚开始接触到这个知识点的时候我觉得这是个很鸡肋的知识,可有可无。但是随着我看完基础视频在练习中,我发现泛型把那个不是鸡肋,确实也很重要。因此我觉得对于泛型我要有一个全面的理解掌握。
泛型:在定义集合时,就直接明确存储元素的具体类型。
这就是用代码体现出来泛型。
在使用迭代器取出元素时,同样明确:
使用泛型同样带来了好处:
1.将运行时期的问题转移到编译时期,可以更好的让程序员发现问题并解决;
2.避免了向下转型的麻烦。
对泛型进行一个小小的总结:
泛型技术在集合中用那个用的范围很大。只要看到类或者接口在描述的时候右边有定义<>,就要泛型。其实就是容器在不明确操作元素的类型的情况下对外提供了一个参数<>。泛型就是应用在编译时期的一项安全机制。
说完了泛型的简单理论,下面看一下反省的内部原理:
在看内部原理时,不得不先说一下泛型的特点:擦除。
反省的擦除:编译器通过泛型对元素进行检查,只要检查通过,就会生成class文件。但是在class文件中,就会讲泛型的标识去掉。
说白了,泛型就是给编译器看的。而且通过反射可以添加其它类型元素:
这是一个小插曲,仅仅是证明泛型是做为编译时期才存在的。接下来对泛型中牵扯的专业术语做一个了解,就以ArrayList<E>和ArrayList<Integer>作为模版说明:
ArrayList<E>整个称之为:泛型类型 <E>称之为:类型变量或类型参数
ArrayList<Integer>整个称之为:参数化类型 ArrayLis称之为:原始类型
<Integer>称之为:类型参数实例或是实际参数类型
说完术语之后,再看一下参数化类型与原始类型的兼容性:
参数化类型可引用原始类型的对象;原始类型也可以引用参数化类型的对象。都会有编译警告,但是不会影响程序的编译和运行:
参数化类型不考虑类型的继承关系:
再来看一道练习题:
这个是正确的。是因为它们之间没有继承关系:第一行代码是原始类型引用参数化类型的对象;第二行代码是参数化类型引用原始类型的对象。
泛型通配符:
在不明确具体类型的情况下,可以用通配符来表示。<?>:这个就是通配符。
通过代码实例来说明通配符作用:
当然泛型也有限定:
1.泛型的上限<? extends E>:只能接受E类型或者是E类型的子类型。
上限的应用场景:一般用于在集合存储元素时。
2.泛型的下限<? superE >:只能接受E类型或者是E类型的父类。
下限的应用场景:当从容器中取出元素时,使用泛型下限。
泛型除了应用到集合中,还可以用到方法上或是类上。接着就是看泛型的应用:
1.泛型类:
在定义时就明确参数,由使用该类的调用者来传递具体类型。
2.泛型方法:
编译器判断泛型方法的实际类型参数的过程叫做类型推断。
调用泛型方法时,实际传递的参数类型或返回值类型来推断:
1.当某个类型变量只在整个参数列表中的所有参数和返回值中的一处被调用,那么根据调用方法时该处的实际应用类型确定;
2.当某个类型变量只在整个参数列表中的所有参数和返回值中的多处被调用。调用方法时,根据多处的实际应用类型对应同一种类型来确定;
3. 当某个类型变量只在整个参数列表中的所有参数和返回值中的多处被调用。如果调用方法时,这多处的实际应用类型对应到了不同的类型,且没有使用返回值,这时候取多个参数的最大的交际类型;
4. 当某个类型变量只在整个参数列表中的所有参数和返回值中的多处被调用。如果调用方法时,这多处的实际应用类型对应到了不同的类型,但有使用返回值,这时候优先考虑返回值的类型。