从Set <someenum>转换为Set <! - ?扩展SomeInterface - >当SomeEnum实现SomeInterface </someenum>时

时间:2014-04-08 10:34:56

标签: java generics enums

我有一个接口和一个枚举如下:

public interface SomeInterface {
    ......
}

public enum SomeEnum implements SomeInterface {
    ......
}

public class SomeClass {
    public void someMethod(Set<SomeInterface> s) {
        ...
    }
}

现在要调用someMethod(Set<SomeInterface> s)我创建一个包含所有元素的枚举集,所以我做了以下事情:

Set<? extends SomeInterface> choosen = EnumSet.allOf(SomeEnum.class);
SomeClass obj = new SomeClass();
obj.someMethod(choosen)

我得到编译时错误:

错误:类SomeClass中的someMethod方法无法应用于给定类型;

required: Set<SomeInterface>
found: Set<CAP#1>

原因:实际参数Set<CAP#1>无法通过方法调用转换转换为Set<SomeInterface> 其中CAP#1是一个新的类型变量: CAP#1扩展了SomeInterface的捕获?扩展SomeInterface

IMP:我知道错误可以由changing the method解析为someMethod(Set<? extends SomeInterface> s),但我无法更改someMethod的签名

3 个答案:

答案 0 :(得分:1)

将您的设置转换为Set<?>,然后转换为您想要的Set<Whatever>。这应该可以解决您的问题......

答案 1 :(得分:0)

获得实现我想要的另一种方式:

Set<SomeInterface> choosen = new HashSet<SomeInterface>(EnumSet.allOf(SomeEnum.class));
someMethod(choosen);

与麦克道尔在copyUp()方法中提到的相似。

答案 2 :(得分:0)

投射和忽略警告显然不是类型安全的。 (在这种特殊情况下可能是安全的,但无论如何我都不会推荐它。)

但最合适的解决方案还取决于someMethodSet<SomeInterface>的关系。如果从指定的集合中读取,那么您可以在集合上传递不可修改的视图

Set<? extends SomeInterface> set = ...
Set<SomeInterface> viewOnSet = Collections.unmodifiableSet(set);
someMethod(viewOnSet);

这是有效的,因为unmodifiableSet视图允许返回的视图更具体:无法向此集添加新元素,因此它是类型安全的。

但是,如果someMethod要修改集合,那么您可以使用已经提到的方法,即创建具有所需类型的集合的副本:

Set<? extends SomeInterface> set = ...
Set<SomeInterface> newSet = new LinkedHashSet<SomeInterface>(set);
someMethod(newSet);