【问题标题】:How to use class's generic in methods如何在方法中使用类的泛型
【发布时间】:2016-10-20 11:03:39
【问题描述】:

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

我的问题是我不能在方法中使用泛型 E。

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 作为 'find()' 的参数,如下所示,但我收到一个错误,提示 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?

Repository 是一个接口,它也采用通用 E。

我正在使用 Spring 和 Hibernate。

【问题讨论】:

  • 我看不出你的两个版本的findById()有什么区别。
  • 也许这可以帮助stackoverflow.com/questions/3403909/… ...但总的来说...这是工作中的类型擦除。
  • @FlorianAlbrecht 我忘了更改第二个,现在它是对的。
  • @GhostCat 这些解决方案和我的差不多。

标签: java spring hibernate generics


【解决方案1】:

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

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

【讨论】:

  • 不完全正确。您可以获得参数化泛型类的类型参数。这是一个肮脏的黑客,但它有效。 stackoverflow.com/questions/18707582/…stackoverflow.com/questions/9934774/…
  • @Denis 是的...不。只是没有。在这里也无济于事。
  • @FlorianAlbrecht,为什么在这里没有帮助?这些链接显示了如何解决 OP 的问题,而您却说这是不可能的。
  • 伙计们,这些解决方案中没有一个比 OP 已经实施的解决方案更简单。就泛型的用途而言,没有一个更稳定、更“正确”。但是,如果您认为这是废话,请随时对我的回答投反对票。
  • 我认为没有任何OP的使用示例,进一步讨论这个是没有意义的。
【解决方案2】:

我在我的项目中使用完全相同的方法,我在 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 - 它的实现非常简单,但是用它编写这种代码要容易得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-11
    • 2018-01-25
    • 2022-11-07
    • 2011-02-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多