我正在编写通用编码器/解码器并遇到扩展通用的问题。这个想法 是我想要一个抽象的Encodeable类,它具有一个“虚拟”静态方法解码,它接受一个Byte []并构造该对象,类似于Serializable。 (我知道这不能在java中完成。)每个扩展Encodeable的类都会覆盖 编码/解码方法。然后我想一般使用这些Encodeable的子类。这是试图表明我的意思:
public class Encodeable{
// I'd like to write
// static abstract Encodeable decode(Byte[]);
// similar to
// virtual Encodeable decode(Byte[]) = 0;
// in C++, but that seems to be illegal in java
static Encodeable decode(Byte[] buf){return null};
}
public class EncodeableFoo extends Encodeable{
static EncodeableFoo decode(Byte[] buf){
// do actual decoding logic here
}
}
public class Bar<T extends Encodeable>{
public void messageReceived(MessageEvent e){
Byte[] buf = e.getMessage();
T messageObj = T.decode(buf);
// do something with T
}
}
按原样,我收到一条错误消息,如
error: incompatible types
T messageObj = T.decode(objBuf);
^
required: T
found: Encodeable
where T is a type-variable:
T extends Encodeable declared in class EdgeClientHandler
在编译时。但是,如果我将解码线更改为
T messageObj = (T) T.decode(objBuf);
它运作得很好。有人可以向我解释这个黑魔法吗?或者,更重要的是,给我一个更好的方法来编写我的通用Bar类,以便它知道T有静态方法解码(以及非静态方法编码)?
答案 0 :(得分:6)
First, static methods in Java cannot be abstract.
其次,如果您希望编译器了解您正在返回T
而不仅仅是Encodeable
,则需要将该方法声明为通用方法。我建议完全远离static
。基本理念:
public interface Decoder<T> {
T decode(Byte[] buf);
}
public class FooDecoder implements Decoder<Foo> {
Foo decode(Byte[] buf){
// do actual decoding logic here
}
}
public class Bar<T extends Encodeable> {
private Decoder<T> decoder; // you'll have to figure out where to get this
public void messageReceived(MessageEvent e){
Byte[] buf = e.getMessage();
T messageObj = decoder.decode(buf);
// do something with T
}
}
您的原始设置似乎混合了可编码的类型以及知道如何从byte[]
解码此类类型的内容,因此我重新命名并摆弄了一些。
附带问题:为什么Byte[]
代替byte[]
s?
答案 1 :(得分:3)
你的设计对我来说有点乱。我不会使用静态方法而是做这样的事情:
public interface Decoder<T extends Encodable> {
T decode(Byte[] buf);
}
public class Bar<T extends Encodable> {
private final Decoder<T> decoder;
public Bar(Decoder<T> decoder) {
this.decoder = decoder;
}
public void messageReceived(MessageEvent e) {
Byte[] buf = e.getMessage();
T messageObj = decoder.decode(buf);
// do something with T
}
}