JAVA学习之泛型
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学习之泛型的更多相关文章
- Java学习之——泛型
1.概要 generics enable types (classes and interfaces) to be parameters when defining classes, interfac ...
- 5 Java学习之 泛型
1. 基本概念 泛型是Java SE 1.5的新特性,泛型的本质是 参数化类型 ,也就是说所操作的 数据类型 被指定为一个参数.这种参数类型可以用在类.接口和方法的创建中,分别称为 ...
- Java学习笔记--泛型
一个泛型类就是具有一个或者多个类型变量的类. 我们可以只关注泛型,而不会为数据存储的细节而烦恼 . java泛型(一).泛型的基本介绍和使用 http://blog.csdn.net/lonelyro ...
- Java学习笔记——泛型
假定T不仅要指定接口的类继承.使用下面的方式: public class some<T extends Iterable<T> & Comparable<T>&g ...
- Java学习点滴——泛型
基于<Java编程思想>第四版 前言 虽然Java的泛型在语法上和C++相比是类似的,但在实现上两者是全然不同的. 语法 Java只需要一个<>就可定义泛型.在<> ...
- Java学习之泛型和异常
泛型 1,设计原则或目的:只要代码在编译的时候没有错误,就不会抛异常. 2,泛型通配符 :类型通配符一般是使用 ? 代替具体的类型实参.注意了,此处是类型实参,而不是类型形参!相当于(父类作用)L ...
- Java学习之==>泛型
一.什么是泛型 泛型,即“参数化类型”,在不创建新的类型的情况下,通过泛型指定的不同类型来控制形参具体限制的类型.也就是说在泛型使用过程中,操作的数据类型被指定为一个参数,这种参数类型可以用在类.接口 ...
- Java学习_泛型
什么是泛型. Java标准库提供的ArrayList内部就是一个Object[]数组,配合存储一个当前分配的长度,就可以充当"可变数组". public class ArrayLi ...
- Thinking in Java学习笔记-泛型和类型安全的容器
示例: public class Apple { private static long counter; private final long id = counter++; public long ...
随机推荐
- 笔记-django第一个项目
笔记-django第一个项目 1. 创建项目 安装 Django 之后,现在有了可用的管理工具 django-admin.可以使用 django-admin 来创建一个项目: 看下djang ...
- 环境变量Path简介
更多详细专业的详解,请参见:http://www.cnblogs.com/sunada2005/articles/2725277.html 什么是Path变量: PATH环境变量.作用是指定命令搜索路 ...
- Android AOSP 单独编译某一模块
由于AOSP 项目太大,我只修改了一个模块,比如设置. 那么只需要单独编译设置这个模块就可以了. 首先执行Source: source build/envsetup.sh 执行之后,就会有一些额外的命 ...
- (转) 如何从 0 开始学 ruby on rails (漫步版)
原文:http://readful.com/post/12322300571/0-ruby-on-rails ruby 是一门编程语言,ruby on rails 是 ruby 的一个 web 框架, ...
- Awesome Flask
Awesome Flask A curated list of awesome Flask resources and plugins Awesome Flask Framework Admin i ...
- MAC 更新brew 镜像源
mac 更新brew镜像源 cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core" git remote set-url o ...
- Qt-QML-给我的导航条写一个动画-State-Transition
上篇中,我已经写出一个导航条的,虽然太丑了,不过功能是有了,这次我将要给我的导航条加一个动画,先看下演示效果 这次我是用的是一个状态动画,大致原理就是写出一个空间的几个状态,完了再加一个过度动画,这里 ...
- 【SpringCloud】第六篇: 分布式配置中心(Spring Cloud Config)
前言: 必需学会SpringBoot基础知识 简介: spring cloud 为开发人员提供了快速构建分布式系统的一些工具,包括配置管理.服务发现.断路器.路由.微代理.事件总线.全局锁.决策竞选. ...
- Java开发工程师(Web方向) - 04.Spring框架 - 第1章.Spring概述
第1章.Spring概述 Spring概述 The Spring Framework is a lightweight solution and a potential one-stop-shop f ...
- Spring 配置String转Date
操作步骤: 1. 实现 org.springframework.core.convert.converter.Converter 接口 2. 配置 org.springframework.contex ...