我正在编写一个消息传递系统来为我的程序执行队列操作。我需要能够通过消息传递各种对象。我目前有一个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
个对象。我确定有更好的传递任意数据的方式。
答案 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。对于此示例,我假设它可以是Integer
,String
或Image
,但是根据需要添加或删除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