简体   繁体   English

java通用构造函数

[英]java generic constructors

I currently have the following code that retrieves data from the database and then create a User . 我目前有以下代码从数据库中检索数据,然后创建一个User This code is used in many of my classe to create other objects such as News , Comments etc... 我的许多classe使用此代码来创建其他对象,如NewsComments等...

It uses apache commons dbutils. 它使用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);

Would it be possible to wrap the QueryRunner in a generic class and override the query method so the handler instanciate the generic T with the ResultSet. 是否可以将QueryRunner包装在泛型类中并覆盖查询方法,以便处理程序使用ResultSet实现泛型T I would make sure any T type would ahve a constructor accepting a ResultSet . 我会确保任何T类型都是接受ResultSet的构造函数。

Like so : 像这样:

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

I don't know if you'll understand, but I hope so, ask me if you want more details or a better explanation. 我不知道你是否理解,但我希望如此,请问我是否需要更多细节或更好的解释。

EDIT 编辑

I thought I could use a AbstractClass instead of the generic type that all of the differents objects would extends but it seems like I can't write an abstract constructor. 我以为我可以使用AbstractClass而不是所有不同对象都会扩展的泛型类型,但似乎我不能编写一个抽象构造函数。 Will I have to make a static method that return an instance of the object like: 我是否必须创建一个返回对象实例的静态方法,如:

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

Possible, yes? 可能,是吗? But its a bad idea. 但这是一个坏主意。

You could do: 你可以这样做:

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

Mixing domain and database is a bad idea, however. 但是,混合域和数据库是一个坏主意。 What would be better, however, would be to define an abtract method that creates the object based on the resultset: 然而,更好的方法是定义一个基于结果集创建对象的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;
  }
}

Then, in your implementing class, you only need to provide a create() method instead of handling the result set yourself, for example: 然后,在您的实现类中,您只需要提供create()方法而不是自己处理结果集,例如:

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

You could do something like that (by passing the class of the object to create, and use reflection to call its constructor), but I would find it bad design to have the POJO dependent on JDBC, and knowing not only how it's stored in database, but also which aliases have been used in the query used to load it. 你可以做类似的事情(通过传递对象的类来创建,并使用反射来调用它的构造函数),但我会发现让POJO依赖于JDBC并且不仅知道它如何存储在数据库中也是不好的设计,以及在用于加载它的查询中使用了哪些别名。

In short, it's not the responsibility of the User POJO constructor to handle a result set of an external, unknown query. 简而言之,用户POJO构造函数不负责处理外部未知查询的结果集。

You could design an AbstractSingleEntityHandler superclass which would just have the 你可以设计一个AbstractSingleEntityHandler超类,它只有

if (rs.next()) {

block, and would delegate the actual entity creation to an abstract method, but you wouldn't gain much. 阻止,并将实际的实体创建委托给抽象方法,但你不会获得太多。

I do not think it is possible to do this in Java. 我认为在Java中不可能这样做。 You cannot create an instance of T in a generic. 您无法在泛型中创建T的实例。 Generics in java are not really templates as in C++, they are only syntax sugar around an object which removes the casts and induces compile time warnings. java中的泛型不是像C ++中那样的模板,它们只是一个object语法糖,它会删除强制转换并引发编译时警告。

There is no way like in C# to constrain T so that it must have a constructor. 在C#中没有办法约束T ,因此必须有一个构造函数。

Your best bet if this is really neccessary is to resolve the appropriate class using reflection, but even then you will run into problem since you cannot know the runtime class of T as the method is being invoked - this information is stripped from the java bytecode. 如果真的有必要,最好的办法是使用反射解析相应的类,但即使这样你也会遇到问题,因为在调用方法时你无法知道T的运行时类 - 这个信息是从java字节码中删除的。 So you are left with passing the class to the method in order to use reflection on it. 因此,您可以将类传递给方法,以便对其进行反射。 And I'm not too sure this is a good design idea anyway. 而且我不太确定这是一个好的设计理念。

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

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