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

Java 如何捕获和传播通配符类型参数?,java,generics,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) { }

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

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(); }
}
将鼠标光标悬停在有问题的语句上会显示:

Required type: capture of ?
Provided: capture of ?
假设我不能/不想将泛型类型
t
更改为
Object
,并且也不想更改体系结构,那么我可以做些什么来编译这里的代码

我尝试更改了
doSomething
的签名,这样它就可以接受整个
Map
并像这样调用它,但也没有运气:

cls.doSomething(cls.getSomething());
这为我汇编了:

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)));
        }
    }
}
import java.util.List;
导入java.util.Map;
公共阶级比较{
接口ICL{
void doSomething(字符串键,T值);
映射getSomething();
}
静态类ClsA实现ICls{
公共void doSomething(字符串键,布尔值){}
公共映射getSomething(){return null;}
}
静态类ClsB实现ICls{
公共void doSomething(字符串键,字符串值){}
公共映射getSomething(){return null;}
}
静态类主{
列表我们不能得到这种关系,但一旦我们得到一个ICL,我们就可以引入一个类型变量
t
,它允许我们表达
getSomething
doSomething
之间的关系,这为我编译:

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)));
        }
    }
}
import java.util.List;
导入java.util.Map;
公共阶级比较{
接口ICL{
void doSomething(字符串键,T值);
映射getSomething();
}
静态类ClsA实现ICls{
公共void doSomething(字符串键,布尔值){}
公共映射getSomething(){return null;}
}
静态类ClsB实现ICls{
公共void doSomething(字符串键,字符串值){}
公共映射getSomething(){return null;}
}
静态类主{

列表我们不能得到这种关系,但是一旦我们得到一个ICL,我们就可以引入一个类型变量
t
,它允许我们表达
getSomething
doSomething

之间的关系。我很好奇我们是否能让Java相信这些类型在这里是可以的。您所描述的内容肯定很有趣逻辑和数学意义,但我不确定Java的类型系统是否足够聪明。这可能是“通过
Object
转换并绕过类型检查器”,但我会听从更了解Java复杂性的人来肯定地说。@azurefrog打字错误!我的错。刚刚在IDE中更正并检查了整个代码。:@SilvioMayolo谢谢!我不愿意这样做。:(否则我宁愿一开始就有一个
映射
。这样会使代码更简单,尽管每次我都必须在每个类中将
对象
转换为适当的类型:(有意思。我很好奇我们是否能让Java相信这里的类型是正确的。您所描述的当然有逻辑和数学上的意义,但我不确定Java的类型系统是否足够聪明。这可能是“通过
对象转换
并绕过类型检查器”的情况。”,但我会听从更了解Java复杂性的人来肯定地说。@azurefrog打字错误!我的错。刚刚在IDE中更正并检查了整个代码。:@SilvioMayolo谢谢!我不愿意这样做。:(否则我宁愿一开始就有一个
映射
。这样会使代码更简单,尽管每次我都必须在每个类中将
对象
转换为适当的类型:(Wowww!!!是的,它确实可以很好地编译!顺便说一句,我删除了
静态
修饰符,它仍然可以很好地编译。你能解释一下为什么你的代码可以工作而我的代码不能工作吗?我认为
无法解析那里的类型,这就是为什么你需要使用t,帮助编译器更多地理解类型。为此,你必须使用ext将该部分提取到另一个方法中。我只需要静态,因为我正在将所有内容包装到一个外部类中。Wowww!!!是的,它确实可以编译!顺便说一句,我删除了
静态
修饰符,它仍然可以编译。你能详细说明为什么你的代码可以工作而我的代码不能工作吗?我认为
无法解析那里的类型,这就是你的原因需要使用T,帮助编译器更多地理解类型。为此,您必须将该部分提取到另一个方法。我只需要静态,因为我正在将所有内容包装到外部类中。
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)));
        }
    }
}