------- android培训、java培训、期待与您交流! ----------
泛型是JDK1.5版本之后出现的新特性,用于解决安全问题
好处:
1.将运行时期出现问题ClassCastException,转移到了编译时期,方便程序员解决问题,让运行时期问题减少
2.避免了强制转换的麻烦
通过<>来定义要操作的数据类型
ArrayList<String> a1 = new ArrayList<String>();
//限定集合成员类型为String
Iterator<String> it = a1.iterator();
class Utils<TR>//泛型类
{
private TR q;
public TR getObject(){}
}
Utils<String> u = new Utils<String>();
当类中操作的数据不确定时,早期定义Object来完成扩展,现在定义泛型来完成扩展。
泛型类定义的泛型,整个类中有效,如果被方法使用,那么
泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定
为了让不同方法操作不同类型,而且类型还不确定,那么可以将泛型类定义在方法上。
public <Q> void show(Q q){}
泛型类中可以同时定义不同的泛型方法
class Demo<T>
{
public void show(T t)
{
System.out.println("show:"+t);
}
public <Q> void print(Q q)
{
System.out.println("print:"+q);
}
//静态方法不可以访问类上定义的泛型
//如果静态方法操作的应用数据类型不确定,可以将泛型定义在方法上。
public static <W> void method(W w)
{
System.out.println("method:"+w);
}
}
//泛型定义在接口上
interface Inter<T>
{
void show(T t);
}
//如果实现仍不确定传入类型,可以继续用泛型定义
class InterImpl<T> implements Inter<T>
{
public void show(T t)
{
System.out.println("show:"+t);
}
}
//对象类型不确定时,可以用?
public static void print(ArrayList<?> a1)
{
Iterator<?> it = al.iterator();
while(it.hasNext())
{
sop(it.next());
}
}
//也可以用T
public static <T> void print(ArrayList<T> a1)
{
Iterator<T> it = al.iterator();
while(it.hasNext())
{
sop(it.next());
}
}
//?通配符,也可以理解为占位符
//不明确具体类型时用?表示
//?可以定义用来接收具备多种泛型的数据
public static void print(ArrayList<?> al)
{
Iterator<?> it = al.iterator();
while(it,hasNext())
{
System.out.println(it.next());
}
}
//"T"表示具体类型,可以接收数据
public static <T> void print(ArrayList<T> al)
{
Iterator<T> it = al.iterator();
while(it,hasNext())
{
System.out.println(it.next());
}
}
泛型限定
? extends E:可以接收E类型或者E的子类型,上限
? super E:可以接收E类型或者E的父类型,下限
泛型是给javac编译器提供的类型限定
只要能跳过编译器就可以往某个泛型集合中加入其它类型的数据,例如,用反射得到集合在调用add方法。
collection.getClass().getMethod("add",Object.class).invoke(collection,"abc");
整个称为ArrayList<E>泛型类型
ArrayList<E>中的E称为类型变量或类型参数
整个ArrayList<Integer>称为参数化类型
ArrayList<Integer>中的Integer称为类型参数的实例化或实际类型参数
ArrayList<Integer>中的<> typeof
ArrayList称为原始类型
创建数组实例时,数组元素不能使用参数化的类型
Vector v1 = new Vector<String>();
Vector<Object> v = v1;
编译不报错
Vector<Object> v = new Vector<String>();
编译报错
因为编译器是一行一行检查代码的
使用?通配符可以引用其他各种参数化类型,?通配符定义的变量主要用作引用,
可以调用与参数化无关的方法,不能调用与参数化有关的方法。
自定义泛型
只有引用类型(不是基本类型)才能作为泛型的基本参数,
也可以用类型变量表示异常即参数化异常。
自己throw异常时可以抛T,catch时要明确所抛异常。
静态方法不能用类上的泛型限定。
通过
反射
获得泛型的实际参数类型
Method applyMethod = GenericTest.class.getMethod("applyVector.class");
Type[] types = applyMethod.getGenericTestParameterTypes();
ParameterizedType pType = (ParameterizedType)types[0];
pType.getRawType();//得到原始类型Vector
pType.getActualTypeArguments()[];//得到实际类型参数Data
public static void applyVector(Vector<Date> v1){}