繁体   English   中英

java通用构造函数

[英]java generic constructors

我目前有以下代码从数据库中检索数据,然后创建一个User 我的许多classe使用此代码来创建其他对象,如NewsComments等...

它使用apache commons 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);

是否可以将QueryRunner包装在泛型类中并覆盖查询方法,以便处理程序使用ResultSet实现泛型T 我会确保任何T类型都是接受ResultSet的构造函数。

像这样:

        public class QueryExecuter<T> extends QueryRunner {
    private ResultSetHandler<T> _handler;

    public QueryExecuter(){//The T type was for testing haha
        super();
        handler = new ResultSetHandler<T>() {

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

                T object = null;
                if (rs.next()) {
                    object = new T(rs);
                }
                return object;
            }
        };
    }
}

我不知道你是否理解,但我希望如此,请问我是否需要更多细节或更好的解释。

编辑

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

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

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

你可以这样做:

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;
  }
}

但是,混合域和数据库是一个坏主意。 然而,更好的方法是定义一个基于结果集创建对象的abtract方法:

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;
  }
}

然后,在您的实现类中,您只需要提供create()方法而不是自己处理结果集,例如:

h = new ResultSetHandler<Person>() {
  protected Person create(ResultSet rs) {
    return new Person(rs.getString("name"));
  }
}

你可以做类似的事情(通过传递对象的类来创建,并使用反射来调用它的构造函数),但我会发现让POJO依赖于JDBC并且不仅知道它如何存储在数据库中也是不好的设计,以及在用于加载它的查询中使用了哪些别名。

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

你可以设计一个AbstractSingleEntityHandler超类,它只有

if (rs.next()) {

阻止,并将实际的实体创建委托给抽象方法,但你不会获得太多。

我认为在Java中不可能这样做。 您无法在泛型中创建T的实例。 java中的泛型不是像C ++中那样的模板,它们只是一个object语法糖,它会删除强制转换并引发编译时警告。

在C#中没有办法约束T ,因此必须有一个构造函数。

如果真的有必要,最好的办法是使用反射解析相应的类,但即使这样你也会遇到问题,因为在调用方法时你无法知道T的运行时类 - 这个信息是从java字节码中删除的。 因此,您可以将类传递给方法,以便对其进行反射。 而且我不太确定这是一个好的设计理念。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM