从EnumSet <a> to Set<b> when A inherits from B</b></a>转换

时间:2011-06-29 23:52:07

标签: java enums enumset

标题几乎解释了这个问题。我有一个接口方法:

Set<Field> getFieldSet()

我有一个类User看起来像这样

class User {
    enum Fields implements Field {
        USERNAME, PASSWORD;
        ...
    }
    ...
}

现在我想实现User的{​​{1}}方法。天真的方式似乎只是getFieldSet(),但我得到以下错误:

return EnumSet.allOf(Fields.class)

除了手动将EnumSet复制到> Type mismatch: cannot convert from Set<User.Fields> to Set<Field> 之外,还有一种很好的方法吗?

4 个答案:

答案 0 :(得分:6)

您可以返回new HashSet<Field>(EnumSet.allOf(Fields.class));

这样可以避免将Set<User.Fields>类型的值分配给Set<Field>类型的变量。

或者,您的界面可以是Set<? extends Field> getFields()。您可以Set<User.Field>分配给捕获变量。

答案 1 :(得分:4)

使用Collections.unmodifiableSet

return Collections.<Field>unmodifiableSet(EnumSet.allOf(Fields.class));

优点:

  • 没有不安全的转换转换:操作在运行时是类型安全的
  • 返回的集实际上是Set<Field>,而不是Set<? extends Field>
  • 不会复制该集,仅包装
  • 返回的集合无法变异

缺点:

  • 返回的集合无法变异,但无论如何都不会安全。

答案 2 :(得分:1)

这不起作用的原因是Set<Fields>不是Set<Field>的子类型。例如,如果您从方法中返回Set<Fields>,则可能会出现以下情况:

Set<Field> fieldSet = user.getFieldSet(); //Returns an EnumSet<Fields>
fieldSet.add(new Field(){}); //Would compile, but would blow up at runtime, 
                             //because the set can only contain Fields enum 
                             //constants

这里最好的选择是使用不同的set实现(通常是不可修改的集合)来返回值。例如:

Set<Field> getFieldSet() {
    return Collections.unmodifiableSet(EnumSet.allOf(Fields.class));
}

或者,如果你需要这个集合是可变的(通常可能不是一个好主意)

Set<Field> getFieldSet() {
    return new HashSet(EnumSet.allOf(Fields.class));
}

答案 3 :(得分:0)

我认为这是一个很好的解决方案。这不是你想要的,但足够接近

import java.util.EnumSet;
import java.util.Set;

public class User {
    enum Fields implements Field {
        USERNAME,
        PASSWORD;
    }

    Set< ? extends Field> getFieldSet() {
        return EnumSet.allOf(Fields.class);
    }
}