我可以这样做通用的东西吗?

Paq*_*oft 4 java generics dao

看起来我遗漏了Java Generics的东西,因为我认为这很简单,在我看来无法完成.也许你可以帮忙......

这就是场景:我正在使用简单的CRUD操作编写一个通用的抽象DAO,因此我的应用程序的每个特定DAO都可以免费使用它:

public abstract DefaultDAO<T,V> {
  private EntityManager manager;

  public BaseDAO(EntityManager em) {
    this.manager = em;
  }

  public void create(T entity) {
    manager.persist(entity);
  }

  // You know the others...

  public T read(V pk) {
    // Now, here is the problem. 
    // EntityManager signature is: public <T> T find(Class<T> entityClass, Object primaryKey);
    // So I must provide the type of the object this method will be returning and 
    // the primary key.
    // resulting object will be T typed and pk type is V type (although is not needed to type it since the method expects an Object)
    // So... I expected to be allowed to do something like this
    return manager.find(T, pk); // But it's not allowed to use T here. T is not an instance
  }   
}
Run Code Online (Sandbox Code Playgroud)

现在我要去实现一个特定的DAO:

public PersonDAO extends DefaultDAO<PersonEntity, Long> {
  public PersonDAO(EntityManager em) {
    super(em);
  }
  // CRUD methods are inherited
}
Run Code Online (Sandbox Code Playgroud)

我的DAO的客户端代码将是:

EntityManager manager = ...
PersonDAO dao = new PersonDAO(manager);
Long pk = .....
PersonEntity person = dao.find(pk); // DAO would return a PersonEntity
Run Code Online (Sandbox Code Playgroud)

当客户端执行代码时,BaseDAO知道它必须返回的实体类型以及该实体的主键类型,因为我在特定的dao上设置它,但我不知道如何正确编写read()方法.

希望你能帮忙.非常感谢!

Jon*_*eet 14

您正在尝试使用类型参数,就好像它是正常表达式一样.你不能这样做.在其他语言中,您可以在执行时获取类型参数的类,但由于类型擦除,您无法使用Java .

在这种情况下,您需要Class<T>在执行时传递- 例如传递给构造函数:

public abstract class DefaultDAO<T, V> {

    private EntityManager manager;
    private final Class<T> clazz;

    public DefaultDAO(EntityManager em, Class<T> clazz) {
        this.manager = em;
        this.clazz = clazz;
    }

    public T read(V pk) {
        return manager.find(clazz, pk);
    }
}
Run Code Online (Sandbox Code Playgroud)

  • @BalusC:我要等到确认之后才开始在答案中谈论它.Java泛型很混乱,没有将未来可能的功能混合到一起:) (4认同)
  • 这是一个由Sun本身开始的约定 - 如果你看一下JDK文档中带有`Class`类型参数的方法(例如`类`本身的那些),你会发现它们使用`clazz`作为参数名. (2认同)