------- android培训、java培训、期待与您交流! ----------
泛型是JDK1.5出现的安全机制。
泛型和集合:
在集合接口、类后增加<Type>,标明这个集合只能保存Type类型的对象,Type是类型参数。这样集合就会自动记住元素的数据类型,从而在取出时避免了强制类型转换。
将运行期的ClassCastException转到了编译期。
运行时会把泛型标记去掉,为了兼容类加载器,生成的class文件是不带泛型的,这个称为泛型的擦除。
泛型和反射:
Class<T>:如果对应的类暂时未知,则使用Class<?>。通过使用Class<T>可以避免强制类型转换:
public class ObjectFactory {
public static <T> T getInstance(Class<T> cls){//使用泛型
try{
return cls.newInstance();
}catch(Exception e){
e.printStackTrace();
return null;
}
}
public static void main(String[] args){
Date d = ObjectFactory.getInstance(Date.class);//不需要强制类型转换。
}
}
虽然泛型标记在编译成class文件时被擦除,但可以 使用反射获取泛型信息。
通常通过反射得到类包含的Field后,可以用下面方法获取Field的数据类型:
Class<?> a = f.getType();
但是如果f的类型有泛型,如Map<String,Integer>,可以用以下方法获取:
Type gType = f.getGenericType();
然后将gType转换为参数化类型ParameterizedType对象,通过以下方法:
Type[] getActualTypeArgument();返回泛型参数类型的数组。
getRawType();返回没有泛型信息的原始类型。
public class GenericTest
{
private Map<String , Integer> score;
public static void main(String[] args)
throws Exception
{
Class<GenericTest> clazz = GenericTest.class;
Field f = clazz.getDeclaredField("score");
Class<?> a = f.getType();
System.out.println("score的类型是:" + a);
// 获得Field实例f的泛型类型
Type gType = f.getGenericType();
if(gType instanceof ParameterizedType)
{
ParameterizedType pType = (ParameterizedType)gType;
Type rType = pType.getRawType();
System.out.println("原始类型是:" + rType);
// 取得泛型类型的泛型参数
Type[] tArgs = pType.getActualTypeArguments();
System.out.println("泛型类型是:");
for (int i = 0; i < tArgs.length; i++)
{
System.out.println("第" + i + "个泛型类型是:" + tArgs[i]);
}
}
else
{
System.out.println("获取泛型类型出错!");
}
}
}
泛型类和泛型方法:
//泛型方法指在方法声明时定义一个或多个类型形参。
//基本类型无法作为泛型参数,可以使用包装类。
//类型参数不能用来创建对象或作为静态变量的类型。
class GenericDemo1<T>{
//T t = new T; 编译错误
//public static T tt; 编译错误
//
public void show(T t){
System.out.println(t);
}
//当方法为静态时,不能访问类上定义的泛型,即不能使用泛型形参;
//静态方法是用泛型只能定义为泛型方法。
public static <E> void print(E e){
System.out.println(e);
}
public void wrong(){
ArrayList<String> cs = new ArrayList<String>();
//instanceof 运算符后不能使用泛型
// if(cs instanceof ArrayList<String>){
}
}
}
数组和泛型的区别点:
如果 Foo 是 Bar 的子类或子接口,数组:Foo[] 是 Bar[] 的子类;
泛型:G<Foo> 不是 G<Bar> 的子类。
类型通配符?
大多时候可以使用泛型方法代替类型通配符。泛型方法允许类型形参被用来表示方法的一个或多个参数之间的类型依赖关系,或方法返回值与类型参数之间的依赖关系。
如果只是进行支持子类化,应该使用类型通配符。<?> 可以看成<? extends Object>.
类型上限:<? extends E> 类型只能是E或E的子类。该方法可以使用E具有的方法和属性。
类型下限:<? super E> 类型只能是E或E的父类。
Collection集合
addAll(Collection<? extends E> col);一般存储元素使用上限,取出时使用上限类型,不会出现安全隐患。当对集合中的元素进行取出操作时,可以使用下限,可以使用父类方法操作。
如TreeSet集合中的比较器:
TreeSet(Comparator<? super E> comparator) 构造一个新的空 TreeSet,它根据指定比较器进行排序。
比较器中的compare()方法对父类参数进行比较,这些参数子类一定包含。
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import com.heima.bean.Animal;
import com.heima.bean.Dog;
public class GenericDemo22 {
/**
* @param args
*/
public static void main(String[] args) {
ArrayList<Dog> al = new ArrayList<Dog>();
al.add(new Dog(1));
al.add(new Dog(2));
al.add(new Dog(3));
al.add(new Dog(4));
printCol3(al);
}
//泛型方法
public static <T> void printCol(Collection<T> col){
Iterator<T> it = col.iterator();
T t = null;
while(it.hasNext()){
t = it.next();
System.out.println(t);
}
}
//类型通配符
public static void printCol2(Collection<?> col){
Iterator<?> it = col.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
}
//限定泛型上限,使用 <? super E>为限定泛型下限
public static void printCol3(Collection<? extends Animal> col){
Iterator<? extends Animal> it = col.iterator();
Animal an = null;
while(it.hasNext()){
an = it.next();
an.run();
}
}
}
java不支持泛型数组
更详细的参阅这篇文章http://blog.csdn.net/orzlzro/article/details/7017435