扩展通用实现者类

时间:2016-06-10 10:16:48

标签: java generics

我有一个DAO对象,我通常用实体类名扩展,如下所示:

public class DAO<T> {

    private final Class<T> clazz;
    public DAO(Class<T> clazz {
        this.clazz = clazz;
    }
}

public class EntityDAO extends DAO<Entity> {

    public EntityDAO() {
        super(Entity.class);
    }
}

但是,我有一些抽象的实体,我想创建一个抽象的DAO,稍后可以在具体的类中实现:

public class DAO<T> {

    private final Class<T> clazz;
    public DAO(Class<T> clazz {
        this.clazz = clazz;
    }
}

public abstract class AbstractEntityDAO extends DAO<T extends AbstractEntity> {

    public AbstractEntityDAO () {
        super(AbstractEntity.class);
    }
}

public abstract class EntityDAO extends AbstractEntityDAO <Entity> {

    public EntityDAO() {
        super(Entity.class);
    }
}

但这不起作用,因为AbstractEntityDAO抱怨一个意外的界限,它无法解决T.是否可以这样做?如果是这样,它是如何写的?

这是使用Java 1.7

1 个答案:

答案 0 :(得分:2)

将通用类型定义放在AbstractEntityDAO

public abstract class AbstractEntityDAO<T extends AbstractEntity> extends DAO<T> {
...
}

使用当前代码AbstractEntityDAO <Entity>应该让编译器抱怨AbstractEntityDAO没有通用参数。

此外,您的AbstractEntityDAO()构造函数也需要接受Class参数。但是,如果始终使用具有类型的类的实例,则根本不需要将该类作为参数传递。如果有T中的具体定义,则使用反射类可以确定EntityDAO的类型。内置的反射实用程序没有提供简单的方法来执行此操作,但幸运的是,您只需要一些额外的代码来提供一个,请查看此处:http://www.artima.com/weblogs/viewpost.jsp?thread=208860

这基本上也是我们正在做的事情。这是我们方法的粗略概述:

abstract class BaseDAO<T> {
  Class<?> entityClass;

  BaseDAO() {
    //this is based on the link I posted above but basically uses the actual concrete class 
    //(subclass determined by getClass() ) to extract the generic types and 
    //since we only have one we get the first one from the returned list
    entityClass = ReflectionHelper.getTypes(getClass(), BaseDAO.class).get(0); 
  }

  public T getEntity(Object id) { 
  ...
  }
}

abstract class TranslatableDAO<T extends TranslatableEntity> extends BaseDAO<T> {
...
}

//Users are not translatable
class UserDAO extends BaseDAO<User> {
...
}

//Products are translatable, i.e. Product extends TranslatableEntity
class ProductDAO extends TranslatableDAO<Product> {
...
}