[英]Java generic child instance from abstract class
我有一个抽象类,一些孩子和抽象类的通用DAO。
public abstract class Person { ... }
public class User extends Person { ... }
public class Client extends Person { ... }
public PersonDao <T extends Person> { ... }
我想在PersonDao中创建一个select方法来返回Person类的子对象。
public T select(int id) throws SQLException {
String sql = "SELECT * FROM person WHERE per_id=?";
PreparedStatement ps = con.preparedStatement(sql);
ps.setInt(1, id);
ResultSet rs = ps.executeQuery();
T t = null;
if(rs.next()) {
t = new T(); // Error line
t.setId(rs.getInt("per_id"));
t.setName(rs.getString("per_name"));
}
return t;
}
如何实例化泛型子类并返回子对象?
由于Type Erasure,你无法在Java中执行此操作。 你可以看到这篇文章来解决你的问题。 基本上,您必须提供要获取的类。
由于Java中的类型擦除 ,不允许使用new T()
。 无论如何,仿制药的整个目的是要确保在你的代码在编译时类型安全,和你的数据访问类不保证,因为在数据库中的条目可以对应到任何一个User
或Client
。 换句话说,SQL语句和子类之间没有映射(请注意,这通常由ORM框架(如Hibernate)处理)。 解决方案是在代码中提供准确指定结果类型的其他参数。 通常, Person
每个子类都应该有自己的DAO实现(即UserDao
和ClientDao
),而PersonDao
方法应该是抽象的,例如:
public abstract class PersonDao<T extends Person> {
abstract T select(int id);
...
}
public class UserDao extends PersonDao<User> {
public User select(int id) throws SQLException {
// Assuming there is a type column to differentiate between types of Person
String sql = "SELECT * FROM person WHERE per_id=? and type=?";
PreparedStatement ps = con.preparedStatement(sql);
ps.setInt(1, id);
ps.setString(2, User.class.getName());
ResultSet rs = ps.executeQuery();
User user = null;
if(rs.next()) {
user = new User();
user.setId(rs.getInt("per_id"));
user.setName(rs.getString("per_name"));
}
return user;
}
...
}
如果代码可以在父PersonDao
共享,因为它在两个实现中是相同的(在这种情况下,我没有看到首先拥有PersonDao
泛型的点,你可以让它返回一个Person
而不是T
),然后你可以在构造函数中传递类:
public class PersonDao<T extends Person> {
private Class<T> type;
public PersonDao(Class<T> type) {
this.type = type;
}
public T select(int id) {
String sql = "SELECT * FROM person WHERE per_id=? and type=?";
PreparedStatement ps = con.preparedStatement(sql);
ps.setInt(1, id);
ps.setString(2, type.getName());
ResultSet rs = ps.executeQuery();
T t = null;
if(rs.next()) {
t = type.newInstance();
t.setId(rs.getInt("per_id"));
t.setName(rs.getString("per_name"));
}
return t;
}
...
}
附注:您的代码段未显示如何关闭JDBC资源。 确保在您的真实代码中执行此操作。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.