Java 如何使用class';方法中的泛型

Java 如何使用class';方法中的泛型,java,spring,hibernate,generics,Java,Spring,Hibernate,Generics,我有一个抽象类,它采用泛型,在这个类中有一些方法 public abstract class AbstractRepository<E> implements Repository<E> { final Class<E> typeParameterClass; public AbstractRepository(Class<E> typeParameterClass) { this.typeParameterCl

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

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-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;
    }
为了解决这个问题,我使用typeParameterClass

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

现在的方式示例:

@Repository
public class UserRepository extends AbstractRepository<User> {

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

    ...
}
@存储库
公共类UserRepository扩展了AbstractRepository{
公共用户存储库(){
super(User.class);
}
...
}
那么,有没有一种方法可以在方法内部使用泛型E

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


我将Spring与Hibernate结合使用。Java在运行时不存在泛型类型信息,因此无法确定用于具体实例的类型参数


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

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


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

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

导入静态com.googlecode.gentyref.generictyperelector.getExactSuperType;
导入静态com.googlecode.gentyref.GenericTypeReflector.getTypeParameter;
公共抽象类GenericRepository{
受保护的通用存储库(){
类型genericRepositoryType=getExactSuperType(getClass(),GenericRepository.class);
类型rawItemType=getTypeParameter(genericRepositoryType,GenericRepository.class.getTypeParameters()[0]);
//未检查
this.modelType=(类)GenericTypeReflector.erase(rawItemType);
}
}

您可以避免使用gentyref—它的实现非常简单,但是使用它编写此类代码要容易得多。

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

导入静态com.googlecode.gentyref.generictyperelector.getExactSuperType;
导入静态com.googlecode.gentyref.GenericTypeReflector.getTypeParameter;
公共抽象类GenericRepository{
受保护的通用存储库(){
类型genericRepositoryType=getExactSuperType(getClass(),GenericRepository.class);
类型rawItemType=getTypeParameter(genericRepositoryType,GenericRepository.class.getTypeParameters()[0]);
//未检查
this.modelType=(类)GenericTypeReflector.erase(rawItemType);
}
}

您可以避免使用gentyref—它的实现非常简单,但是使用它编写此类代码要容易得多。

我看不出您的两个版本的
findById()
之间有什么区别。也许这可以帮助您。。。但总的来说。。。这是工作中的类型擦除。@FlorianAlbrecht我忘记更改第二个,现在它是正确的。@GhostCat这些解决方案与我的解决方案几乎相同。我发现您的两个版本的
findById()
。也许这能帮上忙。。。但总的来说。。。这是工作中的类型擦除。@FlorianAlbrecht我忘了更改第二个,现在是正确的。@GhostCat这些解决方案与我的几乎相同。不完全正确。您可以获取参数化泛型类的类型参数。这是一个肮脏的黑客,但它的工作。还有@Denis是的。。。不,只是不。这在这里没有帮助。@FlorianAlbrecht,为什么在这里没有帮助?这些链接展示了如何解决OP的问题,而你却在说这是不可能的。伙计们,这些解决方案中没有一个比OP已经实现的更简单。就泛型的用途而言,没有一个更稳定、更“正确”。但是,如果你认为我的答案是垃圾的话,请随意否决我的答案。我认为没有OP的任何用法示例,进一步讨论这个问题是没有意义的。不完全正确。您可以获取参数化泛型类的类型参数。这是一个肮脏的黑客,但它的工作。还有@Denis是的。。。不,只是不。这在这里没有帮助。@FlorianAlbrecht,为什么在这里没有帮助?这些链接展示了如何解决OP的问题,而你却在说这是不可能的。伙计们,这些解决方案中没有一个比OP已经实现的更简单。就泛型的用途而言,没有一个更稳定、更“正确”。但是,如果你认为我的答案是垃圾,请随意否决我的答案。我认为,如果没有OP的任何用法示例,进一步讨论这个问题是没有意义的。
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);
     }
}