首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在Java消息分发程序中避免原始类型

在Java消息分发程序中避免原始类型
EN

Stack Overflow用户
提问于 2012-01-10 15:06:57
回答 3查看 1.7K关注 0票数 4

目标

我正在尝试构建一个MessageDispatcher,它将消息从第三方API转换为用户定义的消息,然后将它们分发给用户注册的侦听器。

预期用户将:

message.

  • Register

  • 为每种类型的用户定义一个接口,一个侦听器,每个消息类型的消息调度器。
  1. 将原始/第三方数据传递给传递给侦听器的消息。。

问题描述

不幸的是,我似乎无法避免使用原始类型来实现我想要的API。我在其他地方读到,没有使用原始类型的特殊情况,它们只存在于语言中是为了向后兼容。

有什么方法可以让下面的代码工作吗?还是需要重新设计我的API?

接口

MessageDispatcher实现了以下接口:

代码语言:javascript
复制
public interface MessageDispatcher {

    // Register a listener for a given user defined message type.
    public <T> void registerListener(
        Class<T> messageClass, 
        MessageListener<T> listener);

    // Receive data in 3rd party format, convert and dispatch.
    public void onData(Data data);

}

MessageListener接口定义为:

代码语言:javascript
复制
public interface MessageListener<T> {

    public void onMessage(T message);   

}

用户消息示例可能如下所示:

代码语言:javascript
复制
public interface MyMessage {

    public String getName();   

}

注册侦听器

用户可以按以下方式注册侦听器:

代码语言:javascript
复制
messageDispatcher.registerListener(MyMessage.class, 
    new MessageListener<MyMessage.class>() {
    @Override

   public void onMessage(MyMessage message) {
        System.out.println("Hello " + message.getName());
    }
}

标准消息分发程序可能实现如下方法:

代码语言:javascript
复制
private Map<Class<?>,MessageListener<?>> messageClassToListenerMap;

public <T> void registerListener(
    Class<T> messageClass, 
    MessageListener<T> listener) {

    messageClassToListenerMap.put(messageClass, listener);

    // SNIP: Process the messageClass and extract the information needed
    // for creating dynamic proxies elsewhere in a proxy factory.

}

调度消息

当MessageDispatcher接收到新消息时,它会为对象创建一个动态代理,并将其分派给适当的侦听器。但我的问题是:

代码语言:javascript
复制
public void onData(Data data) {

    // SNIP: Use proxy factory (not shown) to get message class and
    // dynamic proxy object appropriate to the 3rd party data.
    Class<?> messageClass;  // e.g. = MyMessage.class;
    Object dynamicProxy;    // e.g. = DynamicProxy for MyMessage.class;

    // TODO: How to I pick the appropriate MessageListener and dispatch the
    // dynamicProxy in a type safe way?  See below.

}

如果我尝试使用该类型,则无法分派数据:

代码语言:javascript
复制
// Assuming a listener has been registered for the example:
MessageListener<?> listener = messageClassToListenerMap.get(messageClass);

listener.onMessage(dynamicProxy); // ERROR: can't accept Object.
listener.onMessage(messageClass.cast(dynamicProxy); // ERROR: Wrong capture.

这是有意义的,因为我不可能知道我的侦听器接受哪种类型的数据,以及我传递它的数据类型。

但是,如果我使用原始类型,它可以很好地工作:

代码语言:javascript
复制
// Assuming a listener has been registered for the example:
MessageListener listener = messageClassToListenerMap.get(messageClass);  
listener.onMessage(dynamicProxy); // OK, provided I always pass the correct type of object.
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2012-01-11 02:58:49

您不需要使用原始类型--只需将通配符类型转换为您想要的类型。这是一种对类型安全的威胁。它会给出一个未经检查的广播警告,你可以忽略它。但它证明了不使用原始类型是可能的。

代码语言:javascript
复制
MessageListener<Object> listener = (MessageListener<Object>)messageClassToListenerMap.get(messageClass);

listener.onMessage(dynamicProxy);
票数 1
EN

Stack Overflow用户

发布于 2012-01-10 15:21:42

您不能在这里使用泛型,因为只有在运行时才知道确切的类型,因此必须使用不安全的强制转换。原始类型不检查类型,因此它可以工作。泛型只在编译时工作,调度程序在运行时工作。

因此,您应该显式地检查它:

代码语言:javascript
复制
MessageListener listener = messageClassToListenerMap.get(messageClass);  
if(!messageClass.isAssignableFrom(dynamicProxy.getClass()))
  throw new Something();
listener.onMessage(dynamicProxy);

我觉得设计不对。我建议你这样做:

代码语言:javascript
复制
interface MyMessageListener
{
  void onMessageA(String name);
  void onMessageB(String otherParam);
}

当您可以通过接口类和方法名称发送消息时。(您可以使用单一方法的接口,但不是很好的imho)。此外,Spring已经为其提供了基础设施:MethodInterceptorRemoteExporterRemoteInvocation和一些相关的基础设施。

票数 1
EN

Stack Overflow用户

发布于 2012-01-10 15:25:09

当我看到你的代码时,你为什么要为你的消息类使用代理.这个消息只是一个java来签署一个消息事件已经发生了,你只是告诉侦听器,有一个类型的消息已经发生了,你应该做一些事情来做一个侦听器的角色.这是信息的角色..。我不知道为什么会有代理消息,这太令人惊讶了.

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

https://stackoverflow.com/questions/8805428

复制
相关文章

相似问题

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