【问题标题】:Java Abstract Class And GenericsJava抽象类和泛型
【发布时间】:2012-11-01 22:55:10
【问题描述】:

我正在尝试修改 AuthenticatedUser 类以存储 AdminRole 的列表。 AuthenticatedUser 是我所有应用程序都使用的类;当用户成功登录时,它会被放入会话中。现在我想向用户会话添加授权角色列表。然而,每个应用程序对AdminRole 类的定义略有不同。例如,我的 DataCenter 应用程序存储在数据库中:

  employee_id
  role_name
  site_name
  receive_email

并非我的所有应用程序都需要 receive_email 字段,或者可能想要扩展自己的方法。我认为这需要一个抽象类。但是 Eclipse 在此 sn-p 中抱怨 Authorized_role_list 设置器上的错误类型。

  DataCenterAdminRoleDAO dcAdminDao = new DataCenterAdminRoleDAO();
  try {
      List<DataCenterAdminRole> authorized_roles = dcAdminDao.getAuthorizedRoleListByBadge(authenticatedUser.getBadge());
      authenticatedUser.setAuthorized_role_list(authorized_roles);

=== Classes

public class AuthenticatedUser extends Employee implements Serializable {   
  private static final long serialVersionUID = 1L;
  private List<AdminRole> authorized_role_list;
  ...
}

public abstract class AdminRole implements Serializable {
  private static final long serialVersionUID = 1L;
  private String role_name; //regular, admin, editor, etc..
  private String site_id;  //company branches
  ...
}

public class DataCenterAdminRole extends AdminRole implements Serializable {

显然,解决方法是在我的数据中心实现中返回AdminRole 列表,但我认为通过扩展抽象类可以传递子类。我错过了什么?

【问题讨论】:

  • 请尝试创建一个 [sscce](短,自包含,正确示例)。我意识到您有编译错误,但您可以将该行注释掉。同时粘贴 Eclipse 报告的实际错误,无需重新表述。

标签: java inheritance abstract-class


【解决方案1】:

如果是 setter 给您带来麻烦,您可以在 authorized_roles_list 上使用带有通配符的下限

private List<? extends AdminRole> authorized_role_list;
....
public setAuthorized_role_list(List<? extends AdminRole> authorized_roles) {
...
}

【讨论】:

    【解决方案2】:

    泛型的行为与 Java 的其他部分不同。不会发生自动转换,所以如果一个方法调用List&lt;List&gt;,你不能给它一个List&lt;ArrayList&gt;。同样,如果你的 setter 调用 List,你不能给它一个 List&lt;? extends AdminRole&gt;,除非你将它定义为 List&lt;? extends AdminRole&gt;。但是,您可以根据需要覆盖 setter 方法以采用 List&lt;DataCenterAdminRole&gt;,或者将您的 List&lt;DataCenterAdminRole&gt; 转换为 List&lt;AdminRole&gt;,或者只是将您的 setter/字段更改为捕获类型 &lt;? extends AdminRole&gt;

    【讨论】:

      【解决方案3】:

      List&lt;Orange&gt; 不是List&lt;Fruit&gt;,即使 Orange 是水果。如果是List&lt;Fruit&gt;,您可以执行以下操作:

      List<Orange> orangeList = new ArrayList<Orange>();
      List<Fruit> fruitList = orangeList;
      fruitList.add(new Apple());
      

      因此它会完全破坏泛型集合的类型安全,因为一个橘子列表会包含一个苹果。 AuthenticatedUser 应该包含 List&lt;? extends AdminRole&gt; 才能执行您正在执行的操作。

      【讨论】:

      • 为了更好地理解您的类比,我在 Eclipse 中对此进行了编码。我在第 2 行遇到错误。 Eclipse 建议将fruitList 的类型更改为List。我想这就是您要指出的,Eclipse 正在阻止我破坏类型安全。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-15
      • 1970-01-01
      相关资源
      最近更新 更多