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

public class Test {

public Test(){

T t = new T(); // error

Class 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 {

private Class entityClass;

public Class getEntityClass() {

return entityClass;

}

public void setEntityClass(Class entityClass) {

this.entityClass = entityClass;

}

protected BaseDAO(){

Type type=getClass().getGenericSuperclass();

Type[] trueType = ((ParameterizedType) type).getActualTypeArguments();

this.entityClass = (Class) trueType[0];

System.out.println(" base construct invoked");

}

}

package sample.jersey.resources.entity;

public class TagDao extends BaseDAO {

public static void main(String[] args){

TagDao dao=new TagDao();

System.out.println(dao.getEntityClass());

}

}

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

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

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

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

public class Test {

private Map 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 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 {

@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> dao=new BaseDAO>() {

public void draw(){

System.out.println(" I am from inherited class.");

}

};

dao.draw();

}

public void draw(){

System.out.println(" I am from father class.");

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值