除了某些参数类型之外,我有几个具有相同方法的类:
interface ICls<T> {
void doSomething(String key, T value);
Map<String, T> getSomething();
}
class ClsA implements ICls<Boolean> {
@Override public void doSomething(String key, Boolean value) { }
@Override public Map<String, Boolean> getSomething() { return Map.of(); }
}
class ClsB implements ICls<String> {
@Override public void doSomething(String key, String value) {}
@Override public Map<String, String> getSomething() { return Map.of(); }
}
Run Code Online (Sandbox Code Playgroud)
现在我试图有一个主类来存储这些类对象的混合列表,并且对于这些实例中的每一个,在它的两个方法之间传递信息:
class Main {
List<ICls<?>> list = List.of(
new ClsA(),
new ClsB()
);
void run() {
list.forEach(cls -> {
Map<String, ?> data = cls.getSomething();
data.keySet().forEach(key -> cls.doSomething(key, data.get(key)));
});
}
Run Code Online (Sandbox Code Playgroud)
该List<ICls<?>>和Map<String, ?>语句都OK。但是,会map.get(key)引发 IDE 错误:
'doSomething(<String, capture<?>>) in '...ICls' cannot be applied to 'String, capture<?>'
Run Code Online (Sandbox Code Playgroud)
将鼠标光标悬停在违规语句上会显示:
Required type: capture of ?
Provided: capture of ?
Run Code Online (Sandbox Code Playgroud)
假设我不能/不想将泛型类型更改T为Object,并且也不想更改架构,我该怎么做才能使此处的代码编译?
我已经尝试更改签名,doSomething以便它接受整个Map<String, T>并像这样调用它,但也没有运气:
cls.doSomething(cls.getSomething());
Run Code Online (Sandbox Code Playgroud)
这为我编译:
import java.util.List;
import java.util.Map;
public class Comparison {
interface ICls<T> {
void doSomething(String key, T value);
Map<String, T> getSomething();
}
static class ClsA implements ICls<Boolean> {
public void doSomething(String key, Boolean value) {}
public Map<String, Boolean> getSomething() { return null; }
}
static class ClsB implements ICls<String> {
public void doSomething(String key, String value) {}
public Map<String, String> getSomething() { return null; }
}
static class Main {
List<ICls<?>> list = List.of(
new ClsA(),
new ClsB()
);
void run() {
list.forEach(cls -> {
doIt(cls);
});
}
<T> void doIt(ICls<T> cls) {
Map<String, T> data = cls.getSomething();
data.keySet().forEach(key -> cls.doSomething(key, data.get(key)));
}
}
}
Run Code Online (Sandbox Code Playgroud)
它明确了map和cls之间的关系。
在原来的背景下,因为列表的类型的ICL <?>我们不能拿到关系,但一旦我们得到一个单一的ICL我们可以引入一个类型变量T,它允许我们表达之间的关系getSomething和doSomething。
| 归档时间: |
|
| 查看次数: |
56 次 |
| 最近记录: |