Java反射通用类型ParamertizedType对象创建失败,使用java.lang.exception

时间:2015-06-19 05:46:43

标签: java generics reflection

我正在尝试在运行时生成类型化类的实例以使用redis。

这是我的代码,但是它无法创建类型化类T的实例。

interface ObjectFactory<T>
{
    T create() throws Exception;
}

这是创建T

实例的类
import java.lang.reflect.ParameterizedType;

public class RedisObjectConstructor<T> implements ObjectFactory<T>
{

    @SuppressWarnings("unchecked")
    @Override
    public T create() throws Exception
    {
        try
        {
            return (T) ((Class<T>) ((ParameterizedType) this.getClass().getGenericSuperclass()).getActualTypeArguments()[0]).newInstance();
        }
        catch (Exception e)
        {
            throw new Exception();
        }
    }
}

这是实际设置和获取域字段值的逻辑:

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Map;

import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.stereotype.Component;

@Component
public class RedisBasicEntity<T>
{
    private final ObjectFactory<T> factory;

    public RedisBasicEntity(ObjectFactory<T> factory)
    {
        this.factory = factory;
    }

    public Map<String, String> getFields(T redisDomain, Class<? extends Annotation> ann)
    {
        Map<String, String> redisHash = new HashMap<String, String>();
        Class<?> clazz = redisDomain.getClass();
        while (clazz != null)
        {
            for (Field field : clazz.getDeclaredFields())
            {
                if (field.isAnnotationPresent(ann))
                {
                    field.setAccessible(true);
                    try
                    {
                        Object value = field.get(redisDomain);
                        if (value != null)
                        {
                            redisHash.put(field.getName(), value.toString());
                            System.out.println(field.getName() + ":" + value.toString());
                        }
                    }
                    catch (IllegalArgumentException e)
                    {

                    }
                    catch (IllegalAccessException e)
                    {

                    }
                }
            }
            c = c.getSuperclass();
        }
        return redisHash;

    }

    public T getRedisEntity(Map<String, String> redisHash, Class<? extends Annotation> ann) throws Exception
    {
        T redisDomain = factory.create();
        Class<?> clazz = redisDomain.getClass();
        while (clazz != null)
        {
            for (Field field : clazz.getDeclaredFields())
            {
                if (field.isAnnotationPresent(ann))
                {
                    field.setAccessible(true);
                    try
                    {
                        FieldUtils.writeDeclaredField(field, field.getName(), redisHash.get(field.getName()));
                    }
                    catch (Exception e)
                    {

                    }
                }
            }
        }
        return redisDomain;
    }
}

这是我的测试类:

import java.util.HashMap;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import com.ranker.annotations.rediskey.RedisHashKey;
import com.ranker.api.dao.iListQualityDAO;
import com.ranker.app.redis.domain.list.ListQuality;
import com.ranker.app.redis.repository.support.RedisBasicEntity;
import com.ranker.app.redis.repository.support.RedisObjectConstructor;

public class ListQualityDAO implements iListQualityDAO
{
    @Autowired 
    private RedisBasicEntity<ListQuality> redisBasicEntity;

    public static ListQuality saveListQuality()
    {
        RedisObjectConstructor<ListQuality> redisObjectConstructor = new RedisObjectConstructor<ListQuality>();
        RedisBasicEntity<ListQuality> redisBasicEntity = new RedisBasicEntity<ListQuality>(redisObjectConstructor);
        ListQuality listQuality = new ListQuality();
        listQuality.setBurialScore(10.0);
        Map<String, String> redisHash = redisBasicEntity.getFields(listQuality, RedisHashKey.class);
        return null;
    }

    public static ListQuality getListQuality() throws Exception
    {
        RedisObjectConstructor<ListQuality> redisObjectConstructor = new RedisObjectConstructor<ListQuality>();
        RedisBasicEntity<ListQuality> redisBasicEntity = new RedisBasicEntity<ListQuality>(redisObjectConstructor);
        Map<String, String> redisHash = new HashMap<String, String>();
        redisHash.put("satisfactionScore", "10.00");
        redisHash.put("burialScore", "5.00");
        redisHash.put("burialState", "true");
        ListQuality listQuality = redisBasicEntity.getRedisEntity(redisHash, RedisHashKey.class);
        return listQuality;

    }


    public static void main(String args[]) throws Exception
    {
        ListQualityDAO.getListQuality();
    }
}

用于识别字段的我的注释:

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface RedisHashKey {
}

请告诉我这里的错误:

以下是我测试运行时的异常:

  

线程中的异常&#34; main&#34; java.lang.Exception at   com.ranker.app.redis.repository.support.RedisObjectConstructor.create(RedisObjectConstructor.java:19)     在   com.ranker.app.redis.repository.support.RedisBasicEntity.getRedisEntity(RedisBasicEntity.java:61)     在   com.ranker.api.dao.impl.ListQualityDAO.getListQuality(ListQualityDAO.java:37)     在   com.ranker.api.dao.impl.ListQualityDAO.main(ListQualityDAO.java:45)

2 个答案:

答案 0 :(得分:1)

使用TypeTools,您的Class<T> type = (Class<T>)TypeResolver.resolveRawArgument(ObjectFactory.class, getClass()); return type.newInstance(); 实施可以是:

T

注意:这仅适用于您在此类中使用实际值参数化class RedisStringConstructor extends RedisObjectConstructor<String> { //... 的类。例如:

String

这样,类型参数RedisObjectConstructor保留在字节码中,可以恢复。简单地使用某种类型参数实例化new RedisObjectConstructor<String>(); // can't recover String 将不允许它被恢复:

ACC.NBR,CTA.NAMEZ

答案 1 :(得分:0)

正如此stackoverflow response中所述,我以这种方式修改了create的{​​{1}}方法:

RedisObjectConstructor<T>

并像这样实现它:

public class RedisObjectConstructor<T> implements ObjectFactory<T> {
    private final Class<T> type;

    public RedisObjectConstructor(Class<T> type) {
        this.type = type;
    }

    @Override
    public T create() throws Exception {
        return type.newInstance();
    }
}

并且没有更多的强制转换异常问题。