【问题标题】:GenericDAO and ClassCastGenericDAO 和 ClassCast
【发布时间】:2016-01-08 21:20:14
【问题描述】:

我在下面的代码中编写了以下 GenericDAO

abstract public class DAO <T extends AbstractBusinessObject> {

// CRUD: create, read, update, delete 

public abstract T create(Class<T> abObj);

public abstract T read();

public abstract void update(T abObj);

public abstract void delete(T abObj);
}

我还通过命令模式实现了一些命令,这些命令与扩展 GenericDAO 的 DAOInMemory 交互,以执行“注册用户名密码”等任务。

public class RegisterUserCommand extends AbstractCommand {

public RegisterUserCommand() {
    ...
}

...
@Override
public void execute(String[] cmdArgs) {

        // class cast here
        User userObject = (User) daoInstance.create(User.class);

        //why doesn't this work?
        //User userObject = daoInstance.create(User.class); 

    }
}}

我不明白为什么当DAOInMemory 已经在create-method 中转换操作时,我必须转换daoInstance.create(User.class) 的结果?

public class DAOInMemory<T extends AbstractBusinessObject> extends DAO<T> {
    ...

public DAOInMemory() {
    ...


public T create(Class<T> abstractObjectType) {

    IDGenerator IDGenerator = IDGenerator.getInstance();

    if (User.class.isAssignableFrom(abstractObjectType)) {
        BigInteger id = IDGenerator.getID();
        User user = new User(id);
        return (T) user;
    }

您能解释一下 Java 的这种行为吗?

编辑:我忘了加上public class User extends AbstractBusinessObject

【问题讨论】:

  • 我猜你来自.NET - 但在java 编码约定中,变量名以小写字母开头(除非它是一个常量,那么应该使用所有大写字母)
  • 你是如何定义 daoInstance 的?
  • 我仍然不确定您要做什么...您使用了太多泛型 :) 为什么要使用泛型类 DAOInMemory 然后返回特定类型?我建议您创建一个 UserDAO 类,而不是实现 DAO&lt;User&gt; 或扩展 DAOInMemory&lt;User&gt; 类以进行实际实现。
  • @IanMc 好吧,实例化只是DAO daoInstance = new DAOInMemory()在注册所有命令的类的顶部RegisterUserCommandRegisterUserCommand 的构造函数是 public RegisterUserCommand(DAO daoInstance) { super(daoInstance); }
  • 有趣的是(展示了泛型的强大功能),您不需要告诉我们 User 扩展了 AbstractBusinessObject。使用:abstract public class DAO 强制!

标签: java generics dao


【解决方案1】:

在实例化 DAO 类时必须避免使用泛型。

示例 1:(需要演员表):

DAO dao = new DAOInMemory();
User user = (User) dao.create(User.class);

示例 2:(不需要演员表):

DAO<User> dao = new DAOInMemory<User>();
User user = dao.create(User.class);

【讨论】:

  • 那么,第一个变种更可取吗?
  • 不,应该鼓励您使用变体 #2。示例一是原始类型,它会丢失泛型的值(因此需要强制转换)并且会出现运行时错误。泛型的好处是类不匹配错误在编译时被捕获,优于运行时异常。
  • 非常感谢您的解释。
【解决方案2】:

您需要投射,因为T 不一定是User

事实上,这段代码可能会导致类转换异常,因为你的泛型定义是T extends AbstractBusinessObject,这并不意味着User

【讨论】:

  • 实际上,User extends AbstractBusinessObject 在我的代码中
  • 仍然 - 想想一个扫描仪,其中 T 是 AbstractBusinessObject 的其他子类,而不是用户。在您的 create 方法中将用户强制转换为它会导致类强制转换异常
猜你喜欢
  • 2012-07-24
  • 2012-01-24
  • 1970-01-01
  • 2019-08-25
  • 2013-06-27
  • 2015-10-09
  • 1970-01-01
  • 1970-01-01
  • 2012-06-20
相关资源
最近更新 更多