[19/03/23-星期六] 容器_ 泛型Generics

时间:2024-04-14 13:35:22

一、概念

生活中的容器不难理解,是用来容纳物体的,程序中的“容器”也有类似的功能,就是用来容纳和管理数据。

数组就是一种容器,可以在其中放置对象或基本类型数据。

---优势:是一种简单的线性序列,可以快速地访问数组元素,效率高。如果从效率和类型检查的角度讲,数组是最好的。

---劣势:不灵活。容量需要事先定义好,不能随着需求的变化而扩容。(因为数组容量是提前定义好的)

基于数组并不能满足我们对于“管理和组织数据的需求”,需要一种更强大、更灵活、容量随时可扩的容器来装载我们的对象,即容器也叫集合(Collection)

【容器的接口层次】Hash:哈希 ;Array:数组   linked:线性表  Map:存放键值对

[19/03/23-星期六] 容器_ 泛型Generics

【泛型】

泛型是JDK1.5以后增加的,它可以帮助我们建立类型安全的集合。在使用了泛型的集合中,遍历时不必进行强制类型转换。

JDK提供了支持泛型的编译器,将运行时的类型检查提前到了编译时执行,提高了代码可读性和安全性。

泛型的本质就是“数据类型的参数化”。 我们可以把“泛型”理解为数据类型的一个占位符(形式参数),即告诉编译器,在调用泛型时必须传入实际类型。

我们可以在类的声明处增加泛型列表,如:<T,E,V>,字符可以是任何标识符,一般采用这3个字母

【比喻】  容器:厨房一个大桶,放多种肉的混合,可以放但是拿出来某种肉得仔细找找看看

泛型:厨房放几个大桶,把肉分类,每种肉放一桶且各贴一种标签,方便拿出。而泛型就是这个标签。

【自定义泛型】

 /*测试泛型
*Generics:一般的、普通的,无标签、无商标的 Object:目标、物体、对象
*
*/
package cn.sxt.collection; public class Test_0323_Generics {
public static void main(String[] args) {
MyCollection mc=new MyCollection();
mc.set("高老师", 0);
mc.set(200, 1);
System.out.println((String)mc.get(0)); //没有加泛型的情况,取对象内容需要强制转型 ,Object型转成String型
System.out.println((Integer)mc.get(1)); //加了泛型后注意区别 MyCollection2类中, <String>类似于实参对应于形参<E>, 第2个<String>在jdk1.7之后可以不写
MyCollection2<String> mc2=new MyCollection2<String>();
mc2.set("李老师", 0);//如果这样 mc2.set(200, 1);会报错 因为mc2中只能放字符型对象
System.out.println(mc2.get(0));//这里不用像上边一样强制转型了 因为通过设置编译器会自动检查 相当于把肉分类了贴好标签 }
}
//没加泛型的情况
class MyCollection{
Object objs[]=new Object[5]; public void set(Object obj,int index){
objs[index]=obj;
} public Object get(int index) {
return objs[index]; } }
//加了泛型(本质就是某种类型)的情况:可以在类的声明处增加泛型列表,如:<T,E,V> 字符可以是任何标识符,一般采用这3个字母。 类似形参
class MyCollection2 <E> {
Object objs[]=new Object[5]; public void set(E e,int index){
objs[index]=e;
} public E get(int index) {
return (E)objs[index]; } }

【好处】容器相关类都定义了泛型,在开发中使用容器类时都要使用泛型。这样,在容器的存储数据、读取数据时都避免了大量的类型判断,非常便捷。

通过阅读源码,我们发现Collection、List、Set、Map、Iterator接口都定义了泛型,因此,我们在使用这些接口及其实现类时,都要使用泛型。

强烈建议使用泛型。事实上,不使用编译器也不会报错!

接口的源码如下图所示:

[19/03/23-星期六] 容器_ 泛型Generics