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. sql server 获取当前日期前三十天的日期

    select convert(varchar(10),dateadd(dd,number,dateadd(month,-1,getdate())),120) as dtfrom master..spt ...

  2. 小程序开发-9-Behavior行为与加入缓存系统优化流行页面

    Behavior行为与加入缓存系统优化流行页面 navi组件与移动端触碰区域探讨 触碰区域优化 设计师切图切大点,多余部分变成透明色 前端将可触碰区域变大 解决向左箭头变灰,向右变灰 禁用事件的技巧 ...

  3. Java设计模式(20)——行为模式之命令模式(Command)

    一.概述 概念 类似C中的callback! UML简图 角色 客户端:创建具体命令,指定接收者 命令接口:声明命令的接口 具体命令:定义接收者和行为之间的弱耦合(execute执行方法) 请求者(I ...

  4. 成都Uber优步司机奖励政策(1月9日)

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

  5. CF 570 D. Tree Requests

    D. Tree Requests http://codeforces.com/problemset/problem/570/D 题意: 一个以1为根的树,每个点上有一个字母(a-z),每次询问一个子树 ...

  6. MyBatis-MBG(MyBatis Generator)

    1.添加jar包 <dependency> <groupId>org.mybatis.generator</groupId> <artifactId>m ...

  7. jQuery实现“回到顶部”按钮功能

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  8. 【quick-cocos2d-lua】 基本类及用法

    1.cc.Director(导演类) 获得导演类实例:local  director = cc.Director : getInstance() 其中 cc 是Cocos2d-x Lua 类的命名空间 ...

  9. gitignore 文件生效办法

    .gitignore 可以添加一些不加入git版本控制的文件 比如一些测试文件.因人而异的配置信息等等 .gitignore 文件展示如下 /.idea/target//.classpath /.pr ...

  10. 使用js跳转手机站url的若干注意点

    引子: 去年年底公司开发手机站平台,经历了前期的用户群.市场调查,产品需求分析,产品原型设计,ui前端到程序开发上线测试等等工作,终于上线...此处略去本人作为前端开发的心情. 应该说,我们的手机站平 ...