import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.*;
public class Testx4 {
public static void main(String[] args) throws Exception {
/*
* "ArrayList<E>"整个被称为泛型类型;E称为类型变量或类型参数
* "ArrayList<String>"被称为参数化的类型;String类型参数的实例或者实际类型参数
*/
Collection<String> c = new Vector();//参数类型可以可以引用一个原始类型的对象;新类型可不可兼容老类型
Collection c1 = new Vector<String>();//原始类型可以引用一个参数化类型的对象
Vector v = new Vector<String>();
Vector<Object> v1 = v;
//Vector<Object> v2 = new Vector<String>();错误
ArrayList<Integer> al1 = new ArrayList<Integer>();
al1.add(1);
al1.add(2);
ArrayList<String> al2 = new ArrayList<String>();
al2.add("abc");
al2.add("bbb");
System.out.println(al1.getClass() == al2.getClass());
/*泛型属于JDK1.5的性特性;它是提供给javac编译器使用的,可以限定集合中的输入类型
* 让编译器挡住程序中的非法输入,编译器编译带类型说明的集合时会除掉类型信息,使程序
* 运行效率不受影响,对于参数化的泛型类型,getClass()方法的返回值与原始类型完
* 全一样。由于编译生成的字节码去掉泛型的类型信息,那么只要能跳过编译器,就可以往
* 泛型集合中添加其他类型的数据如:通过反射得到集合,在调用其add方法
* 编译后运行的时候的字节码是没有类型信息的
* */
al1.getClass().getMethod("add", Object.class).invoke(al1,"cde");
//System.out.println(al1.get(1));
print(al1);
System.out.println("=====");
print(al2);
//通过Map.entry来迭代出map中的所有值
HashMap<String,Integer> hm = new HashMap<String,Integer>();
hm.put("a", 1);
hm.put("b", 2);
hm.put("c", 3);
Set<Map.Entry<String, Integer>> entrySet = hm.entrySet();
//Map.Entry<String, Integer>在这个set中每个元素都是这个类型,就是把每个key和value弄成一个整体在放到set中,然后在遍历输出
for(Map.Entry<String, Integer> entry : entrySet){
System.out.println(entry.getKey() + "->" + entry.getValue());
}
Method m = Testx4.class.getMethod("applyVector",Vector.class,int.class,HashMap.class);
/*
* 通过反射来获得参数化类型的实际类型。由于对于参数化类型在字节码阶段是没有类型存在的,
* 然而如果把一个这样的的参数化类型当做一个方法的参数的话,那么在字节码中就会存在这个参数化类型的实际类型的说明
*上面的m是我们自己的方法applyVector(),这里面得参数是参数化类型的变量,字节码中就会存在这个方法的参数列表,并且
*这个列表中包括了实际类型
*/
Class<?>[] paraType = m.getParameterTypes();
for(Class cc : paraType){
System.out.println(cc);
}
/*
* 这个是通过m得到方法的参数类型,这个类型不是参数化类型的实际类型,而是最外面得类型
* 比如这里运行结果:class java.util.Vector
* int
* class java.util.HashMap
*
* */
System.out.println("----------------------------------------------------------------");
Type[] type = m.getGenericParameterTypes();
for(Type t : type){
System.out.println(t);
}
/* 通过m的getGenericParameterTypes()方法我们可以得到方法中参数的所有类型包括了参数化类型的实际参数
* 运行结果:java.util.Vector<java.lang.String>
* int
* java.util.HashMap<java.lang.Integer, java.lang.String>
* */
System.out.println("-----------------------------------------------------------------");
ParameterizedType pt = (ParameterizedType)type[0];
//ParameterizedType pt1 = (ParameterizedType)type[1];
ParameterizedType pt2 = (ParameterizedType)type[2];
/*
* 这个ParameterizedType类是type的子接口,这个子接口中拥有3个方法,其中
* Type[] getActualTypeArguments():返回表示此类型实际类型参数的 Type 对象的数组;
* 对于参数化类型,这里就可以得到实际参数类型了
* Type getRawType() :表示参数化类型的最外层的类型;
* */
System.out.println(pt.getActualTypeArguments()[0]);
//输出结果:class java.lang.String;说明这个参数化类型的实际参数类型是String
System.out.println(pt.getRawType());
//输出结果:class java.util.Vector
//System.out.println(pt1.getActualTypeArguments()[0]);
//运行出错,因为这个type[1]是int类型,就不会存在参数化类型的实际类型
System.out.println(pt2.getActualTypeArguments()[0] + "-----"+pt2.getActualTypeArguments()[1]);
//运行结果:class java.lang.Integer-----class java.lang.String
//同样说明了,这个参数化类型的实际类型是Integer和String
}
public static void applyVector(Vector<String> v1,int i,HashMap<Integer,String> v2){
}
public static void print(Collection<?> c){//这个方法可以打印出来各种类型的Collection
//c.add(1);使用通配符就不能调用和类型有关的类型;现在就不能确定是什么类型,所以就不能调用和类型有关的方法
//c.size();和类型没有关系,那么就可以调用
//c = new HashSet<Date>();没有错误,?可以引用其他各种参数化的类型
for(Object obj : c){
System.out.println(obj);
}
}
}
java----泛型
最新推荐文章于 2024-09-08 20:54:26 发布