java 动态泛型_Java通过反射实例化泛型类的问题

问题补充:我再把问题具体一点:

在使用jackson从json转换成bean时,需要传递类信息。

ObjectMapper mapper = new ObjectMapper();

String jackson1 = "json格式的字符串,略";

List list = mapper.readValue(jackson1, new TypeReference>(){});

String jackson2 = "json格式的字符串,略";

ClassB b = mapper.readValue(jackson2, new TypeReference(){});

然后拿着list或者b通过反射调用下面的接口,调用时会传递方法名。

public void testMethod(List list);

public void testMethod2(ClassB b);

想动态地给TypeReference传递类型信息,这个类型可能是ArrayList,也可能是ClassB,不确定,通过配置文件传递进来。

package org.codehaus.jackson.type;

import java.lang.reflect.ParameterizedType;

import java.lang.reflect.Type;

/**

* This class is used to pass full generics type information, and

* avoid problems with type erasure (that basically removes most

* usable type references from runtime Class objects).

* It is based on ideas from

*

* >http://gafter.blogspot.com/2006/12/super-type-tokens.html

,

* Additional idea (from a suggestion made in comments of the article)

* is to require bogus implementation of Comparable

* (any such generic interface would do, as long as it forces a method

* with generic type to be implemented).

* to ensure that a Type argument is indeed given.

*

* Usage is by sub-classing: here is one way to instantiate reference

* to generic type List<Integer>:

*

 
 

* TypeReference ref = new TypeReference<List<Integer>>() { };

*

* which can be passed to methods that accept TypeReference.

*/

public abstract class TypeReference

implements Comparable>

{

final Type _type;

protected TypeReference()

{

Type superClass = getClass().getGenericSuperclass();

if (superClass instanceof Class>) { // sanity check, should never happen

throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information");

}

/* 22-Dec-2008, tatu: Not sure if this case is safe -- I suspect

* it is possible to make it fail?

* But let's deal with specifc

* case when we know an actual use case, and thereby suitable

* work arounds for valid case(s) and/or error to throw

* on invalid one(s).

*/

_type = ((ParameterizedType) superClass).getActualTypeArguments()[0];

}

public Type getType() { return _type; }

/**

* The only reason we define this method (and require implementation

* of Comparable) is to prevent constructing a

* reference without type information.

*/

@Override

public int compareTo(TypeReference o) {

// just need an implementation, not a good one... hence:

return 0;

}

}

现在已经基本有了思路,但是还有点问题:

1.建个子类继承TypeReference,通过构造函数把类型信息传进来,修改TypeReference中的私有属性_type

import java.lang.reflect.Field;

import org.codehaus.jackson.type.TypeReference;

public class TypeReference4Reflect extends TypeReference {

TypeReference4Reflect(T t) throws IllegalArgumentException, IllegalAccessException, SecurityException, NoSuchFieldException {

Class> cla = TypeReference.class ;

Field field = cla.getDeclaredField("_type");

field.setAccessible(true);

field.set(this, t);

}

}

2.通过方法名找到对应的参数信息,把参数信息作为TypeReference4Reflect的构造函数

public static void reflect(String jackson) throws JsonParseException, JsonMappingException, IllegalArgumentException, SecurityException, IOException, IllegalAccessException, NoSuchFieldException, InvocationTargetException {

ObjectMapper mapper = new ObjectMapper();

Method[] methods = TestXMLAndJson.class.getDeclaredMethods();

for(Method m: methods ) {

if(m.getName().equals("testReflect")) {

Type[] types = m.getGenericParameterTypes();

Object o = mapper.readValue(jackson, new TypeReference4Reflect(types[0]));

TestJson testJSON = new TestJson();

m.invoke(testJSON, o);

}

}

}

public void testReflect(List psrList) {

for(Iterator iter = psrList.iterator(); iter.hasNext(); ) {

System.out.println(iter.next().getName());

}

}

3.存在的问题

if(m.getName().equals("testReflect"))

这种方式的判断肯定是不可靠的,有重载的方法就不好使了。参数个数不一样的重载还好办,可以通过判断参数个数来解决。针对目前我们的应用来说勉强可以,但是不够通用。如果参数个数一样类型不一样就不好办了。这样还得判断json内容和参数属性的匹配,不知道有没有更好的方法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值