繁体   English   中英

来自抽象类的Java通用子实例

[英]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() 无论如何,仿制药的整个目的是要确保在你的代码在编译时类型安全,和你的数据访问类不保证,因为在数据库中的条目可以对应到任何一个UserClient 换句话说,SQL语句和子类之间没有映射(请注意,这通常由ORM框架(如Hibernate)处理)。 解决方案是在代码中提供准确指定结果类型的其他参数。 通常, Person每个子类都应该有自己的DAO实现(即UserDaoClientDao ),而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.

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