如何捕获和传播通配符类型参数?

Awe*_*SIM 1 java generics

除了某些参数类型之外,我有几个具有相同方法的类:

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)

假设我不能/不想将泛型类型更改TObject,并且也不想更改架构,我该怎么做才能使此处的代码编译?

我已经尝试更改签名,doSomething以便它接受整个Map<String, T>并像这样调用它,但也没有运气:

cls.doSomething(cls.getSomething());
Run Code Online (Sandbox Code Playgroud)

tgd*_*ies 5

这为我编译:

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,它允许我们表达之间的关系getSomethingdoSomething