* 第三十六集 入门泛型的基本应用
* 体验泛型
* jdk1.5以前的集合类中存在的问题
* ArrayList collection = new ArrayList();
* collection.add(1);
* collection.add(1L);
* collection.add("abc");
* int i = (Integer)collection.get(1);
* 有一个集合增加了整数,一个长整数,一个字符串
* jdk1.5的集合类希望你在定义集合时,明确表示你要向集合中装
* 哪种类型的数据,无法加入指定类型以外的数据
* 泛型是提供给Javac编译器使用的,可以限定集合中的输入类型,
* 让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合时
* 会去掉”类型“信息,使程序运行效率不受影响,对于参数化的泛型类型,
* getClass()的返回值和原类型完全一样。由于编译生成的字节码会
* 去掉泛型类型信息,只要能跳过编译器,就可以往某个泛型集合中加入
* 其它类型的数据,例如,用反射得到集合,再调用其add方法即可
*
*/
基本概念
泛型是JDK1.5的新特性内容之一,由于内容较多较杂,不易掌握,单独笔记。泛型就是一般的所有类型。应用在JDK1.5的安全机制,将运行时期的问题ClassCastException转到了编译时期。避免了强制转换的麻烦。当操作的引用数据类型不确定的时候,就使用<>.将操作的引用数据类型传入即可。<>接受的是一个具体引用数据类型的参数范围。在程序中,只要用到了带有<>的 类或者接口,就要明确传入的具体引用数据类型
/**
* 第三十七集 泛型的内部原理 及更深应用
* 泛型是提供给Javac编译器使用的,可以限定集合中的输入类型,
* 让编译器挡住源程序中的非法输入,编译器编译带类型说明的集合
* 时会去掉”类型“信息,使程序运行效率不受影响,对于参数化的泛
* 型类型,getClass()的返回值和原类型完全一样。由于编译生
* 成的字节码会去掉泛型类型信息,只要能跳过编译器,就可以往某
* 个泛型集合中加入 其它类型的数据,例如,用反射得到集合,再调
* 用其add方法即可
*
* 了解泛型
* ArraList<E>类定义和ArrayList<Integer>类引用中设计如下术语:
* --整个称为ArrayList<E>泛型类型
* --ArrayList<E>中的E被称为类型变量或类型参数
* --整个ArrayList<Integer>称为参数化的类型
* --ArrayList<Integer>中Integer称为类型参数的实例或实际类型参数
* --ArrayList<Integer>中的<>念着tyoeof
* --ArrayList称为原始类型
* 参数化类型与原始类型的兼容性:
* --参数化类型可以引用一个原始类型的对象,编译报告,例如:
* Collection<String> c = new Vector();
* --原始类型可以引用一个参数化的类型的对象,编译报告警告,例如:
* Collection c = new Vector<String>();
* 原来的方法需要接受一个新的参数,新的类型也要传进去
* 参数化类型不考虑类型参数的继承关系:
* --Vector<String> v = new Vector<Object>(); //错误。。
* 不写<Object>没错,写了就成明知故犯了。。
* --Vector<Object> v = new Vector<String>(); //也错误
*
* 在创建数组实例时,数组的元素不能使用参数化的类型,例如,下面语句是错误的
* Vector<Integer> vectorList[] = new Vector<Integer>[10]
* 思考题:线面代码会报错吗?
* Vector v1 = new Vector<String>();
* Vector<Object> v = v1;
*/
泛型的特点
1.泛型技术是给编译器使用的技术,用于编译时期,确保了类型的安全。运行时会将泛型去掉,生产的class文件中是不带有泛型的,这个称为泛型的擦除。
为什么要擦除呢?是为了兼容运行的类加载器。同时泛型也有补偿补偿,在运行时,通过泛型元素的类型进行转换动作,不用使用者再强制转换了。
代码演示:创建一个ArrayList对象,存储的是String类型对象,怎样建Integer类型的对象存入到ArrayList中
/**
* 第三十八集 泛型的通配符扩展应用
* 泛型中的通配符。。
* 问题:
* --定义一个方法,该方法用于打印出任意参数化类型的集合中的所有数据,该方法如何定义
* 错误方式:public static void printCollection(Collection<Object> cols){
for(Object obj:cols){
System.out.println(obj);
}
cols.add("String");没错
cols = new HashSet<Date>();会报错误
}
正确方式:public static void printCollection(Collection<?> cols){
for(Object obj:cols){
System.out.println(obj);
}
//cols.add("String");错误,因为他不知道自己未来匹配就一定是Sring
cols.size();//没有错误,此方法与参数类型没有关系
cols = new HashSet<Date>();
}
总结:
使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要作用引用,
可以调用与参数化无关的方法,不能调与参数有关的方法
*
*限定通配符的上边界:
*--正确:Vector<? extends Number> x = new Veator<Integer>();
*--错误:Vector<? extends Number> x = new Veator<String>();
*限定通配符的下边界:
*--正确:Vector<? super Integer> x = new Veator<Number>();
*--错误:Vector<? super Integer> x = new Veator<Byte>();
*提示限定符总是包括自己
*/
package cn.itcast.day2;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* @param args
* @throws NoSuchMethodException
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws SecurityException
* @throws IllegalArgumentException
*/
public static void main(String[] args) throws IllegalArgumentException, SecurityException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
// TODO Auto-generated method stub
ArrayList collection1 = new ArrayList();
collection1.add(1);
collection1.add(1L);
collection1.add("abc");
//int i = (Integer)collection1.get(1);
/**
* 在原始的类上延长一下
*/
ArrayList<String> collection2 = new ArrayList();
//collection2.add(1);
//collection2.add(1L);
collection2.add("abc");
String element = collection2.get(0);
ArrayList<Integer> collection3 = new ArrayList<Integer>();
System.out.println(collection3.getClass() == collection2.getClass());
/**
* 透过编译器利用反射,泛型是给编译器看的
*/
collection3.getClass().getMethod("add", Object.class).invoke(collection3, "abc");
System.out.println(collection3.get(0));
printCollection(collection3);
//Class<Number> x = String.class.asSubclass(Number.class);
}
public static void printCollection(Collection<?> collection){
//collection.add("abc");
System.out.println(collection.size());
Class<?> y;
Class<String> x;//Class.forName("java.lang.String");
/**
* 泛型的综合应用
*/
HashMap<String, Integer> maps = new HashMap<String, Integer>();
maps.put("zxx", 28);
maps.put("lhm", 28);
maps.put("flx", 28);
/**
* 变量命名可以起方法返回的结果
* 泛型的实际蚕食类型又是一个参数化的类型
*/
Set<Map.Entry<String,Integer>> entrySet = maps.entrySet();
for(Map.Entry<String, Integer> entry : entrySet){
System.out.println(entry.getKey() + ":" + entry.getValue());
}
/**
* 他们取公约共同类型
*/
add(3,5);
Number x1 = add(3.5,3);
Object x2 = add(3,"abc");
}
private static <T> T add(T x,T y){
return null;
}
}