黑马程序员——java基础——泛型
2015-06-12 14:26
405 查看
一, 什么是泛型
泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。Java中的泛型是Java5.0出现一种安全机制,是一种编译时期的技术。
二,怎么表示泛型
Java中用<>来表示泛型,<> 中间的内容通常是用单个大写字母来表示比如:<T> 。<qq,tt>这中写法也不错只不过阅读性差。
三, 泛型中的基本术语
以ArrayList<E>为例 ,<>念着typeof, ArrayList<E>中的E称为类型参数变量,ArrayList<Integer> 中的 Integer成为实际参数类型,整个ArrayList<E>称为泛型类型 , 整个 ArrayList<Integer>称为参数化的类型 。
四,泛型的好处
A:它的出现提高了程序的安全,让程序的一些在运行时期可能出现的问题,转移到编译时期。(ClassCastException)
B:避免了强制装换的麻烦。
下面用一个例子来阐述泛型的优点
直接运行上面的代码肯定会抛出异常(java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String)我们很容易就找出抛异常的地方 ,我们往集合中添加的第五个元素一个Integer 类的 而在下面遍历的时候我们把强制装换成String所以就会抛异常。这样的代码在编译的时候没有问题而在运行时就会出现问题,所以安全性不高,并且需要我要我们去强转。(强制装换的原因 在Java1.4之前没有泛型机制,其实ArrayList 集合的add 方法参数的类型是Object类型,并且 通过迭代器的next()的返回值的类型 也是Object 类 ,所以就需要我们进行向下转型。
到了Java5.0 出现了泛型机制
上面的代码是不能通过编译的 这样就将在运行时出现的问题转移到了编译时候,这样我们就知道程序有问题,就去修改代码。要想通过编译就将list.add(new Integer(2));注释掉。注释掉之后上面的代码就可以正常运行了,并且和最初没有加入泛型的代码作比较发现,加入泛型之后可以省去强转。
五 , 泛型的擦除和补偿
加入了泛型的代码在经过javac编译之后的字节码文件中是不带有泛型的(因为泛型是编译器的技术)这就是泛型的擦除。既然字节码文件中不存在泛型的话,那么为什么最后我们不需强转,这是因为泛型补偿机制的存在,由于有这个补偿机制的存在,在我们遍历集合的时候在底层帮我们完成强转,所以就不需要我们自己去实现强转。
六, 泛型类,接口,方法,限定。
A:泛型类
在定义一个类型的时候 由于这个类操作的引用数据类不确定,就可以加入泛型。
格式:public class 类名<类型参数变量1.....> {}比如:public class ArrayList<E>
我们也可以自定义一个泛型类
这样我们定义好了加入了泛型机制这个Tool工具类
B:泛型方法
在定义一个方法的时候 加入泛型
格式 :访问修饰符 <类型参数变量1.....> 返回值 方法名(参数列表) (一般泛型方法都会在返回值和 方法的参数列表中用到 该方法上定义的泛型) 比如:Collection接口中的toArray() <T> T[]toArray(T[] a)
自定义泛型方法
C:泛型接口
在定义接口的加入泛型
格式: 格式:public interface 接口名<类型参数变量1…> 比如:public interfaceIterator<E>
自定义泛型接口
D:泛型通配符
格式:<?> 就是用?表示类型参数 表示这个泛型接受的类型可以是任意的
E:泛型的限定
a, 上限
格式 :<? extends E> 比如:<? extends Person> 表示这个泛型接受的类型只能是Person或者Person 的子类(包括整个子类体系中的类) 其实上面的泛型通配符就是<? extends Object>
通常对集合中元素进行存储操作的时候用上限。
b,下限
格式:<? extends E> 比如:<? super Person> 表示这个泛型接受的类型只能是Person或者Person的父类(包括整个父类体系中的类)
通常在对集合中的元素进行取出操作的时候用下限
七:泛型注意的地方:
A:当泛型方法是静态的时候,不能使用该方法所在的类上面定义的泛型,要在该静态方法上自己定义泛型。
B:在定义泛型方法的时候,泛型要定义在访问修饰符之后,返回值之前。
C:使用泛型的时候保证左右两边的泛型一样。但是只有一边带有泛型的话是可以 比如 ArrayList<String> list1=new ArrayList(); //ok ArrayList list2=new ArrayList<String>();//ok 这种OK 的原因是兼容以前没有出现泛型之前的代码。
D: 使用泛型通配符的时候 不能像下面一样
泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部分,那些部分在使用前必须作出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。Java中的泛型是Java5.0出现一种安全机制,是一种编译时期的技术。
二,怎么表示泛型
Java中用<>来表示泛型,<> 中间的内容通常是用单个大写字母来表示比如:<T> 。<qq,tt>这中写法也不错只不过阅读性差。
三, 泛型中的基本术语
以ArrayList<E>为例 ,<>念着typeof, ArrayList<E>中的E称为类型参数变量,ArrayList<Integer> 中的 Integer成为实际参数类型,整个ArrayList<E>称为泛型类型 , 整个 ArrayList<Integer>称为参数化的类型 。
四,泛型的好处
A:它的出现提高了程序的安全,让程序的一些在运行时期可能出现的问题,转移到编译时期。(ClassCastException)
B:避免了强制装换的麻烦。
下面用一个例子来阐述泛型的优点
//创建一个arraylist集合 ArrayList list=new ArrayList(); //往集合中添加元素 list.add("aa"); list.add("bb"); list.add("cc"); list.add("cc"); list.add(new Integer(2)); //遍历集合 for(Iterator it=list.iterator();it.hasNext();) { String str=(String)it.next(); System.out.println(str); }
直接运行上面的代码肯定会抛出异常(java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String)我们很容易就找出抛异常的地方 ,我们往集合中添加的第五个元素一个Integer 类的 而在下面遍历的时候我们把强制装换成String所以就会抛异常。这样的代码在编译的时候没有问题而在运行时就会出现问题,所以安全性不高,并且需要我要我们去强转。(强制装换的原因 在Java1.4之前没有泛型机制,其实ArrayList 集合的add 方法参数的类型是Object类型,并且 通过迭代器的next()的返回值的类型 也是Object 类 ,所以就需要我们进行向下转型。
到了Java5.0 出现了泛型机制
//创建一个arraylist集合 ArrayList<String> list=new ArrayList<String>(); //往集合中添加元素 list.add("aa"); list.add("bb"); list.add("cc"); list.add("cc"); list.add(new Integer(2)); //遍历集合 for(Iterator<String> it=list.iterator();it.hasNext();) { System.out.println(it.next()); }
上面的代码是不能通过编译的 这样就将在运行时出现的问题转移到了编译时候,这样我们就知道程序有问题,就去修改代码。要想通过编译就将list.add(new Integer(2));注释掉。注释掉之后上面的代码就可以正常运行了,并且和最初没有加入泛型的代码作比较发现,加入泛型之后可以省去强转。
五 , 泛型的擦除和补偿
加入了泛型的代码在经过javac编译之后的字节码文件中是不带有泛型的(因为泛型是编译器的技术)这就是泛型的擦除。既然字节码文件中不存在泛型的话,那么为什么最后我们不需强转,这是因为泛型补偿机制的存在,由于有这个补偿机制的存在,在我们遍历集合的时候在底层帮我们完成强转,所以就不需要我们自己去实现强转。
六, 泛型类,接口,方法,限定。
A:泛型类
在定义一个类型的时候 由于这个类操作的引用数据类不确定,就可以加入泛型。
格式:public class 类名<类型参数变量1.....> {}比如:public class ArrayList<E>
我们也可以自定义一个泛型类
public class Tool<E> { public E test(E e) { E t=e; return t; } }
这样我们定义好了加入了泛型机制这个Tool工具类
B:泛型方法
在定义一个方法的时候 加入泛型
格式 :访问修饰符 <类型参数变量1.....> 返回值 方法名(参数列表) (一般泛型方法都会在返回值和 方法的参数列表中用到 该方法上定义的泛型) 比如:Collection接口中的toArray() <T> T[]toArray(T[] a)
自定义泛型方法
public <Q> void test(Q q) { [....] }
C:泛型接口
在定义接口的加入泛型
格式: 格式:public interface 接口名<类型参数变量1…> 比如:public interfaceIterator<E>
自定义泛型接口
public interface Tool<T> { public void test(T t); }
D:泛型通配符
格式:<?> 就是用?表示类型参数 表示这个泛型接受的类型可以是任意的
E:泛型的限定
a, 上限
格式 :<? extends E> 比如:<? extends Person> 表示这个泛型接受的类型只能是Person或者Person 的子类(包括整个子类体系中的类) 其实上面的泛型通配符就是<? extends Object>
通常对集合中元素进行存储操作的时候用上限。
b,下限
格式:<? extends E> 比如:<? super Person> 表示这个泛型接受的类型只能是Person或者Person的父类(包括整个父类体系中的类)
通常在对集合中的元素进行取出操作的时候用下限
七:泛型注意的地方:
A:当泛型方法是静态的时候,不能使用该方法所在的类上面定义的泛型,要在该静态方法上自己定义泛型。
B:在定义泛型方法的时候,泛型要定义在访问修饰符之后,返回值之前。
C:使用泛型的时候保证左右两边的泛型一样。但是只有一边带有泛型的话是可以 比如 ArrayList<String> list1=new ArrayList(); //ok ArrayList list2=new ArrayList<String>();//ok 这种OK 的原因是兼容以前没有出现泛型之前的代码。
D: 使用泛型通配符的时候 不能像下面一样
public void test(Collection<?> e) { //....... for(Iterator<?> it=e.iterator();it.hasNext();) { //这种用法是错误的 ? t=it.hasNext(); } }E:子类在实现带有泛型的接口的时候 子类可以丢弃接口的泛型也可以继续使用接口的泛型。
相关文章推荐
- java对世界各个时区(TimeZone)的通用转换处理方法(转载)
- java-注解annotation
- java-模拟tomcat服务器
- java-用HttpURLConnection发送Http请求.
- java-WEB中的监听器Lisener
- Android IPC进程间通讯机制
- Android Native 绘图方法
- Android java 与 javascript互访(相互调用)的方法例子
- 介绍一款信息管理系统的开源框架---jeecg
- 聚类算法之kmeans算法java版本
- java实现 PageRank算法
- PropertyChangeListener简单理解
- 插入排序
- 冒泡排序
- 堆排序
- 快速排序
- 二叉查找树