---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
1.什么是泛型
1.1 泛型是Java SE 1.5的新特性,泛型的本质是参数化类型,也就是说所操作的数据类型被指定为一个参数。这种参数类型可以用在类、接口和方法的创建中,分别称为泛型类、泛型接口、泛型方法。
1.2 不使用泛型和使用泛型的对比
1.2.1 在Java SE 1.5之前,没有泛型的情况的下,通过对类型Object的引用来实现参数的“任意化”,
“任意化”带来的缺点是要做显式的强制类型转换,而这种转换是要求开发者对实际参数类型可以预知的情况下进行的。
对于强制类型转换错误的情况,编译器可能不提示错误,在运行的时候才出现异常,这是一个安全隐患。
1.2.2 泛型的好处是在编译的时候检查类型安全,并且所有的强制转换都是自动和隐式的,提高代码的重用率。
1.3 泛型的规则和限制
1.3.1 泛型的类型参数只能是类类型(包括自定义类),不能是基本数据类型。
1.3.2 同一种泛型可以对应多个版本(因为参数类型是不确定的),不同版本的泛型类实例是不兼容的。
1.3.3 泛型的类型参数可以有多个。
1.3.4 泛型的参数类型可以使用extends语句,例如<T extends superclass>。习惯上称为“有界类型”。
1.3.5 泛型的参数类型还可以是通配符类型。例如Class<?> classType = Class.forName("java.lang.String")。
1.3.6 参数化类型可以引用一个原始类型的对象。
1.3.7 原始类型也可以引用一个参数化类型的对象。
1.4 ArrayList<E> 类定义和ArrayList<Integer>类中涉及术语:
1.4.1 整个ArrayList<E>称为泛型类型。
1.4.2 ArrayList<E>中的E称为类型变量或类型参数。
1.4.3 整个ArrayList<Integer>称为参数化的类型。
1.4.4 ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数
1.4.5 ArrayList<Integer>中的<>念着typeof
1.4.6 ArrayList称为原始类型。
1.5 泛型的使用原理:
泛型是提供给javac编译器使用的,可以限定集合中的输入类型,让编译器挡住源程序中的非法输入,
编译器编译带类型说明的集合时会去除掉“类型”信息,使程序运行效率不受影响。
对于参数化的泛型类型,getClass()方法的返回值和原始类型完全一样。
由于编译生成的字节码会去掉泛型的类型信息,只要能跳过编译器,
就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合对象,再调用其add方法即可。
2. 限制泛型
2.1 在上面的例子中,由于没有限制class GenericsFoo<T>类型持有者T的范围,实际上这里的限定类型相当于Object,
这和“Object泛型”实质是一样的。限制比如我们要限制T为集合接口类型。只需要这么做:
class GenericsFoo<T extends Collection>,这样类中的泛型T只能是Collection接口的实现类,
传入非Collection接口编译会出错。
注意:<T extends Collection>这里的限定使用关键字extends,后面可以是类也可以是接口。
但这里的extends已经不是继承的含义了,应该理解为T类型是实现Collection接口的类型,或者T是继承了XX类的类型。
3. 通配符泛型
3.1 为了解决类型被限制死了不能动态根据实例来确定的缺点,引入了“通配符泛型”。
3.2 针对上面的例子,使用通配泛型格式为<? extends Collection>,“?”代表未知类型,
这个类型是实现Collection接口。
3.2.1 如果只指定了<?>,而没有extends,则默认是允许Object及其下的任何Java类了。也就是任意类。
3.2.2 通配符泛型不单可以向下限制,如<? extends Collection>,还可以向上限制,
如<? super Double>,表示类型只能接受Double及其上层父类类型,如Number、Object类型的实例。
3.2.3 泛型类定义可以有多个泛型参数,中间用逗号隔开,还可以定义泛型接口,泛型方法。
4. 泛型方法
4.1 是否拥有泛型方法,与其所在的类是否泛型没有关系。要定义泛型方法,只需将泛型参数列表置于返回值前。
4.2 使用泛型方法时,不必指明参数类型,编译器会自己找出具体的类型。泛型方法除了定义不同,调用就像普通方法一样。4.3 一个static方法,无法访问泛型类的类型参数,所以,若要static方法需要使用泛型能力,必须使其成为泛型方法。
/*
整个称为ArrayList<E>泛型类型
ArrayList<E>中的E称为类型变量或类型参数
整个ArrayList<Integer>参数化的类型
ArrayList<Integer>中的Integer称为类型参数的实例或实际类型参数
ArrayList<Integer>中<>念typeof
ArrayList称为原始类型
在创建数组实例时,数组的元素不能使用参数化的类型
Vertor<Integer> vectorList[] = new Vector<Integer>[10];
使用?通配符可以引用其他各种参数化的类型,?通配符定义的变量主要用作引用,
可以调用与参数化无关的方法,
不能调用与参数化 有关的方法
*/
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Vector;
public class Test1 {
//泛型
public static void main(String[] args) throws Exception{
// TODO 自动生成的方法存根
//Test2();
//Test1();
//Test3();
Test4();
}
//泛型的好处是把运行时的错误变成编译时的错误,取出时候还不需转换
private static void Test2() {
ArrayList collection1 = new ArrayList();
collection1.add(1);
collection1.add(1L);
collection1.add("abc");
int i = (Integer)collection1.get(1);
}
private static void Test1() {
ArrayList<String> collection1 = new ArrayList<String>();
//collection1.add(1);
//collection1.add(1L);
collection1.add("abc");
String element = collection1.get(0);
//int i = (Integer)collection1.get(1);
System.out.println(element);
//<Integer>的可以传入,<String>类型的也可以传
printCollection(collection1);
}
//泛型在反射技术中的应用
private static void Test3() throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
//Constructor<String> constructor = String.class.getConstructor(StringBuffer.class);
Constructor<String> constructor = String.class.getConstructor(StringBuffer.class);
String str2 = constructor.newInstance(new StringBuffer("abc"));
System.out.println(str2.charAt(2));
//Vector<Integer> vectorList[] = new Vector[10];
}
//把字符串放入ArrayList<Integer>集合中去
private static void Test4() throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, SecurityException{
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(1);
//list.add("abc");
//由于泛型只作用于编译阶段,所以可以用反射区获取add方法
list.getClass().getMethod("add", Object.class).invoke(list, "abc");
System.out.println(list.get(1));
//<Integer>的可以传入
printCollection(list);
}
//打印出任意类型的集合元素
private static void printCollection(Collection<?> collection){
System.out.println("集合中的元素个数:"+collection.size());
for(Object obj:collection){
System.out.println(obj);
}
}
}
package cn.hmm.Generic;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
public class Test2 {
public static void main(String[] args) {
// TODO 自动生成的方法存根
//MapDemo();
Integer[] a = new Integer[]{1,2,3,4};
//char[] b = new char[]{'a','b','c','d'};//基本数据类型不能转换
swap(a,1,2);
for(Integer c:a){
System.out.println(c);
}
Object obj = "abc";
String str = AutoConvert(obj);
}
//泛型一些应用
private static void MapDemo() {
HashMap<String,Integer> maps = new HashMap<String,Integer>();
maps.put("ccz", 26);
maps.put("hmm", 24);
maps.put("hhc", 24);
Set<Map.Entry<String, Integer>> entrySet = maps.entrySet();
for(Map.Entry<String, Integer> entry : entrySet){
System.out.println(entry.getKey() + ":"+entry.getValue());
}
}
private static <T> void copy1(Collection<T> c,T[] a){
}
private static <T> void copy2(T[] c,T[] a){
}
//打印出任意类型的集合元素
private static <T> void printCollection(Collection<T> collection,T obj2){
System.out.println("集合中的元素个数:"+collection.size());
for(Object 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;
}
}
//
private static <T> T AutoConvert(Object obj){
return (T)obj;
}
//交换任意类型的数组的两个元素,泛型的类型不能是基本类型
private static <T> void swap(T[] a,int i,int j){
T temp = a[i];
a[i] = a[j];
a[j] = temp;
}
}
package cn.hmm.Generic;
import java.util.Set;
//dao Data access Object -->crud(Create,Read,update,delete)
public class GenericDao<E> {
public void add(E x){
}
public E findById(int id){
return null;
}
public void delete(E obj){
}
public void delete(int id){
}
public void update(E obj){
}
public E findByname(String name){
return null;
}
//如果是静态方法,要自己在方法上定义
public static <T> void update2(T obj){
}
public Set<E> findByConditions(String s){
return null;
}
}
package cn.hmm.Generic;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Date;
import java.util.Vector;
public class GenericTest {
public static void main(String[] args) throws NoSuchMethodException, SecurityException {
// TODO 自动生成的方法存根
//根据下面这个是没办法得到集合的类型的,但是可以根据方法,把集合当成参数传入
//Vector<Date> v = new Vector<Date>();
Method applyMethod = GenericTest.class.getMethod("applyVector", Vector.class);
Type[] types = applyMethod.getGenericParameterTypes();
ParameterizedType pType = (ParameterizedType)types[0];
System.out.println(pType.getRawType());
System.out.println(pType.getActualTypeArguments()[0]);
}
public static void applyVector(Vector<Date> v1){
}
}
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
详细请查看:www.itheima.com