首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用于澄清不同子类型的Java泛型通配符

用于澄清不同子类型的Java泛型通配符
EN

Stack Overflow用户
提问于 2020-07-28 07:05:22
回答 1查看 120关注 0票数 1

我希望避免代码中的显式强制转换,这是我到目前为止所做的,但是编译器给了我一些错误,我不知道如何在没有强制转换的情况下修复它。

我有一个带有监听器映射的类,以及一些通知侦听器的方法:

代码语言:javascript
复制
public class MessageDispatcher {
    
     private final Map<String, List<ControllerMessageWatcher<? extends ControllerMessage>>> watchers;
     
     public void registerMessageWatcher(Class<? extends ControllerMessage> classToWatch, final ControllerMessageWatcher<?> controllerMessageWatcher) {
        this.watchers.computeIfAbsent(classToWatch.getSimpleName(), k -> new ArrayList<>()).add(controllerMessageWatcher);
    }

     public synchronized void receive(StatusMessage statusMessage) {
         List<ControllerMessageWatcher<?>> watchers = this.watchers.get(statusMessage.getClass().getSimpleName());
         if (watchers != null)
             watchers.forEach(controllerMessageWatcher -> controllerMessageWatcher.newMessage(statusMessage)); 
               // Required type: capture of ?      Provided:  StatusMessage <-- error here!   ^^^^
     }

     public synchronized void receive(UpdateDBMessage updateDBMessage) {
        List<ControllerMessageWatcher<?>> watchers = this.watchers.get(updateDBMessage.getClass().getSimpleName());
        if (watchers != null)
            watchers.forEach(controllerMessageWatcher -> controllerMessageWatcher.newMessage(updateDBMessage));
               // Required type: capture of ?      Provided:  UpdateDBMessage <-- error here!   ^^^^
     }
}

这是侦听器的接口:

代码语言:javascript
复制
public interface ControllerMessageWatcher<T extends ControllerMessage> {

    void newMessage(T message);
}

这就是我希望使用的监听器的实现,避免抛出:

代码语言:javascript
复制
public class Status implements ControllerMessageWatcher<StatusMessage> {
    @Override
    public void newMessage(StatusMessage message) {
        ...
    }

}

所有工作,但接收的方法,这会产生错误(或未经检查的警告,如果我删除通配符)。

我想要实现的是避免在每个newMessage方法中进行显式强制转换(如果删除所有泛型部分,我就必须这样做)。

在从newMessage方法调用MessageDispatcher.receive()时避免错误/警告(现在有)(请参阅该方法中的注释)

这是ControllerMessageStatusMessageUpdateDBMessage

代码语言:javascript
复制
public abstract class ControllerMessage {

    private String messageId;

//    ...  getter setter
}
代码语言:javascript
复制
public class StatusMessage extends ControllerMessage{

    private String aField;

//    ...  getter setter
}
代码语言:javascript
复制
public class UpdateDBMessage extends ControllerMessage{

    private String aField;

//    ...  getter setter
}
EN

回答 1

Stack Overflow用户

发布于 2020-07-28 10:13:19

我认为你的设计是从根本上破坏的,因为你使用了反思。

代码语言:javascript
复制
public void registerMessageWatcher(
    Class<? extends ControllerMessage> classToWatch, 
    final ControllerMessageWatcher<?> controllerMessageWatcher
)

在API级别上,这一步使编译器无法管理继承。

一个小的改进将是使类型一致。

代码语言:javascript
复制
public <T extends ControllerMessage> void registerMessageWatcher(
    Class<T> classToWatch, 
    final ControllerMessageWatcher<T> controllerMessageWatcher
)

现在,我们正在跟踪我们的类类型,无论是好是坏,但我们仍然需要种姓,以保持在地图上的类。

代码语言:javascript
复制
private final Map<Class<?>, List<ControllerMessageWatcher<?>>> watchers;

List<ControllerMessageWatcher<T>> getWatchers( Class<T> clazz ){
    return (List<ControllerMessageWatcher<T>>)watchers.get(clazz);
}

为了避免铸造,我会

代码语言:javascript
复制
public interface ControllerMessageWatcher<T extends ControllerMessage> {
    void newMessage(ControllerMessage message);
}

我不知道你和你的观察者在做什么,这会有新的信息来区分类型。这样你就可以拥有。

代码语言:javascript
复制
List<ControllerMessageWatcher<? extends ControllerMessage>> watchers;
watchers.forEach( w -> w.newMessage( message ) );

然后用接口替换抽象类。

代码语言:javascript
复制
interface ControllerMessage{
    String getMessageId();
    String getAField();
}

现在由特定的观察人员来获取相关信息。还可以为不相关的字段创建默认方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63128708

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档