java泛型的获取和补偿以及内部类

public class Test<T> {
    public Test(){
        T t = new T();    // error
        Class<T> clazz = T.class;   //error
        T[] ts = new T[10];   //error
    }
}

java中泛型的实现时采用擦除法,所以不是第一类型。如若想保留泛型信息,必须采用泛型占位符。

比如常用的开源框架中的DAO层实现。

package sample.jersey.resources.entity;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

public class BaseDAO<U> {
	
	private Class<U> entityClass;
	public Class<U> getEntityClass() {
		return entityClass;
	}
	public void setEntityClass(Class<U> entityClass) {
		this.entityClass = entityClass;
	}
	protected BaseDAO(){
		Type type=getClass().getGenericSuperclass();
		Type[] trueType = ((ParameterizedType) type).getActualTypeArguments();
	    this.entityClass = (Class<U>) trueType[0];
	    System.out.println(" base construct invoked");
	}

}

  

package sample.jersey.resources.entity;

public class TagDao extends BaseDAO<Book> {

	
	public static void main(String[] args){
		TagDao dao=new TagDao();
		System.out.println(dao.getEntityClass());
		
	}
}

  Jackson json中反序列化时,可以通过TypeReference传递容器中的泛型类型,也是利用了泛型继承的特例:

Map<Integer, ApkBean> map = mapper.readValue(jsonData, new TypeReference<Map<Integer, ApkBean>>(){});

  TypeReference是一个泛型抽象类,在readValue的第二个方法中,传入了TypeReference的一个匿名子类实例,由此带入了Map的泛型信息。由于是两级泛型的嵌套,具体的情况其实更复杂一些,有兴趣的可以看看Jackson代码中TypeReference和TypeFactory的实现。

 

 

除了泛型继承这种情况之外,还有另外两个特例,也可以获取ParameterizedType类型,继而获取到泛型的类型。一个是类的field可以通过getGenericType来获取:

public class Test {

    private Map<String, Number> map;

    public static void main(String[] args) throws NoSuchFieldException {
        Class<?> clazz = Test.class;
        Field field = clazz.getDeclaredField("map");
        //取得泛型类型
        Type type = field.getGenericType();
        ParameterizedType ptype = (ParameterizedType)type;
        System.out.println(ptype.getActualTypeArguments()[0]);
        System.out.println(ptype.getActualTypeArguments()[1]);
    }

}

  另外就是方法的泛型参数可以通过getGenericParameterTypes来获取:

public class Test {

    public static void main(String[] args) throws NoSuchMethodException {
        Class<?> clazz = Test.class;
        Method method = clazz.getDeclaredMethod("getGenericSample", Collection.class);
        //取得泛型类型参数集
        Type[] type = method.getGenericParameterTypes();
        ParameterizedType ptype = (ParameterizedType)type[0];
        type = ptype.getActualTypeArguments();
        System.out.println(type[0]);
    }

    public void getGenericSample(Collection<Number> collection){

    }
}

  这两种特例的实用价值比较小,实际的代码hack中也比较少见。

 

下面的代码演示的是内部类的调用和泛型的补偿的另外一个例子。引自jackson里面的genericType里面的实现方法。

package sample.jersey.resources.entity;

import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

import com.sun.jersey.core.reflection.ReflectionHelper;

public class BaseDAO<U> {

	@SuppressWarnings("rawtypes")
	private Class entityClass;
	private Type type;

	public BaseDAO() {
		Type type = getClass().getGenericSuperclass();
		ParameterizedType parameterized = (ParameterizedType) type;
		type = parameterized.getActualTypeArguments()[0];
		entityClass=getClass(type);
//		entityClass=(Class) parameterized.getRawType();
		System.out.println(" base construct invoked");
		System.out.println(type);
		System.out.println(entityClass);
	}
	  @SuppressWarnings("rawtypes")
	private static Class getClass(Type type) {
		  
	        if (type instanceof Class) {
	            return (Class)type;
	        } else if (type instanceof ParameterizedType) {
	            ParameterizedType parameterizedType = (ParameterizedType)type;
	            if (parameterizedType.getRawType() instanceof Class) {
	                return (Class)parameterizedType.getRawType();
	            }
	        } else if (type instanceof GenericArrayType) {
	            GenericArrayType array = (GenericArrayType) type;
	            return ReflectionHelper.getArrayClass((Class) ((ParameterizedType) array.getGenericComponentType()).getRawType());
	        }
	        throw new IllegalArgumentException("Type parameter not a class or " +
	                "parameterized type whose raw type is a class");        
	    }
	public static void main(String[] args) {
		BaseDAO<List<Book>> dao=new BaseDAO<List<Book>>() {
			public void draw(){
				System.out.println(" I am from inherited class.");
			}
		};
		
		dao.draw();
		

	}
	
	
	public void draw(){
		System.out.println(" I am from father class.");
	}
}

  

posted @ 2014-06-17 17:03  menglgcn  阅读(535)  评论(0)    收藏  举报