我有一个接口和一个枚举如下:
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
的签名
答案 0 :(得分:1)
将您的设置转换为Set<?>
,然后转换为您想要的Set<Whatever>
。这应该可以解决您的问题......
答案 1 :(得分:0)
获得实现我想要的另一种方式:
Set<SomeInterface> choosen = new HashSet<SomeInterface>(EnumSet.allOf(SomeEnum.class));
someMethod(choosen);
与麦克道尔在copyUp()
方法中提到的相似。
答案 2 :(得分:0)
投射和忽略警告显然不是类型安全的。 (在这种特殊情况下可能是安全的,但无论如何我都不会推荐它。)
但最合适的解决方案还取决于someMethod
与Set<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);