Simplest is to pass the parser as an argument to the constructor:
public abstract class ProtoDeserializer<T extends Message> {
private final Parser<T> parser;
public ProtoDeserializer(Parser<T> 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;
}
Passing the parser is my current workaround. But it would be nice to avoid it, because it's redundant information.
It may be redundant to you, but it is not redundant to the compiler/runtime.
If you consider that it is possible to create raw implementation of your class:
ProtoDeserializer proto = new ProtoDeserializer() {
...
};
The type T
would have to come from somewhere.
This is just the reality of erased generics. If you need type information of a generic parameter, you will have to manually supply it.
Another hack you can try is to get the concrete type parameter from an implementing sub class:
private final Parser<T> parser;
public ProtoDeserializer() {
Class<?> subclass = this.getClass();
try {
ParameterizedType pType = (ParameterizedType) subclass.getGenericSuperclass();
Class<T> tClass = (Class<T>) 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);
}
}
This would work as long as the subclass directly implements ProtoDeserializer
with a concrete type argument. i.e.:
class MyDeserializer extends ProtoDeserializer<MyMessage> {...}
getParserForType
is notstatic
, how do you call it? Do you instantiateT
? – GermgetParserForType
to know if it would work. – GermT request; request.getParserForType()
– Fixationstatic
method. How is this supposed to work? It doesn’t work, even without Generics involved… – CosmonautSyntax Error
in the comment and the reason why it does not work. This code snippet is just here to explain what I want to do. Not how it should be done (that's what I'm asking for). A piece of code tells more than a thousand words. – Fixationstatic
method without a receiver instance. Otherwise, you could claim that “in a perfect world”, you could typeeōzxvņrökwzℝiaklwo
and the code would do whatever you want. – CosmonautgetParserForType()
method return the rightParser<T>
every time, regardless of whatT
is? There is still no difference to claiming that “in a perfect world”,eōzxvņrökwzℝiaklwo
would do whatever you want. Anyway, it’s not worth to continue this discussion. – Cosmonaut