ArrayList<E>类定义和ArrayList<Integer>类引用中涉及的术语:
1、整个ArrayList<E>称为泛型类型
2、ArrayList<E>中E称为类型变量或类型参数
3、整个ArrayList<Integer>称为参数化的类型
4、ArrayList<Integer>中的Integer叫类型参数的实例或实际类型参数
5、ArrayList<Integer>中的<>念typeof
6、ArrayList称为原始类型

一、泛型是什么能做什么

泛型(Generic type 或者 generics)是对 Java 语言的类型系统的一种扩展,以支持创建可以按类型进行参数化的类。可以把类型参数看作是使用参数化类型时指定的类型的一个占位符,就像方法的形式参数是运行时传递的值的占位符一样。

JDK1.5 之前使用集合的问题

 public  static void testJDK5Befor(){
List list=new ArrayList();
list.add(1);
list.add(2);
list.add("abc");
int a1=(int) list.get(1);
int a2=(int) list.get(2);
}

执行代码在第7行出现错误 Exception in thread "main" java.lang.ClassCastException: java.lang.String cannot be cast to java.lang.Integer

JDK1.5 对集合加入了泛型的概念,直接在编译阶段验证数据类型。

 public  static void testJDK5After(){
List<Integer> list=new ArrayList<Integer>();
list.add(1);
list.add(2);
list.add("abc");
}

第5行在编写时直接报错,提醒你:The method add(Integer) in the type List<Integer> is not applicable for the arguments (String)

泛型的作用:泛型在编译时期进行严格的类型检查,消除了绝大多数的类型转换。泛型在集合中使用广泛,在JDK1.5之后集合框架就全部加入了泛型支持。在没有使用泛型之前,我们可以往List集合中添加任何类型的元素数据,因为此时List集合默认的元素类型为Object,而在我们使用的时候需要进行强制类型转换,这个时候如果我们往List中加入了不同类型的元素,很容易导致类型转换异常。

二、泛型擦除

泛型只作用于编译阶段,在编译阶段严格检查类型是否匹配,类型检查通过后,JVM会将泛型的相关信息擦出掉(即泛型擦除),也就是说,成功编译过后的class文件中是不包含任何泛型信息的,泛型信息不会进入到运行时阶段。

public static void  testMain01(){
ArrayList <String> listStr=new ArrayList<String>();
ArrayList <Integer> listInt=new ArrayList<Integer>();
System.out.println(listInt.getClass()==ArrayList.class);//true
System.out.println(listStr.getClass()==listInt.getClass());//true
}

通过该例子我们可以看出泛型在编译为.class文件,加载到内存中后是没有泛型概念的。

1、通过泛型的该特性我们可以使用反射绕过泛型检查向集合中添加任意类型的数据

public static void  testMain02() throws Exception{
ArrayList <Integer> listInt=new ArrayList<Integer>();
listInt.add(123);
//我们要往该集合内添加其他类型的数据
listInt.getClass().getMethod("add", Object.class).invoke(listInt, "string");
System.out.println(listInt.size());//
System.out.println(listInt.get(1));//string
}

三、泛型使用中出现的问题

//参数化类型与原始类型的兼容性-编译警告
Collection<String> = new Vector();
//原始类型可以引用一个参数化类型的对象。
Collection = new Vector<String >();
//参数化类型不考虑类型参数的继承关系
Vector<String> v = new Vector<Object>(); //错!
Vector<Object> v = new Vector<String>();//错!
//在创建数组实例时,数组的元素不能使用参数化的类型
Vector<Integer> v[] = new Vector<Integer>[10];
//编译可以通过!因为编译器只会按行解释
Vector v1 = new Vector<Integer>();
Vector<Object> v = v1;

 四、泛型的?通配符及扩展

<?>可以引用各种参数化的类型,可以调用与参数无关的方法,不能调用与参数有关的方法

    /**
* 遍历任意集合
* @param collection
*/
public static void printCollection(Collection<?> collection){
//System.out.println(collection.add("aa"));
System.out.println(collection.size());
for(Object obj:collection){
System.out.println(obj);
}
}

限定通配符的上边界
正确:Vector<? extends Number> v=new Vector<Integer>();表示 该泛型类型必须是number类型或者其子类类型
错误:Vector<? extends Number> v=new Vector<String>();

限定通配符的下边界
正确:Vector<? super Integer> v=new Vector<Number>();表示 该泛型类型必须是Integer类型或者Integer的父类类型
错误:Vector<? extends Integer > v=new Vector<Byte>();

五、定义泛型的方法

//采用自定义泛型的方式打印出任意参数类型中的所有元素
private static<T> void printCollection(Collection<T> collection,T obj2 ){
for(T obj : collection){
System.out.println(obj);
}
collection.add(obj2);
} //定义一个 方法,可以将任意类型的某个数组填充为相应类型的某个对象
private static<T> void fillArray(T[] a,T obj){
for(int i=0;i<a.length;i++){
a[i] = obj;
}
}
//定义一个 方法,自动将Object类型的对象转换成其它类型
private static<T> T autoConvert(Object obj){
return (T)obj;
}

六、自定义泛型类

 package com.jalja.org.base.test;

 import java.util.Date;

 public class GenericDao {
public <T> void add(T t){ }
public <T> T findById(int id){
return null;
} public static void main(String[] args) {
GenericDao gd=new GenericDao();
gd.add(new Date());
String str=gd.findById(12);
}
}

一般在DAO中,每个DAO操作的是同一个数据类型,而在本例的15行添加date类型,在16行确返回了一个string类型,我们如何控制我们的dao操作的是同一类型呢,使用泛型类

 package com.jalja.org.base.test;

 import java.util.Date;

 public class GenericDao <T>{
public void add(T t){
System.out.println(t.getClass());
}
public T findById(int id){
return null;
} public static void main(String[] args) {
GenericDao<Date> gd=new GenericDao<Date>();
gd.add(new Date());
String str=(String) gd.findById(12);
}
}

在这里会发现16行出错,Cannot cast from Date to String 。应为你必须操作同一类型 date

泛型类中的静态方法:

package com.jalja.org.base.test;

import java.util.Date;

public class GenericDao <T>{
public void add(T t){
System.out.println(t.getClass());
}
public T findById(int id){
return null;
}
//泛型中不能出现与泛型类相关的静态方法,应为静态方法是作用于类级别的,与具体类的实例对象没有关系。
//如果使用类名调用,泛型类型参数T是无法确定具体类型的所以,这样不可以。
public static void update(T t){ }
//可以定义与泛型类的泛型类型参数无关的静态方法
public static <E> void update(E e){ }
}

JAVA学习之泛型的更多相关文章

  1. Java学习之——泛型

    1.概要 generics enable types (classes and interfaces) to be parameters when defining classes, interfac ...

  2. 5 Java学习之 泛型

    1. 基本概念          泛型是Java SE 1.5的新特性,泛型的本质是 参数化类型 ,也就是说所操作的 数据类型 被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为 ...

  3. Java学习笔记--泛型

    一个泛型类就是具有一个或者多个类型变量的类. 我们可以只关注泛型,而不会为数据存储的细节而烦恼 . java泛型(一).泛型的基本介绍和使用 http://blog.csdn.net/lonelyro ...

  4. Java学习笔记——泛型

    假定T不仅要指定接口的类继承.使用下面的方式: public class some<T extends Iterable<T> & Comparable<T>&g ...

  5. Java学习点滴——泛型

    基于<Java编程思想>第四版 前言 虽然Java的泛型在语法上和C++相比是类似的,但在实现上两者是全然不同的. 语法 Java只需要一个<>就可定义泛型.在<> ...

  6. Java学习之泛型和异常

    泛型 1,设计原则或目的:只要代码在编译的时候没有错误,就不会抛异常.  2,泛型通配符  :类型通配符一般是使用 ? 代替具体的类型实参.注意了,此处是类型实参,而不是类型形参!相当于(父类作用)L ...

  7. Java学习之==>泛型

    一.什么是泛型 泛型,即“参数化类型”,在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型.也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类.接口 ...

  8. Java学习_泛型

    什么是泛型. Java标准库提供的ArrayList内部就是一个Object[]数组,配合存储一个当前分配的长度,就可以充当"可变数组". public class ArrayLi ...

  9. Thinking in Java学习笔记-泛型和类型安全的容器

    示例: public class Apple { private static long counter; private final long id = counter++; public long ...

随机推荐

  1. java 写一个单例设计程序,打印出该对象的地址

    class Test{ public static void main(String[] args) { singleton s1=singleton.getinstance(); singleton ...

  2. 小程序开发-13-小程序wxs的应用

    内容简介的换行 问题:因为微信的<text></text>标签能够转义\n,所以从服务器加载来的数据我们可以直接放到这个标签中,\n就会自己换行了.问题是服务器返回来的数据多了 ...

  3. E. Almost Regular Bracket Sequence

    题目链接:http://codeforces.com/contest/1095/problem/E 解题心得: 刚开始拿到这个题的时候还真的没什么思路,后来仔细想想还是比较简单的.首先题目要求翻转一个 ...

  4. tcp滑动窗口与拥塞控制

    TCP协议作为一个可靠的面向流的传输协议,其可靠性和流量控制由滑动窗口协议保证,而拥塞控制则由控制窗口结合一系列的控制算法实现.一.滑动窗口协议     所谓滑动窗口协议,自己理解有两点:1. “窗口 ...

  5. 全国Uber优步司机奖励政策 (12月28日-1月3日)

    本周已经公开奖励整的城市有:北 京.成 都.重 庆.上 海.深 圳.长 沙.佛 山.广 州.苏 州.杭 州.南 京.宁 波.青 岛.天 津.西 安.武 汉.厦 门,可按CTRL+F,搜城市名快速查找. ...

  6. 北京Uber优步司机奖励政策(2月23日)

    滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...

  7. Ubuntu adb 报错:no permissions (user in plugdev group; are your udev rules wrong?);

    Ubuntu 下 adb 报错: caoxinyu@caoxinyu-ThinkPad-T470p:~/Android/Sdk/platform-tools$ ./adb devices List o ...

  8. 这样的SQL居然能执行

    select /*! distinct   cities.id from cities  join countries on cities.id = countries.id limit 10 */;

  9. Arduino-元件简介

    DS18B20温度传感器 DS18B20是DALLAS公司生产的一种常用的温度传感器,其具有体积小巧.硬件功耗低.抗干扰能力强.精准度高的特点.该传感器具有单总线通讯的能力,电压范围为3.0V~5.5 ...

  10. rn打包分析

    rn打包原来是packager,后来独立出一个专门的打包工具metro,构建工具的大体思路跟前端构建工具差不多,都会有一个启动文件,然后根据模块依赖关系把对应文件找到. 开发中打包 在开发中打包,我们 ...