简体   繁体   English

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

[英]How to capture and propagate a wildcard type argument?

I have a couple of classes having identical methods, except with respect to certain parameter types:我有几个具有相同方法的类,除了某些参数类型:

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(); }
}

Now I'm trying to have a main class that stores a mixed list of these class objects and for each of these instances, passes info between its two methods:现在我正在尝试拥有一个主要的 class 存储这些 class 对象的混合列表,并且对于这些实例中的每一个,在其两种方法之间传递信息:

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)));
        });
    }

The List<ICls<?>> and Map<String, ?> statements are OK. List<ICls<?>>Map<String, ?>语句都可以。 However, the map.get(key) throws an IDE error:但是, map.get(key)会引发 IDE 错误:

'doSomething(<String, capture<?>>) in '...ICls' cannot be applied to 'String, capture<?>'

Hovering the mouse cursor over the offending statement shows:将鼠标 cursor 悬停在违规语句上显示:

Required type: capture of ?
Provided: capture of ?

Assuming that I can't/don't want to change the generic type T to Object , and don't want to change the architecture either, what can I do to make the code here compile?假设我不能/不想将通用类型T更改为Object ,并且也不想更改架构,我该怎么做才能使这里的代码编译?

I've tried changing the signature of doSomething so that it accepts the entire Map<String, T> and call it like so, with no luck either:我尝试更改doSomething的签名,以便它接受整个Map<String, T>并像这样调用它,但也没有运气:

cls.doSomething(cls.getSomething());

This compiles for me:这为我编译:

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)));
        }
    }
}

It makes clear the relationship between the map and the cls.它明确了 map 和 cls 之间的关系。

In the original context, because the type of the List is ICls<?> we can't get that relationship, but once we get a single ICls we can introduce a type variable T which allows us to express the relationship between getSomething and doSomething .在原始上下文中,因为 List 的类型是 ICls<?> 我们无法得到这种关系,但是一旦我们得到一个 ICls,我们就可以引入一个类型变量T ,它允许我们表达getSomethingdoSomething之间的关系。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM