Java:消息系统需要能够传递各种对象

时间:2016-01-10 21:27:32

标签: java messaging

我正在编写一个消息传递系统来为我的程序执行队列操作。我需要能够通过消息传递各种对象。我目前有一个Msg对象接受(Action枚举,Data<?>...对象)。 Data对象旨在成为我可能传递的任何对象的包装器。

目前Data对象使用此代码,使用泛型:

public class Data<T> {

    private T data;

        public Data(T data){
        this.data = data;
    }

    public T getData(){
        return data;
    }

}

Msg对象采用Data<?>...类型,因此Msg有一个Data<?>[]字段。

如果getData()对象上调用Data<?>,则返回Object类型。显然不理想。

我需要能够传递Image个对象以及String个对象。我确定有更好的传递任意数据的方式。

2 个答案:

答案 0 :(得分:0)

如果你调用getData()。getClass(),你将获得传递的类或类型,这在我看来与Object不同。您可能不知道自己得到了什么,但是您可以找到或定义可能传递的所有内容的公共接口。例如,您可以在传递的任何内容上调用toString()或getClass()。你的问题是你传递了任何可以想象的对象,所以我的问题是你要用它做什么?如果要将其序列化到数据库中,则不需要知道它的类型,否则可以测试它或调用公共接口。

public class PlayData {
    class Msg {
        private List<Data<?>> message = new ArrayList<Data<?>>();
        public void addData(Data<?> datum) { message.add(datum); }
        public void printTypes() { for ( Data<?> datum: message ) { System.out.println(datum.getData().getClass()); } }
    }
    class Data<T> {
        private T value;
        public Data(T value) { this.value = value; }
        public T getData() { return value; }
    }
    class Listener {
        public void receive(Msg msg) { msg.printTypes(); }
    }
    class Sender {
        private Listener listener;
        public Sender(Listener listener) { this.listener = listener; }
        public void send(Msg msg) { listener.receive(msg); }
    }
    class MyPacket {
        int i;
        public MyPacket(int i) { this.i = i; }
    }
    public static void main(String[] args) throws Exception { new PlayData().run(); }
    public void run() throws Exception {
        Sender sender = new Sender(new Listener());
        Msg msg = new Msg();
        msg.addData(new Data<String>("testing") );
        msg.addData(new Data<MyPacket>(new MyPacket(42)) );
        sender.send(msg);
    }
}

答案 1 :(得分:0)

你遇到麻烦的原因是你试图让Java的静态类型系统做一些它不能做的事情。从Data<T>转换为Data<?>后,无论T是什么,都会丢失。没有干净的方法让它回来。

让它发挥作用的最快方式(从现在开始)就是开始在任何地方投掷演员阵容,如下所示:

Data<?> d = new Data("Hello");
String contents = (String)d.getData();

这是一个很糟糕的主意,所以让我们回到绘图板。

如果(理想情况下),您拥有提前所需的所有类型(即每个Data String或{{1}或者Image),那么你可以很容易地(虽然它有点乏味)定义一个 Sum类型(如果你来自的话,也就是 union C)您必须处理的不同类型的数据。作为类不变量,我们假设正好一个字段为非null,其余为null。对于此示例,我假设它可以是IntegerStringImage,但是根据需要添加或删除Integer中的类型相当简单

Data

一个必要的副作用是我们无法在不引起异常行为的情况下包裹public class Data { private Image imgData; private String stringData; private Integer intData; public Data(Image img) { this.imgData = img; } public Data(String stringData) { this.stringData = stringData; } public Data(Integer intData) { this.intData = intData; } public boolean isImage() { return imageData != null; } public boolean isInteger() { return intData != null; } public boolean isString() { return stringData != null; } public Image asImage() { if(! isImage()) throw new RuntimeException(); return imgData; } public Image asString() { if(! isString()) throw new RuntimeException(); return stringData; } public Image asInt() { if(! isInt()) throw new RuntimeException(); return intData; } } 。这是期望的,修改类以允许它是不太困难的。

使用这个null类,可以很容易地用Data逻辑来解析它。

if-else