如何在方法中使用类的通用

时间:2016-10-20 11:03:40

标签: java spring hibernate generics

我有一个抽象类,它采用泛型,在这个类中有一些方法。

我的问题是我不能使用通用的E inside方法。

public abstract class AbstractRepository<E> implements Repository<E> {

    final Class<E> typeParameterClass;

    public AbstractRepository(Class<E> typeParameterClass) {
        this.typeParameterClass = typeParameterClass;
    }

    ...

    @Override
    public E findById(Integer id) {
        try {
            this.entityManager.find(typeParameterClass, id);

        } catch (IllegalArgumentException error) {
            error.printStackTrace();

        } catch (PersistenceException error) {
            error.printStackTrace();
        }
        return null;
    }

我尝试使用通用E作为&#39; find()&#39;的参数。如下所示,但我得到一个错误,表示E未定义。

@Override
public E findById(Integer id) {
    try {
        this.entityManager.find(E, id);

    } catch (IllegalArgumentException error) {
        error.printStackTrace();

    } catch (PersistenceException error) {
        error.printStackTrace();
    }
    return null;
}

要解决这个问题,我使用typeParameterClass。

typeParameterClass是一个扩展AbstractRepository的每个其他类必须传递的参数,这个参数是类本身,但它似乎不正确,因为我已经有了泛型类。

现在的方式示例:

@Repository
public class UserRepository extends AbstractRepository<User> {

    public UserRepository(){
        super(User.class);
    }

    ...
}

那么,有没有办法在方法中使用泛型E?

存储库是一个也采用通用E的接口。

我在Spring中使用Hibernate。

2 个答案:

答案 0 :(得分:0)

Java在运行时不存在泛型类型信息,因此无法确定用于具体实例的类型参数。

因此,处理此问题的唯一方法是通过Class参数,因为这些参数设计为在运行时携带类型信息,并具有自引用泛型参数,这就是为什么你可以通过将其声明为E,确保使用的类型属于您的类型Class<E>。同样,所有泛型类型参数都只是编译器糖并在运行时被删除(因此它们只能确保没有人在您的实例中编写通过非E类的代码)。

答案 1 :(得分:-1)

我在我的项目中使用了完全相同的方法,我在Gentyref的帮助下解决了这个问题,以获得更清晰的代码(mavengooglecode):

import static com.googlecode.gentyref.GenericTypeReflector.getExactSuperType;
import static com.googlecode.gentyref.GenericTypeReflector.getTypeParameter;

public abstract class GenericRepository<T> {

    protected GenericRepository() {
        Type genericRepositoryType = getExactSuperType(getClass(), GenericRepository.class);
        Type rawItemType = getTypeParameter(genericRepositoryType, GenericRepository.class.getTypeParameters()[0]);
        //noinspection unchecked
        this.modelType = (Class<T>) GenericTypeReflector.erase(rawItemType);
     }
}

你可以避免使用gentyref - 它的实现非常简单,但用这种代码编写代码要容易得多。