java泛型构造函数

java泛型构造函数,java,generics,constructor,Java,Generics,Constructor,我目前有以下代码从数据库检索数据,然后创建一个用户。这段代码在我的许多类中都被用来创建其他对象,如新闻,评论等 它使用apachecommons dbutils final ResultSetHandler<User> handler = new ResultSetHandler<User>() { @Override public User handle(ResultSet rs) throws SQLException

我目前有以下代码从数据库检索数据,然后创建一个
用户
。这段代码在我的许多类中都被用来创建其他对象,如
新闻
评论

它使用apachecommons dbutils

final ResultSetHandler<User> handler = new ResultSetHandler<User>() {

            @Override
            public User handle(ResultSet rs) throws SQLException {

                User user = null;
                if (rs.next()) {
                    user = new User();
                    user.setId(rs.getInt("id"));
                    user.setUsername(rs.getString("username"));
                    user.setPassword(rs.getString("password"));
                }
                return user;
            }
        };

        final User user = run.query(
                "SELECT id, username, password FROM users WHERE username = ? AND active = 2 LIMIT 1;", handler,
                username);
我不知道你是否能理解,但我希望如此,问我你是否想要更多的细节或更好的解释

编辑

我想我可以使用AbstractClass,而不是泛型类型,所有不同的对象都可以扩展它,但我似乎无法编写抽象构造函数。我是否必须创建一个静态方法来返回对象的实例,如:

public abstract class DatabaseEntity {
    public static abstract DatabaseEntity create(ResultSet rs);//even this doesn't work...
}

我认为用Java不可能做到这一点。不能在泛型中创建
T
的实例。java中的泛型不是C++中的模板,它们只是围绕<代码>对象< /> >的语法糖,它删除了casts并引发编译时警告。 没有像C#中那样的方法来约束
T
,使其必须具有构造函数


如果确实有必要这样做,最好的办法是使用反射来解析适当的类,但即使这样,您也会遇到问题,因为在调用方法时您无法知道T的运行时类-这些信息从java字节码中剥离出来。因此,您只需将类传递给方法,以便对其使用反射。无论如何,我不太确定这是一个好的设计思想。

您可以这样做(通过传递要创建的对象的类,并使用反射调用其构造函数),但我会发现POJO依赖于JDBC,并且不仅知道它如何存储在数据库中,这是一个糟糕的设计,但是在用于加载它的查询中使用了哪些别名

简而言之,用户POJO构造函数不负责处理外部未知查询的结果集

您可以设计一个AbstractSingleEntityHandler超类,它只需要

if (rs.next()) {

块,并将实际实体创建委托给一个抽象方法,但您不会获得太多。

可能,是吗?但这是个坏主意

你可以做:

class ResultSetHandler<T> {
  ResultSetHandler<T>(Class<T> clazz) {
    this.clazz = clazz;
  }

  public T handle(ResultSet rs) throws SQLException {
    T object = null;
    if (rs.next()) {
      object = clazz.getConstructor(ResultSet.class).newInstance(rs)
    }
    return object;
  }
}

为什么您需要在构造函数中传递
T type
?使用反射,您可以使用结果集+1调用类构造函数,因为它比我快,而且写的正是我想要的;)我之所以尝试这样做,是因为您在上面的第一个代码块中看到的处理程序体在任何对象的每个查询中都会重复。我认为最好确保来自db的对象知道如何从查询结果构造自己,
query
方法将直接返回该对象。不依赖于任何环境的对象,如JEE容器或JDBCAPI。您必须在某个地方拥有此代码:处理程序中或构造函数中。最合适的方法是将其放置在处理程序中,而不是构造函数中。我不明白为什么把它放在构造器中可以避免任何重复。他可以像JB Nizet所说的那样通过反射来完成。绝对可能。您只需要引用
。是的,带有反射。您仍然需要将实际的类传递给该方法。如果类信息在运行时出现,你就不能像你想的那样使用T.class了。+1用于提供与我相同的答案,但有很好的代码示例。你说将数据库与域混合不是一个好主意,我明白了,但是你会如何从查询结果中构建这些对象?我使用的是MVC体系结构,因此,我的模型是用于持久性的,并且知道如何在数据库中保存和更新自身,但是我使用一个实用工具来对数据库执行查询。也许使用DAO?是的,DAO层就是你最终要做的。本质上,一个知道如何在两者之间转换的层。
class ResultSetHandler<T> {
  ResultSetHandler<T>(Class<T> clazz) {
    this.clazz = clazz;
  }

  public T handle(ResultSet rs) throws SQLException {
    T object = null;
    if (rs.next()) {
      object = clazz.getConstructor(ResultSet.class).newInstance(rs)
    }
    return object;
  }
}
abstract class ResultSetHandler<T> {

  protected abstract T create(ResultSet rs);

  public T handle(ResultSet rs) throws SQLException {
    T object = null;
    if (rs.next()) {
      object = create(rs);
    }
    return object;
  }
}
h = new ResultSetHandler<Person>() {
  protected Person create(ResultSet rs) {
    return new Person(rs.getString("name"));
  }
}