作者:DilWilling | 来源:互联网 | 2023-02-03 10:59
我正在尝试编写一个通用的Java类,该类可用于反序列化/解析任何protobuf消息。
以下是代码在理想环境中的外观:
public abstract class ProtoDeserializer {
public T deserialize(final byte[] bytes) throws Exception {
Parser parser = T.getParserForType(); // Syntax Error: this method is not static!
T message = parser.parseFrom(bytes);
validate(message);
return message;
}
public abstract void validate(final T message) throws Exception;
}
但是,我无法获得通用protobuf消息的正确解析器。实现此类泛型类的正确方法是什么?
1> Jorn Vernee..:
最简单的方法是将解析器作为参数传递给构造函数:
public abstract class ProtoDeserializer {
private final Parser parser;
public ProtoDeserializer(Parser parser) {
this.parser = parser;
}
public T deserialize(final byte[] bytes) throws Exception {
T message = parser.parseFrom(bytes);
validate(message);
return message;
}
public abstract void validate(final T message) throws Exception;
}
通过解析器是我当前的解决方法。但是最好避免使用它,因为它是多余的信息。
这对您可能是多余的,但对编译器/运行时却不是多余的。
如果您认为可以创建类的原始实现:
ProtoDeserializer proto = new ProtoDeserializer() {
...
};
该类型T
必须来自某个地方。
这只是已删除的泛型的事实。如果需要通用参数的类型信息,则必须手动提供它。
另一个黑客可以尝试是从一个执行子类得到具体的类型参数:
private final Parser parser;
public ProtoDeserializer() {
Class> subclass = this.getClass();
try {
ParameterizedType pType = (ParameterizedType) subclass.getGenericSuperclass();
Class tClass = (Class) pType.getActualTypeArguments()[0];
// In the case where the constructor for `T` takes no arguments.
parser = tClass.newInstance().getParserForType();
} catch(Throwable t) {
throw new RuntimeException("Subclass not compatible", t);
}
}
只要子类直接ProtoDeserializer
使用具体的类型实参实现,此方法就可以工作。即:
class MyDeserializer extends ProtoDeserializer {...}